Andriod 插件化初识

一、目的

主app加载第三方apk提供的view,当view有变化时,只需更换三方app。优点:充分解耦,方便维护

二、实施

1、三方app需提供

(1)action:android.intent.action.CREATE_THIRD

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/TranslucentTheme">
    <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <action android:name="android.intent.action.CREATE_THIRD" />
       <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

(2)对外暴露的静态方法:

    public static View createThirdView(Context hostContext, Context context, Bundle bundle) {
        Log.i("============", "createThirdView");
        View view = LayoutInflater.from(context).inflate(R.layout.layout_view, null, false);
        return view;
    }

2、宿主app

(1)通过action查找revolveinfo信息,revolveinfo可提供包名和类名

(2)通过revolveinfo提供的包名,创建插件context

(3)插件context创建类加载器,配合类名获取类对象

(4)通过反射,由类获取到对应的方法,并调用方法

        var action = "third_action"
        var funcName = "third_method"
        var pluginView: View? = null
        val packageManager = application.packageManager
        val intent = Intent(action)
        //1.查找action对应的resolveInfo信息
        val resolveInfoList =
            packageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA)
        if (resolveInfoList.isNotEmpty()) {
            val resolveInfo = resolveInfoList[0]
            if (resolveInfo.activityInfo == null) {
                return null
            }
            val packageName = resolveInfo.activityInfo.packageName
            val className = resolveInfo.activityInfo.name
          
            //2.创建插件上下文
            val pluginContext = this.createPackageContext(
                packageName,
                Context.CONTEXT_INCLUDE_CODE or Context.CONTEXT_IGNORE_SECURITY
            )
            //3.通过插件上下文,创建类加载器
            val pluginClassLoader =
                PathClassLoader(pluginContext.packageResourcePath, pluginContext.classLoader)
            //4.通过类加载器加载类,并获取方法
            val loadClass = pluginClassLoader.loadClass(className)
            val localMethod = loadClass.getMethod(
                funcName,
                Context::class.java,
                Context::class.java,
                Bundle::class.java
            )
            //5.通过反射调用方法,获取view
            pluginView =
                localMethod.invoke(
                    loadClass,
                    application.applicationContext,
                    pluginContext,
                    Bundle()
                ) as View?
        }

 

posted @ 2022-08-18 14:48  随易来了  阅读(30)  评论(0编辑  收藏  举报