Integration instructions
InstantRun only supports native AAR integration.
New InstantRun features
Supports fixes without a restart under certain conditions.
Supports resource fixes.
A class whitelist is not required when you generate patches.
How it works
Java fixes
Replaces logic dynamically by pre-instrumenting JavaMethod.
Because building a patch requires modifying the source code, you cannot fix third-party libraries whose code is unmodifiable.
SO Fix
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
For native AAR integration, you must first add mPaaS to your project.
Do not mix the dexPatch and InstantRun hotpatching methods.
The number and names of .so files must be the same in the old and new APK packages. Otherwise, you cannot create a hotpatch.
You must use 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 to upgrade.
Add SDK
Native AAR method
For more information, see Manage component dependencies. Install the Hotfix component in your project using Component Management (AAR).
Initialize hotpatch
Native AAR integration
To use the hotpatching feature, you must complete the following steps.
Update your
Applicationobject to inherit fromQuinoxlessApplicationLike, and prevent this class from being obfuscated. The following example uses MyApplication.@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 the AndroidManifest.xml file, set the
Applicationobject to theApplicationobject provided by mPaaS. Add the MyApplication class that you just created to themeta-datatag with the keympaas.quinoxless.extern.application. The following example shows how to do this:<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 custom `Application` agent class that inheritsQuinoxlessApplicationLike.Import the Apache HTTP client.
The hotpatching feature calls functions from the Apache HTTP client. To allow these calls, add the following code to
AndroidManifest.xml. For more information, see Use the Apache HTTP client.<uses-library android:name="org.apache.http.legacy" android:required="false"/>
InstantRun instrumentation configuration and dependencies
InstantRun Maven
maven {
url "https://mvn.cloud.alipay.com/nexus/content/repositories/open/"
}InstantRun instrumentation dependencies
In the `build.gradle` file of your project's main app module, add the following dependencies:
apply plugin: 'com.android.application'
apply plugin: 'com.alipay.instantrun'In the `build.gradle` file of your project's root directory, add the following plugin dependency:
If your project uses AGP 8.0 or later, you must use version 1.0.8 of the plugin dependency. If your project uses a version of AGP earlier than 8.0, you must use version 1.0.7.
dependencies {
classpath "com.mpaas.android.patch:patch-gradle-plugin:1.0.8"
}InstantRun instrumentation configuration
Create the instantrun folder
In the `app` directory of the main project, create an `instantrun` folder. Place the mapping.txt file required to generate `patch.jar` into this folder.
Follow these instructions to add files to the `instantrun` folder:
You must 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 that contains the bug, run the command ./gradlew clean assembleRelease to generate the following files:
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 the main project, add the instantrun.xml configuration file. Carefully review each option in the configuration:
<?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>Modify the bug code
Java function fix method
First, integrate the build dependencies and configurations described above.
Add the following annotation to the modified method:
@com.alipay.instantrun.patch.annotaion.Modify// 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()in 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 and 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 fix method
Modify the relevant C/C++ code or .so file. Then, package the new .so file to replace the original .so library in the project.
Resource fix method
Supports fixing and adding any resource files, but does not support adding .so library resources.
Fixed resource ID configuration
Download the tool JAR package for generating resource files to obtain the resource IDs of the APK package that you want to fix. Run the following command:
java -jar ~/path/stableResourcesId.jar ~/path/old.apk ~/path/valuesThe output files are generated in the target directory.
Place the generated
public.xmlandids.xmlfiles into the~/res/valuesdirectory of the new project that contains the fix.Place the
public.txtfile into the root directory of the new project that contains the fix.Then, add the following configuration to the android node in the
build.gradlefile of the 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 the Basic Tools > Hotfix > Generate Patch (instant run) page.
Note
If you modify or add an xml layout file under res/layout, you must apply a Java patch to the Java code layer. To do this, add the modification annotation, retrieve the corresponding resource ID, and then load the resource.
Use InstantRun
Generate the patch.jar output file
The patch.jar file is a key component for generating the hotpatch package because it contains the fix. You can generate this file from the project that contains the fix. Run the following command in the terminal to generate the file:
./gradlew clean mpGeneratePatchThe output file is generated in the ./build/outputs/instantrun/patch.jar directory of the project.
Generate an InstantRun hotpatch
Generate the patch in your mPaaS plugin project in Android Studio as follows:
Click Basic Tools > Hotfix > Generate Patch (instant run).
On the patch generation page, fill in the required fix information.
Field descriptions
New bundle: Select the path of the APK package that contains the fix.
Old bundle: Select the path of the buggy APK package (the online version).
PatchJarPath dir: The path to the
patch.jarfile that is generated after you run the./gradlew clean mpGeneratePatchcommand in the project where InstantRun is integrated.Patch out dir: The path where the patch package output file is stored.
ImportantThe APK packages for New bundle and Old bundle cannot be stored in the `User` directory on the C drive or in a directory with a name that contains Chinese characters.
Click Next to open the signing information page.
Make sure the signing information is correct. Otherwise, the generation will fail.
After you fill in the information, click Create to generate the patch.
Use the hotpatch
Publish the patch package to the console. For more information, see Use hotpatch.
View logs
Rolling update request logs
Filter for logs where the tag contains DynamicRelease.
InstantRun execution logs
Filter for logs where the tag contains IR.
Patch execution logs
Before creating the patch, enable the patchLog option in the instantrun.xml build configuration file. Filter for logs where the tag contains IR.PatchCode. A log line that contains `invoke method is` indicates that the patch for the corresponding function was executed.