外掛化設計三

kpioneer123發表於2018-01-18

1.Apk動態解析載入流程原理分析? 第一步:主程式載入外掛程式 第二步:主程式啟動外掛流程分析 外掛程式實際上啟動的是代理物件,所以我們需要在清單檔案中配置代理物件的Activity 第三步:代理物件的執行流程

2.Service生命週期?

Service生命週期.png
第一種:本地服務

                 第一點:應用程式內部使用
                 第二點:我們在應用程式中,直接通過startService啟動伺服器,通過stopService停止服務
                 第三點:我們可以通過Service內部呼叫stopSelf或者stopSelfResult()
複製程式碼
public class MyService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        this.stopSelf();
        return null;
    }
}
複製程式碼
                 第四點:無論你呼叫多少次startService,當我們需要停止伺服器的時候,只需要呼叫一次(因為Service是單例)
                 第五點:生命週期
                              startService() -> onCreate() ->onStartCommand() -> Service Running -> stopService() ->onDestory();
                 
     第二種:遠端服務
                   第一點:用於Android系統內部應用程式直接的通訊(程式間的通訊)AIDL
                  
                   第二點:需要定義介面(AIDL)暴露給外部,提供其他的應用進行訪問
                   
                   第三點:客戶端建立Service,並且呼叫bindService(啟動Service)方法建立連線,斷開連線unBindService(關閉Service)

                  第四點:多個客戶端可以繫結同一個服務,如果這個服務沒有被建立,那麼就會呼叫bindService,如果已經建立了onStartCommand方法
                 
                  第五點:生命週期
                                bindService->onCreate->onBind->Service Running->unBindService->onUnBind->onDestory
複製程式碼

3.Service外掛化架構設計實現? 3.1 角色劃分

          3.2 功能實現
複製程式碼

使用 AIDL 跨應用通訊 服務端(Server)

public class TestService extends Service {
    @Override
    public ComponentName startService(Intent service) {
        Log.i("main", "------startService------");
        return super.startService(service);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("main", "------onCreate------");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i("main", "------onStart------");
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("main", "------onStartCommand------");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean stopService(Intent name) {
        Log.i("main", "------stopService------");
        return super.stopService(name);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new TestBind();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("main", "------onDestroy------");
    }
    private class TestBind extends ITestServiceInterface.Stub{

        @Override
        public String getName() throws RemoteException {
            //處理相關業務邏輯
            return "我是A程式Service";
        }
    }
}
複製程式碼

AIDL 定義介面檔案ITestServiceInterface.aidl

interface ITestServiceInterface {

    String getName();
}
複製程式碼

清單檔案中AndroidManifest.xml

        <service
            android:name="com.haocai.architect.plugin.remoteservice.a.TestService"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
                <action android:name="com.haocai.architect.plugin.remoteservice.a.TestService" />
            </intent-filter>
        </service>
複製程式碼

服務端包名(com.haocai.architect.plugin.remoteservice.a)

客戶端(Server)

public class MainActivity extends AppCompatActivity {

   // 服務端包名(com.haocai.architect.plugin.remoteservice.a)
    private static final String ACTION_TEST_SERVICE = "com.haocai.architect.plugin.remoteservice.a.TestService";
    private Intent testIntent;
    private ITestServiceInterface asInterface;
    private TestConnection testConnection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testIntent = new Intent();
        testConnection = new TestConnection();
    }


    public void startRemoteService(View v) {

        //android 5.0以後直設定action不能啟動相應的服務,需要設定packageName或者Component。
        testIntent.setAction(ACTION_TEST_SERVICE);
        testIntent.setComponent(new ComponentName("com.haocai.architect.plugin.remoteservice.a", ACTION_TEST_SERVICE));

       // testIntent.setPackage("com.haocai.architect.plugin.remoteservice.a");
        testIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //繫結服務
        bindService(testIntent, testConnection, Context.BIND_AUTO_CREATE);

    }

    public void stopRemoteService(View v) {
        unbindService(testConnection);
    }
    @Override
    protected void onDestroy() {
        //解綁服務
        if (asInterface != null) {
            unbindService(testConnection);
        }
        super.onDestroy();
    }
    public void getName(View v) {
        Log.d("main name","NULL");
        if (asInterface != null) {
            try {
                String name = this.asInterface.getName();
                Log.d("main name",name);
                Toast.makeText(this, "name:" + name, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }



    // 定義接收器(建立連結)
    private class TestConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //通過服務端onBind方法返回的binder物件得到IMyService的例項,得到例項就可以呼叫它的方法了
            asInterface = ITestServiceInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            asInterface= null;
        }

    }

}
複製程式碼

目標介面:IPluginService 目標物件:PluginService(外掛Service基類) 代理物件:ProxyPluginService

3.2功能實現 第一步:定義目標介面 - IPluginService 第二步:定義目標物件 - PluginService 第三步:定義代理物件 - ProxyPluginService 第四步:實現目標物件具體的細節 第五步:實現代理物件具體的細節 - ProxyPluginService 第六步:在PluginManager類中新增啟動服務的方法 第七步:

相關文章