Android實現進程之間通信

Android實現進程之間通信詳解

Android的每個應用程序都是一個不同的進程,在Android平臺一個進程通常不能訪問另一個進程的內存空間。

比如一個應用程序有兩個進程,一個進程負責UI的展示,而另一個進程(通常是在此進程中使用一個service)用來進行網絡資源的請求,需要主進程和服務進程之間進行數據的傳遞。(微信就是使用的這種機制)
Android提供了AIDL來實現進程間通信(IPC),AIDL全稱爲Android Interface Definition Language。

AIDL IPC機制是面向接口的,使用代理類在客戶端和服務端之間進行數據傳遞。


使用AIDL實現IPC服務需要分別實現服務端和客戶端。實例源碼下載:點擊下載


服務端:


1、新建aidl文件定義服務端和客戶端交互的接口(包括數據接口);
adil文件定義規範:
在服務端的src目錄下新建以.aidl爲後綴的文件,在這個文件中定義接口,聲明服務端和客戶端交互的api,語法和普通java接口聲明一樣,可以添加中英文註釋。
區別:
a、除了Java基本數據類型 (int, long, char, boolean等)、String、CharSequence、List、Map外,其他複雜類型都需要顯式import(包括其他AIDL定義的接口),即便是在同一個包內定義。
b、支持泛型實例化的List,如List<String>;不支持泛型實例化的Map,如Map<String, String>。對於List爲參數接收者接收到的始終是ArrayList;對於Map爲參數接收者接收到的始終是HashMap。
c、interface和函數都不能帶訪問權限修飾符。
d、接口內只允許定義方法,不允許定義靜態屬性。

[java] view plaincopy

    package com.snail.test.aidl.server;  
      
    import com.snail.test.aidl.server.Person;  
    interface IAIDLServerService {  
      
         Person getPerson();  
    }  

aidl文件新建完成後,adt工具會自動編譯aidl文件,大家可以在gen目錄看到對應的java文件。
文件中主要有:
a、抽象類Stub,繼承Binder實現自定義接口,作用同進程內通信服務中自定義的Binder,客戶端通過它對服務進行調用。
b、靜態類Proxy,實現自定義接口,代理模式接收對Stub的調用。

2、新建service實現定義的接口。

接口中傳遞的對象數據需要實現序列化接口,並且也要定義aidl文件。

[java] view plaincopy

    public class AIDLServerService extends Service {  
      
        /**
         * 返回綁定
         */  
        @Override  
        public IBinder onBind(Intent intent) {  
            return mBinder;  
        }  
      
        /**
         * 初始化根據AIDL文件生成的Stub
         */  
        private IAIDLServerService.Stub mBinder = new Stub() {  
      
            /**
             * 實現定義的接口
             */  
            public Person getPerson() throws RemoteException {  
                Person mBook = new Person();  
                mBook.setName("Snail");  
                mBook.setAge(27);  
                return mBook;  
            }  
        };  
      
    }  


客戶端:

1、在工程中定義服務端和客戶端交互的接口,跟服務端的一模一樣,包名也要一樣,不然會報錯java.lang.SecurityException: Binder invocation to an incorrect interface。


2、通過Stub.asInterface方法獲取服務來使用定義的接口實現進程間的通信。

[java] view plaincopy

    public class MainActivity extends Activity {  
      
        private Button mAIDLBtn;  
        private TextView mAIDLView;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            mAIDLBtn = (Button) findViewById(R.id.aidl_btn);  
            mAIDLView = (TextView) findViewById(R.id.aidl_text);  
      
            mAIDLBtn.setOnClickListener(new OnClickListener() {  
                public void onClick(View v) {  
                    // 綁定服務,這裏的service action非常重要,要跟server端定義的action一致  
                    Intent service = new Intent(  
                            "com.snail.test.aidl.server.AIDLServerService");  
                    bindService(service, mConnection, BIND_AUTO_CREATE);  
                }  
      
            });  
        }  
      
        private IAIDLServerService mIaidlServerService = null;  
      
        /** 好資料七七八八網尖鋒網推薦
         * 服務連接
         */  
        private ServiceConnection mConnection = new ServiceConnection() {  
      
            public void onServiceDisconnected(ComponentName name) {  
                mIaidlServerService = null;  
            }  
      
            /**
             * 服務連接成功
             */  
            public void onServiceConnected(ComponentName name, IBinder service) {  
                mIaidlServerService = IAIDLServerService.Stub.asInterface(service);  
                // aidl實現進程間通信  
                try {  
                    Person person = mIaidlServerService.getPerson();  
                    String str = "姓名:" + person.getName() + "\n" + "年齡:"  
                            + person.getAge();  
                    mAIDLView.setText(str);  
                } catch (RemoteException e) {  
                    e.printStackTrace();  
                }  
            }  
        };  
    }  


客戶端和服務端的service生命週期:

客戶端通過bindService綁定服務,若服務未啓動,會先執行Service的onCreate函數,

再執行onBind函數,最後執行ServiceConnection對象的onServiceConnected函數,

客戶端可以自動啓動服務。若服務已啓動但尚未綁定,先執行onBind函數,

再執行ServiceConnection對象的onServiceConnected函數。若服務已綁定成功,則直接返回。

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