Mobile Development 16 min read

How to Prepare Android Apps for Global Release: Architecture, AAB Packaging, and Multi‑Language Support

This article shares practical techniques for adapting Android apps to overseas markets, covering modular code design, compliance checks, AAB bundle creation, Google Play signing, manifest adjustments, and automated multi‑language workflows to streamline global publishing.

NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
NetEase Cloud Music Tech Team
How to Prepare Android Apps for Global Release: Architecture, AAB Packaging, and Multi‑Language Support

Overview

Chinese companies are increasingly publishing Android apps overseas. This summary captures the technical adaptations required to take an Android client (NetEase Cloud Music) from a domestic to an overseas release.

Adapting to Overseas Environments

Common modules must support overseas requirements while preserving the original architecture.

Verify that third‑party services (e.g., NetEase IM, Agora SDK) have overseas endpoints.

Re‑implement core features—login, file upload, push notifications, sharing—for the overseas version.

Audit low‑level libraries for compliance with Google Play policies and correct resource configuration.

Target Google Play as the primary distribution channel and adopt the Android App Bundle ( .aab) format.

Base Library Overseas Implementation Layer

The project follows an interface‑implementation separation pattern. Using a file‑upload library as an example, three AAR modules are produced: uploader_interface – defines all upload‑related APIs. uploader_module – standard implementation that uploads directly to the internal CDN. uploader_module_oversea – overseas implementation that first uploads to Amazon S3 and then synchronises the S3 metadata back to the CDN.

Business code calls the same interface APIs; only the implementation module is swapped for overseas builds.

Low‑Level Library Compliance Check

Avoid prohibited APIs such as dynamic code loading or hot‑fix mechanisms that Google Play rejects.

Remove SDKs or code paths that are unnecessary for overseas users, especially those that embed dynamically loaded native libraries.

Reference: Google Play privacy policy guidelines – https://support.google.com/googleplay/android-developer/answer/9888170?hl=zh-Hans&ref_topic=9877467

AAB Packaging and Play Store Distribution

Build the app bundle with Gradle: ./gradlew :app:bundleRelease For testing, convert the AAB to an .apks package using bundletool and install via adb install-multiple:

java -jar bundletool.jar build-apks --bundle=${FILE_NAME} --output=${target_apks}
unzip ${target_apks}
cd splits
adb install-multiple bae-master.apk xx.apk

To install programmatically without command‑line scripts, use the Android PackageInstaller API. Sample Kotlin code:

val installer = InstallApp.application().packageManager.packageInstaller
val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = installer.createSession(params)
val session = installer.openSession(sessionId)
apks.forEach { apk ->
    session.openWrite(apk.hashCode().toString(), 0, -1).use { out ->
        FileInputStream(apk).use { fin ->
            val buffer = ByteArray(16384)
            var len: Int
            while (fin.read(buffer).also { len = it } != -1) {
                out.write(buffer, 0, len)
            }
        }
        session.fsync(out)
    }
}
session.close()
val intent = Intent(InstallApp.application(), RetActivity::class.java)
intent.action = PACKAGE_INSTALLED_ACTION
val pendingIntent = PendingIntent.getActivity(InstallApp.application(), 0, intent, FLAG_MUTABLE)
val statusReceiver = pendingIntent.intentSender
session.commit(statusReceiver)

The installation result can be read from the intent extra android.content.pm.extra.STATUS.

Google Play Signing

Enable Google Play App Signing. Upload a keystore ( release.jks) as the upload key; Google Play re‑signs the app with a store key ( store.jks). If the default Google‑generated key is used, only a .der public‑key certificate is exported, which cannot be used for normal packaging. Therefore, select “Upload a new app‑signing key from a Java keystore” to provide a full keystore for both upload and store builds.

Manifest uses-feature Issue and Gradle Fix

Declaring uses-feature without android:required="false" can cause Google Play to report zero supported devices. Add the attribute or modify the merged AndroidManifest.xml via a Gradle script that forces required to false for specific features:

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def processManifest = output.getProcessManifestProvider().get()
        processManifest.doLast { task ->
            def manifestFile = file("${task.multiApkManifestOutputDirectory}/AndroidManifest.xml")
            if (manifestFile.exists()) {
                def xml = new XmlParser().parse(manifestFile)
                def androidNs = new Namespace('http://schemas.android.com/apk/res/android', 'android')
                xml.'uses-feature'.each { node ->
                    if (node.@[androidNs.name] == 'android.hardware.camera.front' ||
                        node.@[androidNs.name] == 'android.hardware.camera.front.autofocus') {
                        node.@[androidNs.required] = false
                    }
                }
                manifestFile.text = XmlUtil.serialize(xml)
            }
        }
    }
}

Multi‑Language Workflow

Language switching is performed by changing the Locale and recreating the current Activity:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    config.locale = target
    res.updateConfiguration(config, res.displayMetrics)
    config.setLocale(target)
    context.createConfigurationContext(config)
} else {
    config.locale = target
    res.updateConfiguration(config, res.displayMetrics)
}

Translated XML files are fetched from an internal translation platform and placed into language‑specific resource folders (e.g., /res/values-en, /res/values-in).

A custom Gradle plugin automates two tasks:

Defines supported languages in a configuration file and generates constant code for language keys.

Registers a pre‑build task ( pre${variant}Build) that downloads translation files. For debug builds the resources contain Chinese XML; for release builds they contain English XML.

The plugin also validates resources (detects missing format placeholders, unescaped ampersands) and generates mock strings for missing translations, e.g., "client mock common_hello(id)".

During debugging, a floating‑window tool can display the string‑resource key of any TextView on screen, reducing communication overhead between QA, designers, and developers.

Conclusion

The article outlines practical steps for taking an Android app overseas: modular architecture with an overseas implementation layer, low‑level library compliance, AAB packaging and Google Play signing, manifest feature handling, and an automated multi‑language workflow. Remaining challenges include device fragmentation, low‑end hardware, and network constraints in overseas markets.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

mobile developmentAndroidPackagingAABGoogle PlayApp Releasemulti-language
NetEase Cloud Music Tech Team
Written by

NetEase Cloud Music Tech Team

Official account of NetEase Cloud Music Tech Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.