Applications for operation system Android are most often distributed through Google Play Store which probably every user of some Android device knows. Even though Play Store is by far the most common app store with the widest range of applications, it is not the only one. Phones and tablets from Samsung include Galaxy Store, Amazon is running its Appstore, for the enthusiasts of open-source technologies, there is F-Droid and there are also other app stores. Lately, more and more applications are being distributed via the Huawei AppGallery which we got acquainted with recently in Ackee.

Huawei AppGallery: Why

AppGallery is now pre-installed into all Huawei devices with Android. The catch is that while previously, you could find the good old Play Store next to it (at least on the distributions not designated to the chinese market) nowadays, it is no longer the case for newly released phones such as Mate 30 Pro. The American ministry of trade prohibited american companies from cooperating with some chinese companies, among them also Huawei. The chinese manufacturer can still keep releasing new products with the Android system, because the source code is freely accessible with an unrestricted licence, but they lost access to all key services of Google, including its applications such as the previously mentioned Play Store.

For the chinese market, there is no change, since the operation of american companies has been prohibited due to political reasons for a long time and the chinese run their own internal clones of common services such as Google (Baidu), Facebook (WeChat) or Amazon (Alibaba). Now, Huawei is forced to push their services away from China as well. That is why they are trying to actively widen the supply of known applications within the AppGallery and are contacting developers with offers of favorable conditions if they include their applications into the Huawei store. One of those apps is also Ventusky, a graphically perfected weather forecast for the whole world whose Android version we take care of here in Ackee.

Technical Implementation

Before the release of the application into the Huawei AppGallery, it is necessary to ensure its right functionality even on devices without Google services. In the case of simpler applications that do not use Google services, there is no need for special modifications. But nowadays, most apps use at least one such service – most commonly for example Firebase Analytics, Firebase Crashlytics, Google Location Services and others.

For the Ventusky app, we had to find a replacement for the two following tools:

  • Google Location Services – used to find out the current location of the user in order to display the local weather,
  • Google Play Billing Library – purchases in the application in order to unlock premium content (layer with other kinds of forecasts).

Our goal was to provide the current users all the functionality without changes, still using the Google services, but also include support for applications installed from the AppGallery. Now we can show you two approaches that we used to replace the above mentioned services.

Replacing Google Location Services

Including support of getting location from Huawei devices was easy. Huawei offers the Location Kit, which is an identical copy of Location Services from Google in terms of the outside interface. All we had to do was to take the class LocationProvider and split it into GoogleLocationProvider with the current implementation through Google services and add HuaweiLocationProvider for the devices using the implementation made by Huawei. As the interface is the same, all we had to do was change the imports and voilá – we have functional location services on Huawei devices. The result looks like this:

// LocationProvider.kt

abstract class LocationProvider {
    
    abstract fun getFusedLocation(context: Context): Single<Location>

    // Common functions for both providers
}

// GoogleLocationProvider.kt
import com.google.android.gms.location.LocationServices

class HuaweiLocationProvider : LocationProvider() {

    override fun getFusedLocation(context: Context): Single<Location> {
        val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
        // ...
    }
}

// HuaweiLocationProvider.kt
import com.huawei.hms.location.LocationServices

class HuaweiLocationProvider : LocationProvider() {

    override fun getFusedLocation(context: Context): Single<Location> {
        val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
        // ...
    }
}

During the testing on Huawei devices, we found out that getting location does not have to work all the time. For everything to go well, the phone needs to have HMS Core application installed (similar to Google Play Services) and have the permission assigned to get location. That does not always have to be the case in factory settings, at least on the devices we used. Therefore it was decided that even the Huawei version of the application will attempt to connect to Google services and only in case they are not available, the Huawei services will be used. This scenario can commonly happen for older Huawei devices with Google Play that are used away from China. Therefore even in case that the application is installed from AppGallery, it can under these conditions be using Google services without restrictions. This requirement was implemented easily:

val Context.isGoogleServicesAvailable: Boolean  
    get() = GoogleApiAvailability.getInstance()
                .isGooglePlayServicesAvailable(this) == GoogleConnectionResult.SUCCESS

// Koin DI library
val locationModule = module {    
    single {  
        if (androidContext().isGoogleServicesAvailable) {  
            GoogleLocationProvider(settings = get())  
        } else {  
            HuaweiLocationProvider(settings = get())  

    }
}
 

The used approach with duplicated implementation does have a disadvantage – it is necessary to make each change for both classes. In this case, however, it is the simplest solution, implementation of the given classes is simple and changes are not very common. It would be ideal to only have the logic implemented once and only select the required implementation of the location services. Unfortunately that was not possible in this case, as Google and Huawei location services do not implement any common interface, even though their interfaces are factually identical.

Replacing Google Play Billing Library

While in using the location services we wanted to decide the used implementation during the operation, in the case of in-app shopping we can select the implementation already during compilation. Here it is no longer the case that the application downloaded from Huawei AppGallery will have access to in-app purchases through Google Play. Moreover, Huawei introduced restrictions for application ID of applications that enable in-app purchases through the AppGallery – application ID must end with .huawei, otherwise the purchases in the application will not be working.

The first step was to divide the application into two flavorsgoogle and huawei:

// app/build.gradle

flavorDimensions "market"  

productFlavors {  
    google {  
        dimension "market"  
        applicationId appProperties['google_package_name']  


    huawei {  
        dimension "market"  
        applicationId appProperties['huawei_package_name']  

}

The implementation is slightly different from the location services – we again create an abstract base class, specific implementations will however be placed in the specific flavors

// app/src/main/java/ventusky/billing
abstract class BaseBillingManager(  
    // ...
) {  

    abstract fun getPremiumPrice(listener: PremiumPriceRetrievedListener)  
    abstract fun buyPremium(activity: Activity)

    protected fun savePremiumStatus(premiumStatus: Boolean) {  
        // ...  
    }
}

// app/src/google/ventusky/billing
class BillingManager(  
    // Google In-App dependencies
) : BaseBillingManager(/* ... */) {

    override fun getPremiumPrice(listener: PremiumPriceRetrievedListener) {
        // Google Billing implementation  
    }
    
    override fun buyPremium(activity: Activity) {
        // Google Billing implementation 
    }
}

// app/src/huawei/ventusky/billing
class BillingManager(  
    // Huawei In-App dependencies
) : BaseBillingManager(/* ... */) {

    override fun getPremiumPrice(listener: PremiumPriceRetrievedListener) {
        // Huawei Billing implementation  
    }

    override fun buyPremium(activity: Activity) {
        // Huawei Billing implementation
    }
}

During the application run, we therefore cannot decide whether we are going to be using Google or Huawei implementation, as the resulting APK will only include one specific class BillingManager whose implementation will depend on the selected flavor. But that is an advantage – we do not have to test the availability of the specific services within the code and only later decide which one to use. We already have the right implementation available – the compiled application also does not include the second, unnecessary implementation at all, which restricts the size of the installation package.

Here it is no longer the case that Huawei library for in-app purchases is a copy of the Google interface, so both versions can be updated independently. For those interested in the specific appearance of the implementation, there is the documentation of Google Play Billing library and Huawei In-App Purchases available.

Conclusion: Is Huawei AppGallery worth it?

Is it worth it to release applications into the Huawei AppGallery? For applications targeting the whole world with a numerous user base, definitely yes. It enables you to reach a significant number of further users whose number will probably keep increasing. For smaller apps, it is necessary to weigh the potential advantages against the invested effort with migration of services and maintaining more versions of the application. Especially for local apps running only within a single country, the benefit will probably be small (unless that country is China :).

For those interested in getting a new Android smartphone, we can recommend avoiding devices without Google Play. Even though the supply of alternative application stores including AppGallery is getting wider and wider, it is still very limited compared to the Play Store and a lot of applications are missing which limits the use of the phone significantly.

Leave a Reply

Your email address will not be published. Required fields are marked *