插件化知识梳理(3) Small 框架之宿主分身

本文介绍如何在Small框架中使用宿主分身模块。宿主分身作为宿主的一部分,虽不可独立更新,但能提供稳定资源、代码和第三方库,减小插件体积,并允许插件模块访问其内部资源。

一、前言

插件化知识梳理(1) - Small 框架之如何引入应用插件插件化知识梳理(2) - Small 框架之如何引入公共库插件 前两篇文章中,我们介绍了如何通过Small框架来实现应用插件及公共库插件,今天,我再来介绍一个新的知识点 - 宿主分身。

与应用插件和公共库插件不同,宿主分身会作为宿主的一部分,被编译到宿主当中,因此它不能被独立更新,但是它提供了一些插件所不具备的功能:

  • 插件模块可以自由访问其中的代码和资源
  • 预留特定的资源、代码和AndroidManifest.xml声明,让系统可以正常识别
  • 预留稳定的资源、代码、第三方库,减少插件体积

正如前面介绍的,应用插件通过app.xxx,公共库插件通过lib.xxx的命名方式,让Small进行识别。而宿主分身则需要以app+xxxx的方式来命名。

除了以上介绍的可选情况,有一些代码是必须要放入到宿主分身中的:

  • AndroidManifest.xml的声明
  • 所有权限,例如引入网络权限、读取存储等
  • 包含了某些特殊权限的Activity,如processconfigChanges
  • 任何的provider/receiver/service声明
  • 资源
  • 转场动画
  • 通知栏图标、自定义视图
  • 桌面快捷方式图标

二、具体示例

2.1 创建应用插件模块

首先,我们创建一个新的插件模块,创建的方式和 插件化知识梳理(1) - Small 框架之如何引入应用插件 中介绍的相同:

其中, DetailActivity是插件的入口,而以 Stub开头的四个类分别为 Activity/Service/ContentProvider/BroadcastReceiver,我们需要在宿主分身模块中对其进行声明。

public class StubActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_stub);
    }
}
复制代码
public class StubBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "StubBroadcastReceiver, onReceive", Toast.LENGTH_SHORT).show();
    }
}
复制代码
public class StubContentProvider extends ContentProvider {

    public static final Uri CONTENT_URI = Uri.parse("content://com.demo.small.app.detail.stub.provider");

    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        Toast.makeText(getContext(), "StubContentProvider, insert", Toast.LENGTH_SHORT).show();
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
}
复制代码
public class StubService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(getApplicationContext(), "StubService, onStartCommand", Toast.LENGTH_SHORT).show();
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
复制代码

为了方便验证,我们在回调函数中弹出Toast

public class DetailActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
    }

    public void activity(View view) {
        Intent intent = new Intent(this, StubActivity.class);
        startActivity(intent);
    }

    public void service(View view) {
        Intent intent = new Intent(this, StubService.class);
        startService(intent);
    }

    public void contentProvider(View view) {
        ContentValues values = new ContentValues();
        getContentResolver().insert(StubContentProvider.CONTENT_URI, values);
    }

    public void broadcastReceiver(View view) {
        Intent intent = new Intent();
        intent.setAction("com.demo.small.action.stub.broadcast");
        sendBroadcast(intent);
    }
}
复制代码

2.2 创建宿主分身模块

创建宿主分身模块时,需要选择Android Library,并且它的模块名需要为app+xxx的结构,这里,我们命名为app+detail

对于宿主分身模块,这里我们需要在 AndroidManifest.xml文件中,添加必须要的声明:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo.small.appdetail">

    <application
        android:allowBackup="true"
        android:label="@string/app_name">

        <!-- Stub Activity -->
        <activity android:name="com.demo.small.app.detail.StubActivity" android:theme="@style/Theme.AppCompat"/>

        <!-- Stub Service -->
        <service android:name="com.demo.small.app.detail.StubService"/>

        <!-- Stub ContentProvider -->
        <provider
            android:authorities="com.demo.small.app.detail.stub.provider"
            android:name="com.demo.small.app.detail.StubContentProvider"/>

        <!-- Stub BroadcastReceiver -->
        <receiver android:name="com.demo.small.app.detail.StubBroadcastReceiver">
            <intent-filter>
                <action android:name="com.demo.small.action.stub.broadcast"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>
复制代码

2.3 修改宿主模块的 bundle.json 文件

对于宿主分身模块,不需要添加声明,我们所需要的只是对新增的应用插件模块app.detail添加声明:

{
  "version": "1.0.0",
  "bundles": [
    {
      "uri": "lib.utils",
      "pkg": "com.demo.small.lib.utils"
    },
    {
      "uri": "lib.style",
      "pkg": "com.demo.small.lib.style"
    },
    {
      "uri": "main",
      "pkg": "com.demo.small.app.main"
    },
    {
      "uri": "detail",
      "pkg": "com.demo.small.app.detail"
    }
  ]
}
复制代码

2.4 结果

通过分析最后生成的 APK文件,可以发现,只有应用插件和公共库插件模块作为 so被打包进入了 APK中,而宿主分身模块并没有生成 so
而我们在宿主分身中的声明则被加入到了最后的 AndroidManifest.xml文件中:


更多文章,欢迎访问我的 Android 知识梳理系列:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值