3

In order for my application to be approved and visible on both of Google PlayStore and Huawei App Gallery, I am currently maintaining two different branches:

  • Google branch which has react-native-maps installed but no HMS packages.

  • Huawei branch which has HMS maps installed but not react-native-maps.

I'm aware of the HMS+GMS approach, but from my experience having a module like react-native-maps that relies heavily on GMS made my app hidden from pure HMS devices, even though my app had ways to check and never navigate to screens that rely on GMS.

Both branches have the same code on the JavaScript side except one file which is used to display the map, this file imports from react-native-maps on GMS phones, and from react-native-hms-map for Huawei phones.

My question is: is there a way to dynamically exclude some files and packages in build time based on the product flavor so that I can use one codebase and just ignore some file when building the APK.

Solution: Managed to come up with a solution that got my app approved and fully visible on app stores through disabling auto linking for react native maps and manually linking it based on the product flavor. (Code might not be the cleanest but it's behaving as expected, so any cleanup suggestions would be appreciated)

Steps:

1. Disable manual linking for react-native-maps on android

By creating a file named react-native.config.js in the root directory of the project, and added the following

module.exports = {
  dependencies: {
    "react-native-maps": {
      platforms: {
        android: null,
      }
    }
  }
}

2. Added product flavors for Google and Huawei

By adding the following to android/app/build.gradle

...
...
android{
    ...
    ...
    flavorDimensions "provider"
    productFlavors {
        google {
            
            dimension "provider"
            
        }
        huawei {
            
            dimension "provider"
            
        }
    }
    ...
    ...
}
...
...

3. Added the following to the same android/app/build.gradle file

...
...
dependencies {
    ...
    ...
    huaweiImplementation 'com.huawei.hms:location:4.0.2.300'
    huaweiImplementation 'com.huawei.hms:hwid:4.0.1.300'

    googleImplementation project(':react-native-maps')
    ...
    ...
}
...
...

4. Added the following into android/settings.gradle

include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')

5. Created 2 folders inside android/app/src

folders named: huawei and google with the following structure

6. added a java file inside android/app/src/google/java/com/appname

MapPackageChecker.java

package com.appname;
import com.facebook.react.ReactPackage;
import com.airbnb.android.react.maps.MapsPackage;

public class MapPackageChecker {

  public static ReactPackage getMapPackage() {
     return new MapsPackage();
  }

}

7. added a java file inside android/app/src/huawei/java/com/appname

MapPackageChecker.java

package com.appname;
import com.facebook.react.ReactPackage;

public class MapPackageChecker {

  public static ReactPackage getMapPackage() {
     return null;
  }

}

8. added the following to android/app/src/main/java/com/appname/MainApplication.java

import static com.appname.MapPackageChecker.getMapPackage;
...
...
        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          
          //start of new lines
          if(BuildConfig.FLAVOR.equals("google")){
            packages.add(getMapPackage());
          }
          //end of new lines

          return packages;
        }
...
...

9. Access flavor name from react native code

I decided to use react-native-build-config for this purpose

Example for navigation component:

import googleMapScreen from "./googleMapScreen.js"; //relies on gms maps
import huaweiMapScreen from "./huaweiMapScreen.js"; //relies on hms maps

import BuildConfig from 'react-native-build-config';
const flavor = BuildConfig.FLAVOR
...
...
    <Stack.Screen
        name="MapScreen"
        component={flavor === "huawei" ? huaweiMapScreen : googleMapScreen}
    />
...
...

10. After adding product flavors, we need to make some changes to our commands

yarn react-native run-android

becomes: yarn react-native run-android --variant=huaweiDebug

or: yarn react-native run-android --variant=googleDebug

./gradlew assembleRelease

becomes: ./gradlew assembleHuaweiRelease

or: ./gradlew assembleGoogleRelease

11. For convenience we can add the following to package.json scripts

"scripts":{
   "run-huawei": "yarn react-native run-android --variant=huaweiDebug",
   "run-google": "yarn react-native run-android --variant=googleDebug",
}
RodSar
  • 1,211
  • 1
  • 4
  • 14

2 Answers2

1

First of all, Huawei does support react-native-maps. Please check here: https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides-V1/integrating-sdk-0000001050034173-V1

When HMS+GMS is the preferred solution, in the code the APP needs to decide whether to use HMS or GMS based on the availability of HMS and GMS services on the device.

. How to decide whether to use HMS or GMS : enter image description here

  • Check that GMS is available enter image description here

There are also some links for your reference:

React Native Application Detect device support GMS or HMS: https://forums.developer.huawei.com/forumPortal/en/topic/0201200045194610058?fid=0101187876626530001

Choice SDK - an open-source GMS-HMS wrapper: https://forums.developer.huawei.com/forumPortal/en/topic/0201555879126330259?fid=0101187876626530001

Zinna
  • 1,947
  • 2
  • 5
  • 20
  • Thanks for the answer, i wasn't aware of Choice SDK so i will give that a try. As for react-native-maps and the react-native-hms-map you mentioned, those are two different packages. Just to be clear, the required approach is not GMS+HMS because when using this approach HMS only devices aren't able to see my app on app gallery, and Huawei support mentioned the reason being react-native-maps package. I instead want to have separate GMS and HMS builds without needing to remove react-native-maps and add react-native-hms-map every time before building. – RodSar Jan 12 '22 at 02:50
  • @RodSar What I mean is to use react-native-hms-map if it's ok with your app's design, it will work on all types of Huawei phones. – Zinna Jan 12 '22 at 17:32
  • yeah i'm using that for our Huawei branch, and the normal react-native-maps for the Google branch, i'm just looking for a way to have both packages installed at the same time and still getting full visibility on Huawei App Gallery instead of having to maintain 2 different branches – RodSar Jan 13 '22 at 01:59
1

You may refer to this.

It's configured in here:

enter image description here

And run the following command:

enter image description here

zhangxaochen
  • 32,744
  • 15
  • 77
  • 108
  • I already have my flavors setup, the current issue is that my app does not appear on HMS only devices unless i remove react-native-maps package and all its imports before building the apk, i already do HMS and GMS availability checks before navigating to the map screen but just having the react-native-maps package installed at all is preventing my app from showing on HMS only devices – RodSar Jan 12 '22 at 02:58
  • hi@RodSar, thanks for your feedback, could you mind leave your appid for us to check more info? – zhangxaochen Jan 12 '22 at 07:27
  • 1
    App ID: 103005683 Current version of the app does not have react-native-maps or any GMS and HMS availability checks, and only has HMS packages installed, this approach got it to show on all Huawei phones but is hard to maintain. Previous version had react-native-maps installed, but dynamically navigates to either GMS or HMS version of our map screen based on which service is available, this approach got it to show on some Huawei phones, but not on the latest ones. – RodSar Jan 12 '22 at 09:33
  • 1
    After checking with the review team, they found that the the map in your app of the previous version was unavailable on the HMS device during the test, and therefore your app was not visible on the HMS phone. We suspect that there is a problem with the logic of H and G, could you mind post the code how you do HMS and GMS availability checks? It is recommended that you use [this](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/about-0000001137975023?ha_source=hms1) to determine the logic of G or H. – zhangxaochen Jan 13 '22 at 02:56
  • Huawei phones were always able to reach the map screen during testing on physical devices or cloud debugging so I'm not sure how that was triggered during the test, and I think the HMS+GMS implementation was deleted from version history so if the test you're talking about happened yesterday then you might have tested an old version which didn't support GMS+HMS. Continued next comment..... – RodSar Jan 13 '22 at 04:10
  • 1
    In order to make things clearer, I will reupload a version that has both react-native-maps and react-native-hms-map with availability checks to determine where to navigate, so as long as all Huawei phones are able to reach the HMS map screen without encountering the GMS map screen, then the test will pass even if i have both packages installed is that correct? Thank you for the help, really appreciate it – RodSar Jan 13 '22 at 04:11
  • 1
    yes, you can resubmit your application, and just in case you could also send your APK to hmscore@huawei.com for us to check. – zhangxaochen Jan 13 '22 at 06:10
  • 1
    thanks for the help, i submitted again and got the app approved and visible, i've added my solution in the original post. – RodSar Jan 18 '22 at 06:33