1. Precautions

In the Add HMS API scenario, please refer to all sections to complete the conversion.

In the To HMS API scenario, you only need to refer to sections 1.1 Preparations, 1.2 gradle File Configuration and 7 setMapStyle(). If discarded APIs are used, please also refer to 6. Substitute Solutions for Certain Discarded APIs.

After the conversion is complete, synchronize the project, reload the dependencies, and ensure that the new dependencies are downloaded.

1.1 Preparations

  1. Configuring App Information in AppGallery Connect

  2. Integrating the HMS SDK

  3. Configuring Obfuscation Scripts

  4. Applying for Permissions

1.2 gradle File Configuration

  1. compileSdkVersion 29
  2. buildToolsVersion '29.0.2'
  3. defaultConfig {
  4.     minSdkVersion 19
  5.     targetSdkVersion 29
  6. }
  1. implementation 'androidx.appcompat:appcompat:1.1.0'
  2. implementation 'androidx.recyclerview:recyclerview:1.1.0'
  1. public class CameraDemoActivity extends androidx.appcompat.app.AppCompatActivity
  1. implementation 'com.google.android.gms:play-services-base:17.1.0'
  2. implementation 'com.google.android.gms:play-services-basement:17.1.0'
  1. compileOptions {sourceCompatibility = 1.8    targetCompatibility = 1.8}

1.3 Conversion from switch-case to if-else

After the conversion is complete, case expressions must be constant expression is displayed for some statements selected using switch-case. The case in switch must be an exception expressed in a constant. This method needs to be converted to the if-else format to resolve the switch exception.

Original sample code:

  1. switch (reason) {
  2.     case OnCameraMoveStartedListener.REASON_GESTURE:
  3.         currPolylineOptions.color(Color.BLUE);
  4.         reasonText = "GESTURE";
  5.         break;
  6.     case OnCameraMoveStartedListener.REASON_API_ANIMATION:
  7.         currPolylineOptions.color(Color.RED);
  8.         reasonText = "API_ANIMATION";
  9.         break;
  10.     case OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION:
  11.         currPolylineOptions.color(Color.GREEN);
  12.         reasonText = "DEVELOPER_ANIMATION";
  13.         break;
  14. }

Modified sample code:

  1. if (OnCameraMoveStartedListener.getREASON_GESTURE() == reason) {
  2.     this.currPolylineOptions.color(Color.BLUE);
  3.     reasonText = "GESTURE";
  4. } else if (OnCameraMoveStartedListener.getREASON_API_ANIMATION() == reason) {
  5.     this.currPolylineOptions.color(Color.RED);
  6.     reasonText = "API_ANIMATION";
  7. } else if (OnCameraMoveStartedListener.getREASON_DEVELOPER_ANIMATION() == reason) {
  8.     this.currPolylineOptions.color(Color.GREEN);
  9.     reasonText = "DEVELOPER_ANIMATION";
  10. } else {
  11.     reasonText = "UNKNOWN_REASON";
  12. }

2. fragment

After the Add HMS API conversion is complete, you can configure the classloader (simple, only resource import and configuration file modification are required) or manually write code (complex, heavy manual conversion workload) to implement the compatibility of Google APIs and HMS for activity displayed in fragment.

Configuring the Classloader (Beta)

Currently, the classloader mode does not support Add HMS API conversion in Generate code for creating app dependent only on GMS SDK mode. Do not select it when using the tool for conversion.

1. Decompress the package and cut the resource files.

    a. Decompress the fragment-support.zip package in the project-level directory xmsadapter/src/main/java.

    b. Move the scripts, src, xh, and xg folders to the xmsadapter folder.

2. Modify the project-related configuration files.

    a. Add the following reference to the settings.gradle file in the project-level directory:

  1. include ':xmsadapter:xh', ':xmsadapter:xg'

    b. In the dependencies {} area of the build.gradle file in the project-level directory, set the Gradle plug-in version to 3.5.0 or later.

  1.    buildscript {
  2.        dependencies {
  3.            classpath 'com.android.tools.build:gradle:3.5.0'
  4.        }
  5.    }

    c. In the gradle/wrapper/gradle-wrapper.properties file in the project-level directory, set the Gradle version to 5.4.1 or later.

  1. distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

    d. In the build.gradle file in the app-level directory, set minSdkVersion to 24 or later and add the following dependency in the dependencies {} area:

  1.    android {
  2.        defaultConfig {
  3.            minSdkVersion 24
  4.        }
  5.    }
  6.    dependencies {
  7.        compileOnly project(':xmsadapter:xh')
  8.        compileOnly project(':xmsadapter:xg')
  9.    }

    e. Add the following reference to the xmsadapter/build.gradle file in the project-level directory:

  1. apply from: 'scripts/copy-dex.gradle'

3. Change the fragment-related package names.

In Android Studio, choose Edit > Find > Replace in Path, select the Module and app filters (as shown in the red boxes in the following figure), replace com.google.android.gms.maps with org.xms.g.maps, and click Replace All.

4. Call the init method at the program entry to initialize the program.

    a. Implement a program entry class that inherits android.app.Application in the app and overwrite the onCreate method in the class.

  1. public class MyApp extends Application {
  2.    @Override
  3.    public void onCreate() {
  4.        super.onCreate();
  5.        GlobalEnvSetting.init(this,null);
  6.        XMS.init(this);
  7.    }
  8. }

    b. Modify the application name attribute in the src/main/AndroidManifest.xml file in the app-level directory and add the new application subclass in the first entry.

  1. <application
  2.    android:name=".MyApp"
  3. </application>

5.Configure the obfuscation rule for the packaged app version for release.

    a.If the obfuscation optimization parameter of the proguard tool is enabled when your app is packaged into a version for release, check whether thebuild.gradlefile of the app contains the following content. If yes, the obfuscation optimization parameter is enabled. In this case, go to step b. Otherwise, skip this step.

  1. android {
  2. buildTypes {
  3.  release {
  4.   minifyEnabled true
  5.   proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  6.  }
  7. }
  8. }

    b.To prevent the proguard tool from incorrectly obfuscating or removing fragment-related code, configure the following obfuscation filtering rules in theproguard-rules.profile in the app-level directory:

  1. -keep class * extends androidx.fragment.app.Fragment{*;}
  2. -keep class org.xms.g.maps.ExtensionMapOptions{*;}
  3. -keep class com.huawei.hms.maps.HuaweiMapOptions{*;}
  4. -keep class com.google.android.gms.maps.GoogleMapOptions{*;}
  5. -keep interface org.xms.g.maps.OnMapReadyCallback{*;}
  6. -keep interface com.huawei.hms.maps.OnMapReadyCallback{*;}
  7. -keep interface com.google.android.gms.maps.OnMapReadyCallback{*;}
  8. -keep class org.xms.g.maps.StreetViewPanoramaOptions{*;}
  9. -keep class com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback{*;}
  10. -keep class com.huawei.hms.maps.OnStreetViewPanoramaReadyCallback{*;}
  11. -keep interface org.xms.g.maps.OnStreetViewPanoramaReadyCallback{*;}
  12. -keep interface com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback{*;}
  13. -keep interface com.huawei.hms.maps.OnStreetViewPanoramaReadyCallback{*;}
  14. -keep class com.huawei.hms.dynamicloader.** { *; }
  15. -keep class com.huawei.hms.feature.dynamic.** {*;}
  16. -keep class com.huawei.hms.feature.** { *;}

6.Handle the exception.

    It is recommended that you do not rescan a project.

    If a rescanning is performed, you will see the message shown in the following figure. In this case, back up and remove the xh and xg folders from the xmsadapter folder. After the rescanning is complete, restore the backup to the xmsadapter folder.

Manually Writing Code

1. Modify the layout resource file.

In the Add HMS API scenario, Google APIs and HMS need to use independent layout resource files. The <fragment/>class paths in the resource files are different.

Reference for the fragment definition in the HMS layout resource file:

  1. <fragment
  2.     android:id="@+id/map"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     class="com.huawei.hms.maps.SupportMapFragment" />

Reference for the fragment definition in the Google API layout resource file:

  1. <fragment
  2.     android:id="@+id/map"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     class="com.google.android.gms.maps.SupportMapFragment" />

Resource file reference:

basic_demo: original layout resource file

basic_demo_hms: layout resource file of HMS

Each layout resource file must be in duplicate, one for HMS and the other for Google APIs. The files are used together with the code for compatible redirection.

2. Modify the code.

If fragment is used, you can use if-else in the onCreate() method of activity to make a copy of the code compatible with both HMS and Google APIs. The modification method is as follows:

Original sample code:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.     super.onCreate(savedInstanceState);
  3.     setContentView(R.layout.events_demo);
  4.     mTapTextView = (TextView) findViewById(R.id.tap_text);
  5.     mCameraTextView = (TextView) findViewById(R.id.camera_text);
  6.     SupportMapFragment mapFragment =
  7.             (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
  8.     mapFragment.getMapAsync(this);
  9. }

Modified sample code:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.     super.onCreate(savedInstanceState);
  3.         //Create according to G or H based on the current type.
  4.     if (org.xms.g.utils.GlobalEnvSetting.isHms()) {
  5.         createAsH();
  6.     } else {
  7.         createAsG();
  8.     }
  9. }
  10. /**
  11. * HMS creation process
  12.  */
  13. private void createAsH() {
  14.     Log.d(TAG, "create as hms");
  15.                 // Set the HMS resource file.
  16.     setContentView(R.layout.events_demo_hms);
  17.                 // Initialize parameters.
  18.     initMember();
  19.                // Obtain the HMS fragment based on the ID.
  20.     com.huawei.hms.maps.SupportMapFragment hMapFragment =
  21.             (com.huawei.hms.maps.SupportMapFragment) this.getSupportFragmentManager().findFragmentById(R.id.map);
  22.                 // Load a map.
  23.     hMapFragment.getMapAsync(this.getHInstanceOnMapReadyCallback());
  24. }
  25. /**
  26. * GMS creation process
  27.  */
  28. private void createAsG() {
  29.     Log.d(TAG, "create as gms");
  30.                  // Set the GMS resource file.
  31.     setContentView(R.layout.events_demo);
  32.               // Initialize parameters.
  33.     initMember();
  34.              // Obtain the GMS fragment based on the ID.
  35.     com.google.android.gms.maps.SupportMapFragment gMapFragment =
  36.             (com.google.android.gms.maps.SupportMapFragment) this.getSupportFragmentManager()
  37.                     .findFragmentById(R.id.map);
  38.                 // Load a map.
  39.     gMapFragment.getMapAsync(this.getGInstanceOnMapReadyCallback());
  40. }
  41. /**
  42. * Initialize member variables and extract them into independent methods.
  43.  */
  44. private void initMember() {
  45.     this.mTapTextView = (TextView) findViewById(R.id.tap_text);
  46.     this.mCameraTextView = (TextView) findViewById(R.id.camera_text);
  47. }

Specify Google APIs or HMS to load map resources based on isHms in the current environment variable. The options are as follows:

  1. void initMember(): initialization position of private member variables and code that can be shared.
  2. void createAsG(): Google API creation process.
  3. void createAsH(): HMS creation process.

3. Map Constants

After the conversion is complete, please refer to the following table if an exception occurs in the reference of constants. In GoogleMap, constants are directly used. However, in the Add HMS API scenario, constants are used in Getter mode. For example:

For BitmapDescriptorFactory.HUE_ORANGE, the new method is to use BitmapDescriptorFactory.getHUE_ORANGE() in Getter mode.

Getting googleMap Constants

Getting Add HMS API Constants

import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID. (directly used after reference)

ExtensionMap.getMAP_TYPE_NORMAL()

BitmapDescriptorFactory.HUE_ORANGE

BitmapDescriptorFactory.getHUE_ORANGE();

HuaweiMap.OnCameraMoveStartedListener.REASON_API_ANIMATION

HuaweiMap.OnCameraMoveStartedListener.getREASON_API_ANIMATION()


Getting googleMap Constants

Getting To HMS API Constants

import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID. (directly used after reference)

import static com.huawei.hms.maps.HuaweiMap.MAP_TYPE_HYBRID. (directly used after reference)

4. Special Fragment Scenarios (OnMapAndViewReadyListener)

Some demos such as Marker implement the OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener API. The Fragment used supports conversion in the OnMapAndViewReadyListener class in the Add HMS API scenario. The modification is as follows.

l   Modify the constructor. The parameter type of the constructor mapFragment needs to be converted from SupportMapFragment to the parent class Fragment.

  1. public OnMapAndViewReadyListener(
  2.         Fragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) {}

l   The sample code for OnMapAndViewReadyListener compatible with Google APIs and HMS is as follows:

  1. public class OnMapAndViewReadyListener implements OnGlobalLayoutListener, OnMapReadyCallback {
  2.     /**
  3.      * A listener that needs to wait for both the GoogleMap and the View to be initialized.
  4.      */
  5.     public interface OnGlobalLayoutAndMapReadyListener {
  6.         void onMapReady(ExtensionMap googleMap);
  7.     }
  8.     private final View mapView;
  9.     private final OnGlobalLayoutAndMapReadyListener devCallback;
  10.     private boolean isViewReady;
  11.     private boolean isMapReady;
  12.     private ExtensionMap googleMap;
  13.     public OnMapAndViewReadyListener(
  14.             Fragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) {
  15.        // HMS processing
  16.         if (org.xms.g.utils.GlobalEnvSetting.isHms()) {
  17.             com.huawei.hms.maps.SupportMapFragment hMapFragment = (com.huawei.hms.maps.SupportMapFragment) mapFragment;
  18.             mapView = mapFragment.getView();
  19.             this.devCallback = devCallback;
  20.             registerListeners();
  21.             // GoogleMap. Note if the GoogleMap is already ready it will still fire the callback later.
  22.             hMapFragment.getMapAsync(this.getHInstanceOnMapReadyCallback());
  23.         } else {
  24.              // GMS processing
  25.             com.google.android.gms.maps.SupportMapFragment gMapFragment = (com.google.android.gms.maps.SupportMapFragment) mapFragment;
  26.             mapView = mapFragment.getView();
  27.             this.devCallback = devCallback;
  28.             registerListeners();
  29.             // GoogleMap. Note if the GoogleMap is already ready it will still fire the callback later.
  30.             gMapFragment.getMapAsync(this.getGInstanceOnMapReadyCallback());
  31.         }
  32.     }
  33.     private void registerListeners() {
  34.         isViewReady = false;
  35.         isMapReady = false;
  36.         googleMap = null;
  37.         // View layout.
  38.         if ((mapView.getWidth() != 0) && (mapView.getHeight() != 0)) {
  39.             // View has already completed layout.
  40.             isViewReady = true;
  41.         } else {
  42.             // Map has not undergone layout, register a View observer.
  43.             mapView.getViewTreeObserver().addOnGlobalLayoutListener(this);
  44.         }
  45.     }
  46.     @Override
  47.     public void onMapReady(ExtensionMap googleMap) {
  48.         // NOTE: The GoogleMap API specifies the listener is removed just prior to invocation.
  49.         this.googleMap = googleMap;
  50.         isMapReady = true;
  51.         fireCallbackIfReady();
  52.     }
  53.     @SuppressWarnings("deprecation")  // We use the new method when supported
  54.     @SuppressLint("NewApi")  // We check which build version we are using.
  55.     @Override
  56.     public void onGlobalLayout() {
  57.         // Remove our listener.
  58.         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
  59.             mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
  60.         } else {
  61.             mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
  62.         }
  63.         isViewReady = true;
  64.         fireCallbackIfReady();
  65.     }
  66.     private void fireCallbackIfReady() {
  67.         if (isViewReady && isMapReady) {
  68.             devCallback.onMapReady(googleMap);
  69.         }
  70.     }
  71. }

 

l   In the Add HMS API scenario, the sample code of onCreate() modification for activity to call OnMapAndViewReadyListener is as follows:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3.     super.onCreate(savedInstanceState);
  4.     if (org.xms.g.utils.GlobalEnvSetting.isHms()) {
  5.         createAsH();
  6.     } else {
  7.         createAsG();
  8.     }
  9. }
  10. private void createAsH() {
  11.     Log.d(TAG, "create as hms");
  12.     setContentView(R.layout.marker_demo_hms);
  13.     initMember();
  14.     com.huawei.hms.maps.SupportMapFragment hMapFragment = (com.huawei.hms.maps.SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
  15.     new OnMapAndViewReadyListener(hMapFragment, this);
  16. }
  17. private void createAsG() {
  18.     Log.d(TAG, "create as gms");
  19.     setContentView(R.layout.marker_demo);
  20.     initMember();
  21.     com.google.android.gms.maps.SupportMapFragment hMapFragment = (com.google.android.gms.maps.SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
  22.     new OnMapAndViewReadyListener(hMapFragment, this);
  23. }
  24. private void initMember() {
  25.     this.mTopText = (TextView) findViewById(R.id.top_text);
  26.     this.mRotationBar = (SeekBar) findViewById(R.id.rotationSeekBar);
  27.     this.mRotationBar.setMax(360);
  28.     this.mRotationBar.setOnSeekBarChangeListener(this);
  29.     this.mFlatBox = (CheckBox) findViewById(R.id.flat);
  30.     this.mOptions = (RadioGroup) findViewById(R.id.custom_info_window_options);
  31.     this.mOptions.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  32.         @Override
  33.         public void onCheckedChanged(RadioGroup group, int checkedId) {
  34.             if (MarkerDemoActivity.this.mLastSelectedMarker != null && MarkerDemoActivity.this.mLastSelectedMarker.isInfoWindowShown()) {
  35.                 // Refresh the info window when the info window's content has changed.
  36.                 MarkerDemoActivity.this.mLastSelectedMarker.showInfoWindow();
  37.             }
  38.         }
  39.     });
  40. }

 

5. streetViewPanoramaFragment

In the Add HMS API scenario, the call method of fragment is slightly different from that of streeViewPanoramaFragment compared with 2. fragment. However, the basic approach is to perform if-else processing based on the system type. The reference is as follows.

l   Sample code of modifying onCreate in activity

Original code:

  1. protected void onCreate(final Bundle savedInstanceState) {
  2.     super.onCreate(savedInstanceState);
  3.     setContentView(R.layout.street_view_panorama_basic_demo);
  4.     SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
  5.             (SupportStreetViewPanoramaFragment)
  6.                     getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
  7.     streetViewPanoramaFragment.getStreetViewPanoramaAsync(
  8.             new OnStreetViewPanoramaReadyCallback() {
  9.                 @Override
  10.                 public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
  11.                     // Only set the panorama to SYDNEY on startup (when no panoramas have been
  12.                     // loaded which is when the savedInstanceState is null).
  13.                     if (savedInstanceState == null) {
  14.                         panorama.setPosition(SYDNEY);
  15.                     }
  16.                 }
  17.             });
  18. }

Modified sample code:

  1. @Override
  2. protected void onCreate(final Bundle savedInstanceState) {
  3.     super.onCreate(savedInstanceState);
  4.     if (org.xms.g.utils.GlobalEnvSetting.isHms()) {
  5.         createAsH(savedInstanceState);
  6.     } else {
  7.         createAsG(savedInstanceState);
  8.     }
  9. }
  10. private void createAsH(final Bundle savedInstanceState) {
  11.     Log.d(TAG, "create as hms");
  12.     setContentView(R.layout.street_view_panorama_basic_demo_hms);
  13.     initMember();
  14.     com.huawei.hms.maps.SupportStreetViewPanoramaFragment hStreetViewPanoramaFragment =
  15.             (com.huawei.hms.maps.SupportStreetViewPanoramaFragment) getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
  16.     hStreetViewPanoramaFragment.getStreetViewPanoramaAsync(panorama -> {
  17.         // Only set the panorama to SYDNEY on startup (when no panoramas have been
  18.         // loaded which is when the savedInstanceState is null).
  19.       // Convert to org.xms for HMS.
  20.         org.xms.g.maps.StreetViewPanorama xmsStreetViewPanorama =
  21.                 new org.xms.g.maps.StreetViewPanorama(null, panorama);
  22.         if (savedInstanceState == null) {
  23.             xmsStreetViewPanorama.setPosition(SYDNEY);
  24.         }
  25.     });
  26. }
  27. private void createAsG(final Bundle savedInstanceState) {
  28.     Log.d(TAG, "create as gms");
  29.     setContentView(R.layout.street_view_panorama_basic_demo);
  30.     initMember();
  31.     com.google.android.gms.maps.SupportStreetViewPanoramaFragment gStreetViewPanoramaFragment =
  32.             (com.google.android.gms.maps.SupportStreetViewPanoramaFragment) getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
  33.     gStreetViewPanoramaFragment.getStreetViewPanoramaAsync(panorama -> {
  34.         // Only set the panorama to SYDNEY on startup (when no panoramas have been
  35.         // loaded which is when the savedInstanceState is null).
  36.       // Convert to org.xms for HMS.
  37.         org.xms.g.maps.StreetViewPanorama xmsStreetViewPanorama =
  38.                 new org.xms.g.maps.StreetViewPanorama(panorama, null);
  39.         if (savedInstanceState == null) {
  40.             xmsStreetViewPanorama.setPosition(SYDNEY);
  41.         }
  42.     });
  43. }
  44. private void initMember() {
  45. }

For details about how to call streeViewPanoramaFragment, please refer to the sample code to make adjustment.

6. Substitute Solutions for Certain Discarded APIs

If Location Kit APIs are used in the To HMS API scenario, the Location dependency needs to be added. For details about the version number in ${version, please refer to Version Change History of Location Kit.

  1. implementation 'com.huawei.hms:location:${version}'

To use the Location function, ensure that you have obtained the location permission.

Sample code for obtaining the location permission:

  1. /**
  2. * only have permission of location, location function is enable
  3. **/
  4. if(enableMyLocation()){
  5.    getMyLocation();
  6.    setOnMyLocationChangeListener();
  7. }
  8. /**
  9. * Request code for location permission request.
  10. *
  11. * @see #onRequestPermissionsResult(int, String[], int[])
  12. */
  13. private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
  14. /**
  15. * Enables the My Location layer if the fine location permission has been granted.
  16. */
  17. private boolean enableMyLocation() {
  18.    if (ContextCompat.checkSelfPermission(this,
  19.            Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
  20.        // Permission to access the location is missing.
  21.        PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
  22.                Manifest.permission.ACCESS_FINE_LOCATION, true);
  23.         return false;
  24.    }else {
  25.        return true;
  26.    }
  27. }

6.1 HuaweiMap.getMyLocation()

This API can be replaced by the FusedLocationProviderClient.getLastLocation() method of HUAWEI Location Kit. For details about the API function, please refer to the getLastLocation() method in the References of HUAWEI Location Kit.

To HMS API sample code:

  1. // Current position.
  2. private  android.location.Location myLocation;
  3. /**
  4. * this is an Example:
  5. * using location kit getLastLocation ,replace HuaweiMap.getMylocation() function
  6. */
  7. private void getMyLocation(){
  8.    com.huawei.hmf.tasks.Task<android.location.Location> locationTask =  LocationServices
  9.            .getFusedLocationProviderClient(this).getLastLocation();
  10.    locationTask.addOnCompleteListener(param0 -> {
  11.       if (locationTask != null) {
  12.            myLocation = locationTask.getResult();
  13.            double Lat = myLocation.getLatitude();
  14.            double Lng = myLocation.getLongitude();
  15.            Log.d(TAG, " Lat is : " + Lat +", Lng is : "+Lng);
  16.        }
  17.    }).addOnFailureListener(param0 -> Log.d(TAG,"lastLocation is error"));
  18. }

Add HMS API sample code:

  1. //current location
  2. private  android.location.Location myLocation;
  3. /**
  4. * this is an Example:
  5. * using location kit getLastLocation ,replace HuaweiMap.getMylocation() function
  6. */
  7. private void getMyLocation(){
  8.   org.xms.g.tasks.Task<android.location.Location> locationTask =  LocationServices
  9.           .getFusedLocationProviderClient(this).getLastLocation();
  10.   locationTask.addOnCompleteListener(param0 -> {
  11.       if (locationTask != null) {
  12.           myLocation = locationTask.getResult();
  13.           double Lat = myLocation.getLatitude();
  14.           double Lng = myLocation.getLongitude();
  15.           Log.d(TAG, " Lat is : " + Lat +", Lng is : "+Lng);
  16.       }
  17.    }).addOnFailureListener(param0 -> Log.d(TAG,"lastLocation is error"));
  18. }

6.2 HuaweiMap.setOnMyLocationListener()

This API can be replaced by the FusedLocationProviderClient.requestLocationUpdates(LocationRequest request,LocationCallback callback,Looper looper) method of HUAWEI Location Kit. For the API description, please refer to FusedLocationProviderClient.

To HMS API sample code:

  1. /**
  2. * this is an Example
  3. * using location kit requestLocationUpdates(Request,LocationCallback,Looper) ,replace HuaweiMap.setOnMyLocationChangeListener()
  4. */
  5. private void setOnMyLocationChangeListener(){
  6.    // When you construct request parameters, please refer to the development guide of the Location Kit.
  7.    com.huawei.hms.location.LocationRequest request = new  com.huawei.hms.location.LocationRequest();
  8.    request.setInterval(2000);
  9.    LocationServices
  10.           .getFusedLocationProviderClient(this).requestLocationUpdates(request, new LocationCallback() {
  11.       @Override
  12.       public void onLocationResult(  com.huawei.hms.location.LocationResult locationResult) {
  13.           if (locationResult != null) {
  14.               List<Location> locations = locationResult.getLocations();
  15.                    if (!locations.isEmpty()) {
  16.                        for (Location location : locations) {
  17.                            Log.i(TAG,
  18.                                    "onLocationResult location[Longitude,Latitude,Accuracy]:"
  19.                                            + location.getLongitude() + "," + location.getLatitude() + ","
  20.                                            + location.getAccuracy());
  21.                        }
  22.                    }
  23.                }
  24.            }
  25.            @Override
  26.            public void onLocationAvailability(LocationAvailability locationAvailability) {
  27.                if (locationAvailability != null) {
  28.                    boolean flag = locationAvailability.isLocationAvailable();
  29.                    Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
  30.                }
  31.            }
  32.        }, android.os.Looper.myLooper()).addOnSuccessListener(new OnSuccessListener<Void>() {
  33.            @Override
  34.            public void onSuccess(Void param0) {
  35.                Log.d(TAG,"onSuccess.....");
  36.            }
  37.     });
  38. }

Add HMS API sample code:

  1. /**
  2. * this is an Example
  3. * using location kit requestLocationUpdates(Request,LocationCallback,Looper) ,replace HuaweiMap.setOnMyLocationChangeListener()
  4. */
  5. private void setOnMyLocationChangeListener(){
  6.      // When you construct request parameters, please refer to the development guide of the Location Kit.
  7.        org.xms.g.location.LocationRequest request = new  org.xms.g.location.LocationRequest();
  8.        request.setInterval(2000);
  9.        LocationServices
  10.                .getFusedLocationProviderClient(this).requestLocationUpdates(request, new LocationCallback() {
  11.            @Override
  12.            public void onLocationResult(  org.xms.g.location.LocationResult locationResult) {
  13.                if (locationResult != null) {
  14.                    List<Location> locations = locationResult.getLocations();
  15.                    if (!locations.isEmpty()) {
  16.                        for (Location location : locations) {
  17.                            Log.i(TAG,
  18.                                    "onLocationResult location[Longitude,Latitude,Accuracy]:"
  19.                                            + location.getLongitude() + "," + location.getLatitude() + ","
  20.                                            + location.getAccuracy());
  21.                        }
  22.                    }
  23.                }
  24.            }
  25.            @Override
  26.            public void onLocationAvailability(LocationAvailability locationAvailability) {
  27.                if (locationAvailability != null) {
  28.                    boolean flag = locationAvailability.isLocationAvailable();
  29.                    Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
  30.                }
  31.            }
  32.        }, android.os.Looper.myLooper()).addOnSuccessListener(new OnSuccessListener<Void>() {
  33.            @Override
  34.            public void onSuccess(Void param0) {
  35.                Log.d(TAG,"onSuccess.....");
  36.            }
  37.    });
  38. }

6.3 HuaweiMap.setOnCameraChangeListener()

This method can be replaced by the setOnCameraMoveStartedListener, setOnCameraMoveListener, and setOnCameraIdleListener methods for listening to the moveCamera event.

Sample code:

  1. /**
  2. * this is an Example
  3.    * using setOnCameraMoveStartedListener, setOnCameraMoveListener, setOnCameraIdleListener to
  4. * replace to HuaweiMap.setOnCameraChangeListener.
  5. */
  6. private void setOnCameraChangeListener() {
  7.        Log.d(TAG, " start addMoveListener...");
  8.        this.mMap.setOnCameraMoveStartedListener(i -> Log.d(TAG," start camera move..."));
  9.        this.mMap.setOnCameraMoveListener(() -> Log.d(TAG," camera moving..."));
  10.        this.mMap.setOnCameraIdleListener(() -> {
  11.            Log.d(TAG," idle camera move... ");
  12.        });
  13. }

7 setMapStyle()

JSON resource files need to be loaded for map style settings (options: retro, night, grayscale, and simple). The JSON file format used by HuaweiMap is different from that used by GoogleMap. As a result, they cannot share the same JSON resource files. Compatibility adaptation is required at the service code layer. To download the map style JSON files for HuaweiMap, please go to Download link.

In the To HMS API scenario, perform the following steps for modification:

1. Download the Huawei JSON files.

2. In the res/raw directory of the project (that is, the directory of the map style JSON resource files, which may vary according to projects), replace the resource files with those of the same names. The following figure shows the files for replacement.

In the Add HMS API scenario, perform the following steps for modification:

1. Download the Huawei JSON files.

2. Add mapstyle_grayscale_hms.json, mapstyle_night_hms.json, and mapstyle_retro_hms.json to the res/raw directory of the project (the directory may vary according to projects) as the map style resource files of HuaweiMap. These files coexist with the map style resource files of GoogleMap. The following figure shows the files after the addition.

3. The following is the sample code for Add HMS API compatibility after the modification: Load different JSON resource files based on system settings.

  1. private void setSelectedStyle() {
  2.        MapStyleOptions style;
  3.        switch (this.mSelectedStyleId) {
  4.            case R.string.style_label_retro:
  5.                // Sets the retro style via raw resource JSON.
  6.                if(GlobalEnvSetting.isHms()){
  7.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_retro_hms);
  8.                }else{
  9.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_retro);
  10.                }
  11.                break;
  12.            case R.string.style_label_night:
  13.                // Sets the night style via raw resource JSON.
  14.                if(GlobalEnvSetting.isHms()){
  15.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_night_hms);
  16.                }else{
  17.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_night);
  18.                }
  19.                break;
  20.            case R.string.style_label_grayscale:
  21.                // Sets the grayscale style via raw resource JSON.
  22.                if(GlobalEnvSetting.isHms()){
  23.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_grayscale_hms);
  24.                }else{
  25.                    style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle_grayscale);
  26.                }
  27.                break;
  28.            case R.string.style_label_no_pois_no_transit:
  29.                // Sets the no POIs or transit style via JSON string.
  30.                style = new MapStyleOptions("[" + "  {" + "    \"featureType\":\"poi.business\","
  31.                    + "    \"elementType\":\"all\"," + "    \"stylers\":[" + "      {"
  32.                    + "        \"visibility\":\"off\"" + "      }" + "    ]" + "  }," + "  {"
  33.                    + "    \"featureType\":\"transit\"," + "    \"elementType\":\"all\"," + "    \"stylers\":["
  34.                    + "      {" + "        \"visibility\":\"off\"" + "      }" + "    ]" + "  }" + "]");
  35.                break;
  36.            case R.string.style_label_default:
  37.                // Removes previously set style, by setting it to null.
  38.                style = null;
  39.                break;
  40.            default:
  41.                return;
  42.        }
  43.        this.mMap.setMapStyle(style);
  44. }