Android進程間通訊之重識AIDL

前言

就像一部電影原諒慘敗的票房,我走在街上,悶着頭遊蕩,把心事流放。

簡介

在之前的一篇文章中點擊查看,我們曾講過Android中AIDL的使用,它可以實現進程間的通信。今天來整理之前寫的東西,突然發現了新的問題。
由於本次博文是基於之前的AIDL文章來寫的,所以今天我們只是大概做個總結,如果你還沒有看過我之前寫的關於AIDL的文章點擊打開鏈接,可以先去閱讀下。

項目結構

1. 服務端

這裏寫圖片描述

2. 客戶端

這裏寫圖片描述

問題

1. 隱式啓動service代碼

 private void startService() {
        Intent intent = new Intent();
        intent.setAction("service.DataService");
        conn = new MyServiceConnection();
        bindService(intent, conn, BIND_AUTO_CREATE);
 }

2. 運行截圖(Android 6.0系統)

這裏寫圖片描述
這是當我們點擊按鈕綁定服務時產生的crash,原因是“Service Intent must be explicit(顯式地)”,意思是“與服務相關的intent必須顯式地綁定”。
原來從Android 5.0之後,爲了安全性考慮,google就不建議隱式地啓動服務,而必須要顯示指定。

3. 處理

轉換爲顯式地Intent

public class IntentUtil {

    public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
        // Retrieve all services that can match the given intent
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
        // Make sure only one match was found
        if (resolveInfo == null || resolveInfo.size() != 1) {
            return null;
        }
        // Get component info and create ComponentName
        ResolveInfo serviceInfo = resolveInfo.get(0);
        String packageName = serviceInfo.serviceInfo.packageName;
        String className = serviceInfo.serviceInfo.name;
        ComponentName component = new ComponentName(packageName, className);
        // Create a new intent. Use the old one for extras and such reuse
        Intent explicitIntent = new Intent(implicitIntent);
        // Set the component to be explicit
        explicitIntent.setComponent(component);
        return explicitIntent;
    }

}

根據api版本進行intent的顯式轉換:

private void startService() {
        Intent intent = new Intent();
        intent.setAction("service.DataService");
        Intent explicitIntent;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            explicitIntent = IntentUtil.getExplicitIntent(this, intent);
        } else {
            explicitIntent = intent;
        }
        conn = new MyServiceConnection();
        bindService(explicitIntent, conn, BIND_AUTO_CREATE);
    }

我們在系統api版本大於21的情況下做了intent的顯式轉換。

4. 運行截圖

通過轉換,我們成功訪問到了服務端定義的方法。

這裏寫圖片描述

總結

由於Android系統本身就處在一個不斷迭代的過程,所以有可能我們之前寫的東西在運行到最新的系統上時會出問題,這就要求我們要勤于思索,善於實踐,這樣才能發現我們在寫代碼中所犯的失誤,從而更好地提高我們自己。

源碼

服務端源碼
https://github.com/kuangxiaoguo0123/ATAidlStudy
客戶端源碼
https://github.com/kuangxiaoguo0123/ATAidlNative

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章