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

1、前言

插件化知識梳理(1) - Small 框架之如何引入應用插件插件化知識梳理(2) - Small 框架之如何引入公共庫插件 前兩篇文章中,咱們介紹瞭如何經過Small框架來實現應用插件及公共庫插件,今天,我再來介紹一個新的知識點 - 宿主分身。android

與應用插件和公共庫插件不一樣,宿主分身會做爲宿主的一部分,被編譯到宿主當中,所以它不能被獨立更新,可是它提供了一些插件所不具有的功能:json

  • 插件模塊能夠自由訪問其中的代碼和資源
  • 預留特定的資源、代碼和AndroidManifest.xml聲明,讓系統能夠正常識別
  • 預留穩定的資源、代碼、第三方庫,減小插件體積

正如前面介紹的,應用插件經過app.xxx,公共庫插件經過lib.xxx的命名方式,讓Small進行識別。而宿主分身則須要以app+xxxx的方式來命名。bash

除了以上介紹的可選狀況,有一些代碼是必需要放入到宿主分身中的:網絡

  • AndroidManifest.xml的聲明
  • 全部權限,例如引入網絡權限、讀取存儲等
  • 包含了某些特殊權限的Activity,如processconfigChanges
  • 任何的provider/receiver/service聲明
  • 資源
  • 轉場動畫
  • 通知欄圖標、自定義視圖
  • 桌面快捷方式圖標

2、具體示例

2.1 建立應用插件模塊

首先,咱們建立一個新的插件模塊,建立的方式和 插件化知識梳理(1) - Small 框架之如何引入應用插件 中介紹的相同: app

其中, 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 ide

對於宿主分身模塊,這裏咱們須要在 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 知識梳理系列:

相關文章
相關標籤/搜索