Integration instructions
InstantRun is mPaaS's hotpatching solution for Android apps. It lets you push Java, .so, and resource fixes to production.
This guide covers the full integration and patch delivery workflow:
What's new in InstantRun
Fixes without a restart under certain conditions
Resource fixes
No class whitelist required when generating patches
How it works
Java fixes
Replaces method logic dynamically by pre-instrumenting JavaMethod.
Patches require source code modification, so third-party libraries with unmodifiable code cannot be fixed.
.so fixes
If the original .so file has not been loaded, the fix takes effect immediately.
Resource fixes
Adds and modifies resources using fixed resource IDs.
Prerequisites
Before you begin, make sure that you have:
Added mPaaS to your project (native AAR integration only)
Not mixed the dexPatch and InstantRun hotpatching methods — they are incompatible
Verified that the number and names of .so files are identical in the old and new APK packages; mismatches block hotpatch creation
Baseline version 10.2.3.20 or later. If you are on baseline version 10.1.68, follow the mPaaS 10.2.3 upgrade guide before continuing.
Step 1: Add the SDK
InstantRun only supports native AAR integration.
In your project, use Component Management (AAR) to install the Hotfix component. For details, see Manage component dependencies.
Step 2: Initialize hotpatch
Native AAR integration
Complete all three steps before using the hotpatching feature.
-
Update your
Applicationclass to extendQuinoxlessApplicationLike, and annotate it with@Keepto prevent obfuscation. CallMPHotpatch.init()insideonMPaaSFrameworkInitFinished().@Keep public class MyApplication extends QuinoxlessApplicationLike implements Application.ActivityLifecycleCallbacks { private static final String TAG = "MyApplication"; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); Log.i(TAG, "attacheBaseContext"); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); registerActivityLifecycleCallbacks(this); } @Override public void onMPaaSFrameworkInitFinished() { MPHotpatch.init(); LoggerFactory.getTraceLogger().info(TAG, getProcessName()); } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.i(TAG, "onActivityCreated"); } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } } -
In
AndroidManifest.xml, set theApplicationentry to the mPaaS-providedcom.alipay.mobile.framework.quinoxless.QuinoxlessApplication, and register your custom class under thempaas.quinoxless.extern.applicationmeta-datakey:<application android:name="com.alipay.mobile.framework.quinoxless.QuinoxlessApplication" > <meta-data android:name="mpaas.quinoxless.extern.application" android:value="com.mpaas.demo.MyApplication" /> </application>com.mpaas.demo.MyApplicationis your customApplicationagent class that inheritsQuinoxlessApplicationLike. -
Import the Apache HTTP client.
The hotpatching feature calls Apache HTTP client functions. Add the following to
AndroidManifest.xmlto allow these calls. For more information, see Use the Apache HTTP client.<uses-library android:name="org.apache.http.legacy" android:required="false"/>
Step 3: Configure InstantRun instrumentation
Add the Maven repository
maven {
url "https://mvn.cloud.alipay.com/nexus/content/repositories/open/"
}
Add plugin dependencies
In the build.gradle of your app module, apply the InstantRun plugin:
apply plugin: 'com.android.application'
apply plugin: 'com.alipay.instantrun'
In your project's root build.gradle, add the plugin classpath:
Use version 1.0.8 for Android Gradle Plugin (AGP) 8.0 or later. Use version 1.0.7 for AGP versions earlier than 8.0.
dependencies {
classpath "com.mpaas.android.patch:patch-gradle-plugin:1.0.8"
}
Configure the instantrun folder
Create the instantrun folder
In the app directory of your project, create an instantrun folder. This folder holds the mapping.txt and related files needed to generate patch.jar.
Save the following files before each version release. When you need to apply a fix, replace the files in the instantrun folder with the saved files from the previous version.
In the project with the bug, run ./gradlew clean assembleRelease to generate the following files, then place them in the instantrun folder:
instantrun/InstantRunMapping.txt.gz (This is the InstantRunMapping_release.txt.gz or InstantRunMapping_debug.txt.gz file generated after the build. The output is in ./build/outputs/instantrun/. If it exists, rename it and place it here.)
instantrun/mapping.txt (This is the mapping.txt from the original project when building the release package. The output is in ./build/outputs/mapping/[debug|release]/mapping.txt.)
instantrun/methodsMap.instantrun (This is the methodsMap.instantrun generated by the original bundle-level instrumentation. The output is in ./build/outputs/instantrun/methodsMap.instantrun. If it exists, place it here.)
Add the instantrun.xml configuration file
In the app directory of your project, add an instantrun.xml configuration file. The comments in the file explain when to change the defaults:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<switch>
<!--true enables InstantRun. Note that even if this value is true, InstantRun is enabled by default only in Release mode.-->
<!--false disables InstantRun. InstantRun will not run in either Debug or Release mode.-->
<turnOnInstantRun>true</turnOnInstantRun>
<!--Specifies whether to enable manual mode. In manual mode, all classes under the package name specified by patchPackageName are found, obfuscation is handled automatically, and then all classes under the patchPackageName are made into a patch.-->
<!--This switch only makes a patch from all classes under the package name specified by patchPackageName. It is for special cases and is not commonly used.-->
<manual>false</manual>
<!--Specifies whether to force code insertion. InstantRun is disabled by default in debug mode. Setting this option to true inserts code in debug mode.-->
<!--However, this configuration item has no effect if turnOnInstantRun is false.-->
<forceInsert>false</forceInsert>
<!--Configures the patch function matching rule. The default is function signature. You can change it to function ordinal number, which is stored in methodsMap.instantrun.-->
<!--The signature mode aspect uses more space, while the id mode aspect uses less space. The id mode is more suitable for apps where the installation package size is a concern.-->
<!--<methodMatchMode>signature</methodMatchMode>-->
<methodMatchMode>id</methodMatchMode>
<!--Specifies whether to catch all exceptions in the patch. Set this switch to true for online releases and false for testing.-->
<catchReflectException>false</catchReflectException>
<!--Specifies whether to add logs to the patch. Set this switch to false for online releases and true for testing.-->
<patchLog>true</patchLog>
<!--Specifies whether the project supports ProGuard.-->
<proguard>true</proguard>
</switch>
<!--The package names or class names that require HotPatch. Code will be inserted into all classes under these package names.-->
<!--Each bundle must configure this item with the package names of your own code within the bundle. InstantRun inserts code into the classes under these package names. Classes without inserted code cannot be fixed by InstantRun.-->
<acceptPackageName name="acceptPackage">
<name>com.</name>
<name>android.</name>
<name>org.</name>
</acceptPackageName>
<!--Package names where InstantRun code insertion is not needed. The InstantRun library does not require code insertion. Keep the following configuration items. You can add more based on the needs of each app.-->
<exceptPackageName name="exceptPackage">
<name>com.alipay.euler</name>
<name>com.alipay.dexpatch</name>
<name>com.alipay.instantrun</name>
<name>ohos.</name>
<name>com.alipay.mobile.quinox.LauncherApplication</name>
</exceptPackageName>
<!--The function access types and corresponding package name lists that do not require InstantRun instrumentation. On-demand instrumentation can reduce the integration package size.-->
<methodExceptConfig name="methodExceptConfig">
<privateMethodPackage>
<name>com.instantrun.demo</name>
</privateMethodPackage>
<packageMethodPackage>
<name>com.instantrun.demo</name>
</packageMethodPackage>
<protectedMethodPackage>
<name>com.instantrun.demo</name>
</protectedMethodPackage>
<publicMethodPackage>
<name>com.instantrun.demo</name>
</publicMethodPackage>
<syntheticMethodPackage>
<name>com.instantrun.demo</name>
</syntheticMethodPackage>
</methodExceptConfig>
<!--The package name of the patch. Ensure it is unique. Enter the APK package name.-->
<patchPackageName name="patchPackage">
<name>com.instantrun.demo</name>
</patchPackageName>
</resources>
Step 4: Fix the bug
Java function fixes
Complete the build dependencies and configuration from Step 3 first.
-
Annotate each modified method with
@com.alipay.instantrun.patch.annotaion.Modify, or callcom.alipay.instantrun.patch.InstantRunModify.modify()at the start of the method body:// Modify the method @com.alipay.instantrun.patch.annotaion.Modify protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // Or call the com.alipay.instantrun.patch.InstantRunModify.modify() method inside the modified method protected void onCreate(Bundle savedInstanceState) { com.alipay.instantrun.patch.InstantRunModify.modify() super.onCreate(savedInstanceState); } -
For Lambda expressions, call
com.alipay.instantrun.patch.InstantRunModify.modify()inside the modified method:// Modify the method @com.alipay.instantrun.patch.annotaion.Modify protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // Or call the com.alipay.instantrun.patch.InstantRunModify.modify() method inside the modified method protected void onCreate(Bundle savedInstanceState) { com.alipay.instantrun.patch.InstantRunModify.modify() super.onCreate(savedInstanceState); } -
For new classes or methods, use the
@com.alipay.instantrun.patch.annotation.Addannotation:// Add a method @com.alipay.instantrun.patch.annotaion.Add public String getString() { return "InstantRun"; } // Add a class @com.alipay.instantrun.patch.annotaion.Add public class NewAddCLass { public static String get() { return "instantRun"; } }
.so file fixes
Modify the relevant C/C++ code or .so file, then package the new .so file to replace the original .so library in your project.
Resource fixes
Resource fixes support adding and modifying any resource files, except .so library resources.
Fixed resource ID configuration
-
Download the tool JAR package for generating resource files to extract the resource IDs from the APK you want to fix:
java -jar ~/path/stableResourcesId.jar ~/path/old.apk ~/path/valuesThe output files are generated in the target directory.
Copy the generated
public.xmlandids.xmlfiles into the~/res/valuesdirectory of the new project that contains the fix.-
Copy the
public.txtfile into the root directory of the new project that contains the fix.Then add the following to the
androidnode in thebuild.gradleof your app module:aaptOptions { File publicTxtFile = project.rootProject.file( 'public.txt') if (publicTxtFile.exists()) { additionalParameters "--stable-ids", "${project.rootProject.file ('public.txt').absolutePath}" } }
Configure patch packaging
In the mPaaS plugin for Android Studio, go to Basic Tools > Hotfix > Generate Patch (instant run).
Note on layout file changes
If you modify or add an xml layout file under res/layout, you must also apply a Java patch at the code layer: add the modification annotation, retrieve the corresponding resource ID, and load the resource.
Step 5: Generate the patch
Generate patch.jar
patch.jar contains the fix and is required to build the hotpatch package. In the project that contains the fix, run:
./gradlew clean mpGeneratePatch
The file is output to ./build/outputs/instantrun/patch.jar.
Generate the InstantRun hotpatch
In Android Studio, use the mPaaS plugin to build the patch:
Click Basic Tools > Hotfix > Generate Patch (instant run).
-
Fill in the required fields:
New bundle: Path to the fixed APK package.
Old bundle: Path to the buggy APK package (the version currently in production).
PatchJarPath dir: Path to the
patch.jargenerated by running./gradlew clean mpGeneratePatchin the InstantRun-integrated project.Patch out dir: Directory where the output patch package is saved.
ImportantDo not store the APK packages in the
Userdirectory on the C drive or in a directory with a name that contains Chinese characters. Click Next and verify the signing information. Incorrect signing details cause patch generation to fail.
Click Create to generate the patch.
Step 6: Publish the hotpatch
Publish the patch package to the mPaaS console. For more information, see Use hotpatch.
View logs
Use the following log filters to diagnose hotpatch behavior:
-
Rolling update request logs
Filter for log tags containing
DynamicRelease. -
InstantRun execution logs
Filter for log tags containing
IR. -
Patch execution logs
Enable
patchLogininstantrun.xmlbefore building the patch, then filter for log tags containingIR.PatchCode. A log line containinginvoke method isconfirms that the patch was applied to the corresponding method.