Recently, the company needs to integrate the hot update function in its project. Since we stepped in many pits at the beginning of access, we now record the integration process. The integration process refers to the Bugly official documentation hot Update User Guide bugly.qq.com/docs/user-g…

Hot updates are Bugly’s ability for developers to urgently fix online bugs without having to issue a new version for users to be aware of. Bugly currently adopts the open source solution of wechat Tinker. Developers only need to integrate the SDK provided by us to realize the function of automatically downloading, synthesizing and applying patches, and provide a hot update management background for developers to manage patches of each version.

Why use Bugly hot updates? You don't have to pay attention to how Tinker syntheses the patch you don't have to build the patch yourself you don't have to worry about anything in the background that's going to issue the patch strategy you don't have to worry about when the patch is being downloaded and synthesizing, The background policy provides a convenient way to integrate Tinker and uses HTTPS and signature verification mechanisms to control the security of patch delivery dimensions, effectively controlling the impact range of patches and providing a one-stop solution for application upgradeCopy the code

Step 1: Add the plugin dependencies to the build.gradle file in the root directory:

Executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables = new executables For example the classpath 1.0.4"com.tencent.bugly:tinker-support:latest.release"// Pull the latest version}}Copy the code

Let me write a code slice here

Add the following to your App Module’s “build.gradle” file:

Android {defaultConfig {NDK {// set the supported SO library architecture abiFilters'armeabi'/ /,'x86'.'armeabi-v7a'.'x86_64'.'arm64-v8a'
          }
        }
      }
      
      dependencies {
	         compile "Com. Android. Support: multidex: 1.0.1." "Latest. Release indicates the latest version number. You can also specify a specific version number, for example, 1.2.0 compile'com.tencent.bugly:crashreport_upgrade:latest.release'Latest. Release indicates the latest version number. You can also specify a specific version number, for example, 2.2.0 compile'com.tencent.bugly:nativecrashreport:latest.release'
      }
Copy the code

In the app Module “build.gradle” file add:

// The dependency plugin script applies from:'tinker-support.gradle'
Copy the code

Tinker-support. gradle: tinker-support.gradle: tinker-support.gradle: tinker-support.gradle: tinker-support.gradle: tinker-support

apply plugin: 'com.tencent.bugly.tinker-support'

	def bakPath = file("${buildDir}/bakApk/") /** * Enter the base package directory generated by each build */ def baseApkDir ="app-0908-17-42-31"/** * For details about plug-in parameters, see */ tinkerSupport {// Enable tinker-support. The default value is tinker-supporttrue
    enable = true// Specify the archive directory. The default is the current module subdirectory tinker autoBackupApkDir ="${bakPath}"When compiling the patch package, you must specify the apK of the baseline version. The default value is null. If this value is null, it indicates that the patch package is not compiled"${bakPath}/${baseApkDir}/app-release.apk"// Corresponding tinker plug-in applyMapping baseApkProguardMapping ="${bakPath}/${baseApkDir}/app-release-mapping.txt"// applyResourceMapping baseApkResourceMapping ="${bakPath}/${baseApkDir}/app-release-R.txt"TinkerId = // tinkerId = // tinkerId = // tinkerId = // tinkerId ="Base - 1.0.4." "
    tinkerId = "Patch - 1.0.4"// Whether to enable overwriting tinkerPatch configuration. The default valuefalse/ / open tinkerPatch configuration is not effective after that without adding tinkerPatch overrideTinkerPatchConfiguration =true// buildAllFlavorsDir = when building multichannel patches"${bakPath}/${baseApkDir}"IsProtectedApp = supports hardeningtrue// Whether to enable reflection Application modeenableProxyApplication = true} /** * Generally speaking, we do not need to make any changes to the following parameters * For detailed description of each parameter please refer to: * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97 */ tinkerPatch { oldApk ="${bakPath}/${baseApkDir}/app-release.apk"
		    ignoreWarning = false
		    useSign = true
	   dex {
		    dexMode = "jar"
	        pattern = ["classes*.dex"]
	        loader = []
	    }
	lib {
        pattern = ["lib/*/*.so"]
    }

    res {
        pattern = ["res/*"."r/*"."assets/*"."resources.arsc"."AndroidManifest.xml"]
        ignoreChange = []
        largeModSize = 100
    }

    packageConfig {
    }
    sevenZip {
        zipArtifact = "Com. Tencent. Mm: SevenZip: 1.1.10"
	// path = "/usr/local/bin/7za"
    }
    
    buildConfig {
        keepDexApply = false
        //tinkerId = "1.0.1 - base"
	   //applyMapping = "${bakPath}/${appName}/app-release-mapping.txt"// Optional, set the mapping file. It is recommended to keep the proGuard obfuscation mode of the old APK //applyResourceMapping ="${bakPath}/${appName}/app-release-R.txt"// Optional, set r.txt file to keep ResId allocation through old APK file}}Copy the code

Step 3: Initialize the SDK

EnableProxyApplication = false (pro test this)

This is the access method recommended by Tinker, which increases the cost of access to some extent, but has better compatibility. After integrating the Bugly upgrade SDK, we need to customize ApplicationLike to implement the Application code as followsCopy the code

The custom Application

Public class SampleApplication extends TinkerApplication {/* This class integrates with the TinkerApplication class and does nothing in it. All Application code is placed in the ApplicationLike inherited class. TinkerFlags Indicates the types supported by Tinker: dex Only, Library Only or all suuport, default: TINKER_ENABLE_ALL parameter 2: delegateClassName Application Proxy 4: tinkerLoadVerifyFlag Whether to enable md5 authentication for dex or lib. The default value isfalse*/
    public SampleApplication() {
        super(TINKER_ENABLE_ALL, "The package name. WeixinTinker. SampleApplicationLike"."com.tencent.tinker.loader.TinkerLoader".false); }}Copy the code

Custom SampleApplicationLike

/** * Create a custom ApplicationLike class. This class is the proxy class for Application, <br/> */ public class SampleApplicationLike extends DefaultApplicationLike {public static final String TAG ="Tinker.SampleApplicationLike";

		    public SampleApplicationLike(Application application, int tinkerFlags,
                                 boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
                                 long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime,
                applicationStartMillisTime, tinkerResultIntent);
    }


    @Override
    public void onCreate() { super.onCreate(); // Set whether to enable hot updatetrue
        Beta.enableHotfix = true; // Set whether to automatically download patches. The default value istrue
        Beta.canAutoDownloadPatch = false; // Set whether to automatically compose patches. Defaulttrue
        Beta.canAutoPatch = false; // Sets whether to prompt the user to restartfalse
        Beta.canNotifyUserRestart = true; // Patch callback interface beta. betaPatchListener = newBetaPatchListener() {
            @Override
            public void onPatchReceived(String patchFile) {
                //Toast.makeText(getApplication(), "Patch download address" + patchFile, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDownloadReceived(long savedLength, long totalLength) {
                Toast.makeText(getApplication(),
                        String.format(Locale.getDefault(), "%s %d%%"."Resources downloading now",
                                (int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)),
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDownloadSuccess(String msg) {
                Toast.makeText(getApplication(), "Resources downloaded successfully and ready to decompress.", Toast.LENGTH_SHORT).show();
                Beta.applyDownloadedPatch();
            }

            @Override
            public void onDownloadFailure(String msg) {
                Toast.makeText(getApplication(), "Resource download failed. Please try again.", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onApplySuccess(String msg) {
                Toast.makeText(getApplication(), "Resources decompressed, please close the application, click the desktop icon to start.", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onApplyFailure(String msg) {
                Toast.makeText(getApplication(), "Resource decompression failed, please try later", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPatchRollback() {}}; // Set the development device, default isfalse, upload the patch if the range is specified for the issuance of the "development" equipment, you need to call this interface to identify development equipment Bugly. SetIsDevelopmentDevice (getApplication (),true); Init (getApplication(), appId, bugly.init (getApplication(), appId, Bugly)true); } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onBaseContextAttached(Context base) { super.onBaseContextAttached(base); // you must install multiDex whatever tinker is installed! MultiDex.install(base); // TODO: installTinker beta. installTinker(this); } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void registerActivityLifecycleCallback( Application.ActivityLifecycleCallbacks callbacks) { getApplication().registerActivityLifecycleCallbacks(callbacks); }} Note: Tinker requires you to start MultiDex. You need to configure compile in Dependencies"Com. Android. Support: multidex: 1.0.1." "You can use the multidex.install method. The SampleApplicationLike class is the proxy class for Application. All previous implementations of Application must be copied to this class. Call bet.installtinker (this) in onBaseContextAttached; .Copy the code

Case of enabproxyApplication = true (not tested)

public class MyApplication extends Application {

    @Override
    public void onCreate() { super.onCreate(); // When debugging, change the third parameter to Buglytrue
        Bugly.init(this, "900029763".false); } @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // you must install multiDex whatever tinker is installed! MultiDex.install(base); // installTinker beta.installtinker (); }} to note: You don't need to modify the Application, mainly to reduce the cost of access, Our plugin will dynamically replace the Application in the AndroidMinifest file and define the classes for us to reflect the real Application (you need to access SDK 1.2.2 and plug-in 1.0.3 and above).Copy the code

Step 4: Androidmanifest.xml configuration Do the following in AndroidMainfest.xml:

  1. Access configuration
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
		<uses-permission android:name="android.permission.INTERNET" />
		<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
		<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
		<uses-permission android:name="android.permission.READ_LOGS" />
	    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Copy the code
  1. The Activity configuration
<activity
    android:name="com.tencent.bugly.beta.ui.BetaActivity"
    android:configChanges="keyboardHidden|orientation|screenSize|locale"
    android:theme="@android:style/Theme.Translucent" />
Copy the code

Step 5: Obfuscation configuration To avoid obfuscating the SDK, add the following configuration to the Proguard obfuscation file:

-dontwarn com.tencent.bugly.** -keep public class com.tencent.bugly.**{*; }Copy the code

If you use the support-V4 package, you also need to configure the following obfuscation rules:

-keep class android.support.**{*; }Copy the code

Step 6: Test

Hot Update: Steps to generate hardened differential packs:

1. Package with signature files, three files will be generated in the build/ Outputs /bakApk path: APK file, Mapping file and R file (suggestion: save these three files to prevent loss) 2. Modify the following in the tinker-support.gradle file: BaseApkDir Base package directory, APK file generated by baseApk, Mapping file generated by baseApkProguardMapping, R file generated by baseApkResourceMapping 3. Harden and re-sign the generated APK file. (Perform this operation during security hardening.) 4. Copy the re-signed files under the App Module project (hardening is required) 5. Open Gradle in the upper right corner of AS, go to App ->Tasks-> Tinker-Support, double-click the buildTinkerPatchRelease script. Build ->outputs->patch->release patch_signed_7zp.apk differential package 6 Example Configure the differential package patch_signed_7zip.apk in the backgroundCopy the code

Upload a patch package to a platform Upload a patch package to a platform and deliver editing rules

conclusion

Integrated Bugly hot update with the help of official documentation. Of course, the original Tinker hot update was also integrated before, which was more complicated than this one. When it was connected, wechat Tinker did not support reinforcement, which did not meet the company’s needs. A week later, Tinker released a new version, which supported reinforcement I think it will waste a lot of time, so I use Bugly to integrate, so that when testing, I can go to Bugly background configuration to test.

The following is our personal public account (LongXuanzhigu). Our articles will be synchronized to this account, which is convenient for exchanging and learning Android knowledge and sharing personal favorite articles: