一、項目介紹 【知識準備】 ①Android Interface definition language(aidl,android介面定義語言),其目的實現跨進程的調用。進程是程式在os中執行的載體,一個程式對應一個進程,不同進程就是指不同程式,aidl實現不同程式之間的調用。 ②主線程與子線程通信 ...
一、項目介紹
【知識準備】
①Android Interface definition language(aidl,android介面定義語言),其目的實現跨進程的調用。進程是程式在os中執行的載體,一個程式對應一個進程,不同進程就是指不同程式,aidl實現不同程式之間的調用。
②主線程與子線程通信使用handler,handler可以在子線程中發出消息,在主線程處理消息,從而完成線程之間的通信,即使有多個線程,仍然是一個程式。
③不同程式之間需要通過aidl通信,通信方式可以有多種,aidl是其中一種。實現的結果就像自己的程式調用自己的其他方法一樣,感覺就像一個程式。
④業務場景:例如購物app需要支付,購物app是淘寶,支付app是支付寶。所以就需要不同的程式進行通信。
二、首先介紹一個App之間的Service和Activity之間的通信
【項目結構】
【MyService】
【提示】
①創建Service
②如果不是通過上述方法創建,一定要記得註冊
1 <service
2 android:name=".MyService"
3 android:enabled="true"
4 android:exported="true"></service>
【代碼】
1 public class MyService extends Service {
2 public MyService() {
3 }
4
5 @Override
6 public IBinder onBind(Intent intent) {
7 return new MyBinder();//return MyBinder通過ServiceConnection在activity中拿到MyBinder
8 }
9
10 @Override
11 public int onStartCommand(Intent intent, int flags, int startId) {
12
13 return super.onStartCommand(intent, flags, startId);
14 }
15
16 public void payService(){
17 Log.i("MyService", "payService: --------");
18 }
19
20 class MyBinder extends Binder{
21
22 public void pay(){
23 payService();
24 }//通過Binder實例將service中的方法暴露出去
25 }
26 }
【layout_main】
添加按鈕,點擊便於調用
1 <Button
2 android:id="@+id/btn_paly"
3 android:text="Pay"
4 android:layout_width="wrap_content"
5 android:layout_height="wrap_content" />
【MainActivity】
1 public class MainActivity extends AppCompatActivity {
2
3 MyService.MyBinder binder = null;
4 ServiceConnection conn;
5
6 @Override
7 protected void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.activity_main);
10
11 Button btnPlay = (Button) findViewById(R.id.btn_paly);
12 conn = new ServiceConnection() {
13 @Override
14 public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
15 binder = (MyService.MyBinder) iBinder;
16 }
17
18 @Override
19 public void onServiceDisconnected(ComponentName componentName) {
20
21 }
22 };
23
24 Intent intent = new Intent(MainActivity.this,MyService.class);
25 bindService(intent,conn,BIND_AUTO_CREATE);//開啟服務
26
27 btnPlay.setOnClickListener(new View.OnClickListener() {
28 @Override
29 public void onClick(View view) {
30 if (binder!=null){
31 binder.play();
32 }
33 }
34 });
35 }
36 }
【效果】
點擊後輸出service中pay方法中的內容
三、兩個App之間的Service通信
【項目結構】
【步驟】
①在AppPayProvider中創建MyService
代碼同上
【註冊】
Ⅰ、註冊時(android:enabled="true" android:exported="true")設置為true,將Service暴露出去,另一個App才能訪問到它
Ⅱ、添加『<intent-filter>』。由於不是同一個App,通過intent-filter對Intent進行過濾,讓另一個app通過action開啟服務
1 <service
2 android:name=".MyService"
3 android:enabled="true"
4 android:exported="true">
5 <!--enable:ture設置可用
6 exported:ture對外暴露 -->
7 <intent-filter>
8 <action android:name="com.xqz.apppayprovider.MyService" />
9 </intent-filter>
10 </service>
②MainActivity和layout_main保留創建時不作任何修改,但也不要刪掉,因為安裝程式必須提供起始頁面,否則將會出錯
③在AppPayProvider中添加AIDL
【代碼】
【提示】介面中定義中方法要和Service中的MyBinder中的方法一致
④再創建好AIDL,添加完方法後,android studio需要對這個aidl進行編譯,會自動按aidl規範生成一個Binder子類的代碼。
⑤對MyService中的MyBinder進行修改
【提示】繼承IPay.Stub。在這之前必須Make Project,否則將沒有隻能聯想
⑥創建AppPayUser對AppPayProvider中的MyService進行操作
【layout-main】
1 <Button
2 android:id="@+id/btnPay"
3 android:text="pay"
4 android:layout_width="wrap_content"
5 android:layout_height="wrap_content" />
⑦將AppPayProvider中AIDL拷貝到AppPayUser中
【提示】Ⅰ、包名要相同,按目錄位置複製,通過下述方法,直接在文件夾進行複製。『此處可以查看項目結構,可以看到包名是相同的』
Ⅱ、同樣拷貝過來後需要Make Project
⑧【AppPayUser-MainActivity】
1 public class MainActivity extends AppCompatActivity {
2
3 Button btnPay;
4 private IPay myBinder;//定義AIDL
5
6 ServiceConnection conn = new ServiceConnection() {
7 @Override
8 public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
9
10 myBinder = IPay.Stub.asInterface(iBinder);
11 }
12
13 @Override
14 public void onServiceDisconnected(ComponentName componentName) {
15
16 }
17 };
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_main);
23
24 Intent intent = new Intent();
25 intent.setAction("com.xqz.apppayprovider.MyService");
26 //表示按照什麼進行過濾,啟動意圖
27 /*android5.0之後,如果servicer不在同一個App的包中,
28 需要設置service所在程式的包名
29 (包名可以到App的清單文件AndroidManifest中查看)*/
30 intent.setPackage("com.xqz.apppayprovider");
31 bindService(intent,conn,BIND_AUTO_CREATE);//開啟Service
32
33 btnPay = (Button) findViewById(R.id.btnPay);
34
35 btnPay.setOnClickListener(new View.OnClickListener() {
36 @Override
37 public void onClick(View view) {
38 try {
39 myBinder.pay();
40 } catch (RemoteException e) {
41 //因為是跨程式調用服務,可能會出現遠程異常
42 e.printStackTrace();
43 }
44 }
45 });
46 }
47 }
【安裝】
先安裝AppPayProvider再安裝AppPayUser。
【效果】
將run中的 視圖調到AppPayProvider,點擊模擬器AppPayUser中的pay按鈕,將會執行AppPayProvider中MyService中pay方法中的內容。
四、總結
【跨App和同App之間的區別】
①跨App開啟服務是提供服務的App需要設置intent-filter過濾器,控制服務的App需要通過。setAction和setPackage方法進行設置action和包名,才能開啟服務。而同App只需要指定啟動的service就可。
②跨App的MyBinder實例要通過AIDL獲取,兩個應用定義同樣的介面的方法,通過對應的AIDL名稱.Stub.asInterface方法得到binder實例,然後就和同App的myBinder使用麽有區別了。
③跨App的MyBinder對象的使用必須捕獲異常,而同App不需要。
④可以根據上方簡單的例子實現很多類似的功能。