Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically link packages based on product flavor to support GMS & HMS with one code base

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",
}
like image 602
RodSarhan Avatar asked Nov 28 '25 10:11

RodSarhan


2 Answers

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

like image 136
Zinna Avatar answered Nov 30 '25 04:11

Zinna


You may refer to this.

It's configured in here:

enter image description here

And run the following command:

enter image description here

like image 21
zhangxaochen Avatar answered Nov 30 '25 05:11

zhangxaochen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!