1 转换前须知

1.1 开发准备

    1. AppGallery Connect配置   

    2. 集成HMS SDK

    3. 配置混淆脚本

    4. 权限申请

1.2 gradle配置文件

  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 switch-case到if-else转化

工具转化完成后,某些使用 switch-case选择语句会出现case expressions must be constant expression,switch中case必须为常量异常。此类方法需要转化成if-else形式,以此方式解决switch异常问题。

原代码示例:

  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. }

修改代码示例:

  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

工具Add HMS API转换完成后,对于使用fragment展示的activity,我们提供配置classloader(简单,仅需导入资源和修改配置文件)和手写代码(复杂,手工转换工作量大)两种手工转换方式来实现兼容Google API和HMS。

配置classloader方式(Beta)

目前classloader方式暂时不支持“Generate code for creating app dependent only on GMS SDK”模式下的Add HMS API转换,在使用工具转换时请不要勾选。

1. 解压压缩包并剪切资源文件。

    a. 解压项目级目录下的xmsadapter/src/main/java文件夹下fragment-support.zip压缩包。

    b. 将其中scripts、src、xh、xg四个文件夹移动到xmsadapter文件夹下。

2. 修改工程相关配置文件。

    a. 在项目级目录下的settings.gradle文件里,添加如下引用。

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

    b. 在项目级目录下的build.gradle文件dependencies{}区块中,配置gradle插件版本为3.5.0以上。

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

    c. 在项目级目录下的gradle/wrapper/gradle-wrapper.properties文件里,配置gradle版本为5.4.1以上。

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

    d. 在app应用级目录下的build.gradle文件里,配置minSdkVersion为24以上,并在dependencies{}区块中添加如下依赖。

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

    e. 在项目级目录下的xmsadapter/build.gradle文件里,添加如下引用。

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

3. 修改Fragment相关包名。

在Android Studio中选择Edit->Find->Replace in Path,选择Module过滤器和主应用(app)过滤器(如下图中红框所示),将com.google.android.gms.maps替换成org.xms.g.maps,然后点击Replace All。

4. 在程序入口处调用init方法初始化。

    a. 在app主应用中实现一个程序入口类继承android.app.Application,并覆写其中onCreate方法。

  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. 修改app应用级目录下的src/main/AndroidManifest.xml中应用包名属性application name,添加第一条中新增的application子类。

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

5.配置打包Release版本应用的混淆规则。

    a.如果您的应用打包Release版本时开启了proguard混淆优化参数,请检查app应用级目录下build.gradle文件中若有以下内容,表示已开启proguard混淆优化参数,则需要执行步骤b,否则无需执行。

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

    b.为了避免被proguard错误地混淆或移除掉fragment相关代码,请在app应用级目录下的proguard-rules.pro文件中配置如下混淆过滤规则:

  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.异常规避。

    目前不建议重复扫描。

    如果重新扫描分析工程中出现如下Merge提示信息,请先备份并移除xmsadapter文件夹下的xh和xg文件夹,待扫描分析完成以后,再将备份恢复至xmsadapter目录下。

手写代码方式

1. 修改layout资源文件。

Add HMS API场景下,Google API和HMS需要使用独立的layout资源文件,在各自的资源文件中<fragment/>class路径不同。

HMS layout资源文件中Fragment定义参考:

  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" />

Google API layout资源文件中Fragment定义参考:

  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" />

资源文件参考:

basic_demo:原始layout资源文件。

basic_demo_hms:HMS的layout资源文件。

layout资源文件都需要一式两份,HMS和Google API各一份,配合代码兼容跳转使用。

2. 修改代码。

如果使用到了Fragment,可以在activity的onCreate()方法中通过if-else的方式一份代码同时兼容HMS和Google API。修改方式如下:

原代码示例:

  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. }

修改后代码示例:

  1. protected void onCreate(Bundle savedInstanceState) {
  2.     super.onCreate(savedInstanceState);
  3.     //根据当前类型,选择根据G或者H创建
  4.     if (org.xms.g.utils.GlobalEnvSetting.isHms()) {
  5.         createAsH();
  6.     } else {
  7.         createAsG();
  8.     }
  9. }
  10. /**
  11.  * HMS 创建流程
  12.  */
  13. private void createAsH() {
  14.     Log.d(TAG, "create as hms");
  15.     //设置hms资源文件
  16.     setContentView(R.layout.events_demo_hms);
  17.     //初始化参数
  18.     initMember();
  19.     //根据id获取hms的fragment
  20.     com.huawei.hms.maps.SupportMapFragment hMapFragment =
  21.             (com.huawei.hms.maps.SupportMapFragment) this.getSupportFragmentManager().findFragmentById(R.id.map);
  22.     //地图加载
  23.     hMapFragment.getMapAsync(this.getHInstanceOnMapReadyCallback());
  24. }
  25. /**
  26.  * GMS 创建流程
  27.  */
  28. private void createAsG() {
  29.     Log.d(TAG, "create as gms");
  30.     //设置gms资源文件
  31.     setContentView(R.layout.events_demo);
  32.     //初始化参数
  33.     initMember();
  34.     //根据id获取gms的fragment
  35.     com.google.android.gms.maps.SupportMapFragment gMapFragment =
  36.             (com.google.android.gms.maps.SupportMapFragment) this.getSupportFragmentManager()
  37.                     .findFragmentById(R.id.map);
  38.     //地图加载
  39.     gMapFragment.getMapAsync(this.getGInstanceOnMapReadyCallback());
  40. }
  41. /**
  42.  * 成员变量初始化,抽离成单独方法
  43.  */
  44. private void initMember() {
  45.     this.mTapTextView = (TextView) findViewById(R.id.tap_text);
  46.     this.mCameraTextView = (TextView) findViewById(R.id.camera_text);
  47. }

根据当前环境变量中isHms标识,选择Google API或者HMS加载地图资源,方法含义如下:

void initMember() :私有成员变量及可共用代码初始化位置。

void createAsG() :Google API创建流程。

void createAsH() :HMS创建流程。

3 Map相关常量

工具完成转换后,如果在常量引用上有异常,可参考下方列表。googleMap中对常量采用直接使用的方式,但在Add HMS API场景下,常量使用Getter的方式来使用。如:

BitmapDescriptorFactory.HUE_ORANGE ,新的方式采用BitmapDescriptorFactory.getHUE_ORANGE(),Getter的方式来获取。

googleMap常量获取

AddHMS API常量获取

import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID;(引用后直接使用)

ExtensionMap.getMAP_TYPE_NORMAL()

BitmapDescriptorFactory.HUE_ORANGE

BitmapDescriptorFactory.getHUE_ORANGE();

HuaweiMap.OnCameraMoveStartedListener.REASON_API_ANIMATION

HuaweiMap.OnCameraMoveStartedListener.getREASON_API_ANIMATION()


googleMap常量获取

To HMS API常量获取

import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID;(引用后直接使用)

import static   com.huawei.hms.maps.HuaweiMap.MAP_TYPE_HYBRID;(引用后直接使用)

4 fragment的特殊场景(OnMapAndViewReadyListener)

Marker等部分demo实现了OnMapAndViewReadyListener.OnGlobalLayoutAndMapReadyListener接口。其使用的Fragment支持Add HMS API场景的转换,在OnMapAndViewReadyListener类中进行,修改参考如下。

  1. public OnMapAndViewReadyListener(
  2.         Fragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) {}
  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处理
  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 处理
  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. }
  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

Add HMS API场景下,streeViewPanoramaFragment相对8.2 fragment的fragment在调用方式上略微有些不同,但基本思想都是根据系统类型做if-else处理。具体参考如下。

原始代码:

  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. }

修改后代码参考:

  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.         // HMS 转成org.xms
  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.         // HMS 转成org.xms
  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. }

streeViewPanoramaFragment的调用可以参考示例修改做业务的对应调整。

6 部分废弃接口替代方案

如果To HMS API场景使用Loaction kit的接口,需要增加Location依赖。版本号“${version”请参考Location kit的版本更新说明。

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

如果使用Location功能,需要确保当前已获得位置权限。

获取位置权限示例代码:

  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()

此接口可以使用Location kit中的FusedLocationProviderClient.getLastLocation()方法替代。关于此接口的详细功能描述,可以参考Location kit的API参考中getLastLocation()方法。

示例代码:

To HMS API示例代码:

  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示例代码:

  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()

此接口可以使用Location kit中的FusedLocationProviderClient.requestLocationUpdates(LocationRequest request,LocationCallback callback,Looper looper)方法替代。接口描述可以参考FusedLocationProviderClient。

To HMS API示例代码:

  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示例代码:

  1. /**
  2. * this is an Example
  3. * using location kit requestLocationUpdates(Request,LocationCallback,Looper) ,replace HuaweiMap.setOnMyLocationChangeListener()
  4. */
  5. private void setOnMyLocationChangeListener(){
  6.        //Construct request param,you can read location kit developer guide for details
  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()

此方法可以使用setOnCameraMoveStartedListener、setOnCameraMoveListener、setOnCameraIdleListener方法替代,实现moveCamera事件的监听。

示例代码:

  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()

地图样式设置(包括retro、night、grayscale、simple样式 )需要加载json资源文件,huaweiMap与googleMap使用的json文件格式上有差异,导致不能共用一份json资源文件。需要在业务代码层面做兼容适配。HuaweiMap 地图样式json文件下载链接。

To HMS API场景下的修改步骤:

1. 下载huawei json文件。

2. 在项目中res/raw目录下(即地图样式json资源文件目录,各项目可能有所不同),替换同名资源文件内容,替换文件如下图所示。


Add HMS API场景下的修改步骤:

1. 下载huawei json文件。

2. 在项目中res/raw目录下(即地图样式json资源文件目录,各项目可能有所不同),新增mapstyle_grayscale_hms.json、mapstyle_night_hms.json、mapstyle_retro_hms.json作为HuaweiMap地图样式资源文件,与googleMap地图样式资源文件并存,新增后文件如下图所示。

3. 修改后Add HMS API兼容示例代码如下。根据系统设置加载不同的json资源文件。

  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. }