Android dynamic loading

Table of contents

1. Introduction to dynamic loading technology

2. Types of dynamic loading technology

1. Dynamically load the so library

2. Dynamically load dex/jar/apk files

3. The concept of class loader

4. The principle of dynamic loading

5. Implementation of dynamic loading

1. Simple dynamic loading mode

2. Using reflection

3. The way to use the interface

4. Use the proxy Activity mode

6. How to create a plug-in project

Seven. The advantages of dynamic loading

8. Disadvantages of dynamic loading


1. Introduction to dynamic loading technology

When the program is running, load some executable files that do not exist in the program itself and run the code logic in these files. Dynamic loading has the following characteristics:

  1. When the application is running, it loads some executable files that do not exist locally to achieve some specific functions;
  2. These executables are replaceable;
  3. Replacing static resources does not belong to dynamic loading, such as changing the startup image, changing the theme, or using server switches to control the hidden implementation of advertisements, etc.;
  4. The core idea of ​​dynamic loading in Android is to dynamically call external dex files.

2. Types of dynamic loading technology

In the Android project, the dynamic loading technology can be divided into two types according to the loaded executable file.

1. Dynamically load the so library

Android's NDK actually uses the method of dynamically loading the .so library and calling its package through JNI. The latter is generally compiled by C/C++, and the efficiency of running in the Native layer is much higher than that of java code executed in a virtual machine, so Android often loads dynamic .so libraries to complete some tasks that require relatively high performance, such as T9 search , Bitmap decoding, Gaussian blur of pictures, etc.

2. Dynamically load dex/jar/apk files

In an Android project, all java code will be compiled into a dex file. When the Android application is running, it works by executing the business logic in the dex file. Using the dynamic loading technology, an external dex file can be loaded when the Android application is running. Downloading a new dex file through the network and replacing the original dex file can achieve the purpose of upgrading the application without installing a new APK file.

3. The concept of class loader

Class loader (Class Loader) is a very important concept in Java. The class loader is responsible for loading the bytecode of the java class into the Java virtual machine. The class loaders in Android are DexClassLoader and PathClassLoader. Their difference is:

  • DexClassLoader: can load jar/apk/dex, and can load uninstalled apk from SD card;
  • PathClassLoader: Only installed apk files can be loaded.

4. The principle of dynamic loading

No matter what kind of dynamic loading, the basic principle is to load some external executable files when the program is running, and then call a method of these files to execute business logic. For these external executable files, they must be copied to the data/packagename/internal storage file path before being called by the Android application, and the corresponding files are loaded using the class loader to obtain internal resources through reflection for use by the host APP. The general process of dynamic loading is:

  1. Copy the executable file (.so/dex/jar/apk) to the internal storage of the application APP;
  2. load the executable;
  3. Call specific methods to perform business;

5. Implementation of dynamic loading

1. Simple dynamic loading mode

Compile the java code into a .class file through the JDK compilation command javac, and then use the jar command to package the .class file into a .jar file. Finally, use the DX tool of the Android SDK to optimize the .jar file into a .dex file.

After loading through DexClassLoader, use reflection or interface to call the methods inside.

    private void getOutData(){
        File optimizadDexOutputPath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"test_dexloafer.jar");
        // 无法直接从外部路径加载.dex文件,需要指定APP内部路径作为缓存目录(.dex文件会被解压到此目录)
        File dexOutputDir = this.getDir("dex",0);
        //构造类加载器
        DexClassLoader dexClassLoader = new DexClassLoader(optimizadDexOutputPath.getAbsolutePath(),dexOutputDir.getAbsolutePath(),null,ClassLoader.getSystemClassLoader());
    } 

2. Using reflection

Classes loaded using DexClassLoader cannot be called directly, but can be called by reflection.

 private void getOutData(){
        File optimizadDexOutputPath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"test_dexloafer.jar");
        File dexOutputDir = this.getDir("dex",0);
        DexClassLoader dexClassLoader = new DexClassLoader(optimizadDexOutputPath.getAbsolutePath(),dexOutputDir.getAbsolutePath(),null,ClassLoader.getSystemClassLoader());
        Class libProviderClazz = null;
        try {
            libProviderClazz = dexClassLoader.loadClass("包名.类名");
            //遍历所有的方法
            Method[] methods = libProviderClazz.getDeclaredMethods();
            for (int i = 0;i<methods.length;i++){
                Log.e("test",methods[i].toString());
            }
            //通过方法名获取func方法
            Method func= libProviderClazz.getDeclaredMethod("func");
            //外部可以调用
            func.setAccessible(true);
            //调用该方法获得值
            String string = (String) func.invoke(libProviderClazz.newInstance());
            Toast.makeText(this, string, Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

3. The way to use the interface

Abstract the methods of the .dex file into public interfaces, copy these interfaces to the main project, and implement dynamic loading through interface calls

pulic interface IFunc{
    public String func();
}

// 调用
IFunc ifunc = (IFunc)libProviderClazz;
String string = ifunc.func();
Toast.makeText(this, string, Toast.LENGTH_LONG).show();

4. Use the proxy Activity mode

Using the Activity in the plug-in apk needs to solve two problems:

1. How to make the Activity in the plug-in apk have a life cycle

The main project apk registers an empty ProxyActivity, and synchronously calls the lifecycle method of the Activity in the plug-in in the life cycle of ProxyActivity, so as to realize the business logic of executing the plug-in apk.

2. How to make the Activity in the plug-in apk have a context

The new resources that need to be used in the plug-in are all created through java code (xml layout, animation, point nine pictures). A Resource instance can be created through an AsserManager instance

  public int getAppNameResId(String apkPath){
        PackageManager packageManager = this.getPackageManager();
        PackageInfo info = packageManager.getPackageArchiveInfo(apkPath,0);
        return info.applicationInfo.labelRes;
    }
    private Resources getExtResource(Context context,String apkPath){
        int mDexPath = getAppNameResId(apkPath);
        Resources res = context.getResources();
        try {
            Class<?> assetClass = Class.forName("android.content.res.AssetManager");
            Object assetManager = assetClass.getConstructor(null).newInstance(null);
            assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath",String.class);
            addAssetPath.invoke(assetManager,mDexPath);

            Class<?> resClass = Class.forName("android.content.res.Resources");
            res = (Resources) resClass.getConstructor(assetClass,res.getDisplayMetrics().getClass(),res.getConfiguration().getClass())
                    .newInstance(assetManager,res.getDisplayMetrics(),res.getConfiguration());
        }catch (Exception e){
            e.printStackTrace();
        }
        return res;
    }

6. How to create a plug-in project

The plug-in project is an apply plugin:'com.android.library' in an android library .gradle file. The plug-in project is to provide a class and generate a jar package for the main project to load and call.

step1. Double-click the assemble task in gradle

step2. Find the jar file under the path ./myplugin/build/intermediates/aar_main_jar/debug/classes.jar

step3. Open the dx tool and execute the following command to optimize origin.jar

dx --dex --output=target.jar origin.jar

step4. Set minifyEnabled in debug of buildTypes to false

debug{
        minifyEnabled false
    }

step5. Use adb push XXX.jar /sdcard/  to put dex/jar on sdcard.

Seven. The advantages of dynamic loading

  1. Avoid the upgrade process of APK overlay installation and improve user experience;
  2. Dynamically fix some urgent bugs in the application;
  3. When the application volume is huge, some modules can be split out in the form of plug-ins through dynamic loading, reducing the size of the project and improving the compilation speed, and also allowing the main project and plug-in projects to be developed in parallel;
  4. The plug-in module can be initialized when needed in a lazy loading manner, improving the startup speed of the application;
  5. In terms of project management, splitting the plug-in module achieves code separation at the project level and reduces the coupling between modules;
  6. When promoting other applications on Android applications, dynamic loading can be used to allow users to experience the functions of new applications first without downloading and installing a new apk
  7. Reduce the number of methods for the main project dex

8. Disadvantages of dynamic loading

  1. With the deepening of the complexity of the dynamic loading framework, the construction process of the project becomes complicated;
  2. Since the plug-in project is developed independently, when the main project runs the plug-in, the code logic is prone to bugs;
  3. Some frameworks use reflection to call part of the Android system Framework layer code, and there is a risk of compatibility;
  4. Using dynamic loading plug-ins may encounter compatibility problems when using system resources.

reference

Research on Dynamic Loading Technology - From Simple to Deep - Short Book (jianshu.com)

(3 messages) Android dynamic loading_Dog-sin dog's blog-CSDN blog_android dynamic loading

Guess you like

Origin blog.csdn.net/weixin_43858011/article/details/125070085