Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android:遠程服務Service(含AIDL & IPC講解)

Android:遠程服務Service(含AIDL & IPC講解)

編輯:關於Android編程

前言

Service作為Android四大組件之一,應用非常廣泛 本文將介紹Service其中一種常見用法:遠程Service

目錄

目錄


1. 遠程服務與本地服務的區別

遠程服務與本地服務最大的區別是:遠程Service與調用者不在同一個進程裡(即遠程Service是運行在另外一個進程);而本地服務則是與調用者運行在同一個進程裡 二者區別的詳細區別如下圖:

按運行地點分類


2. 使用場景

多個應用程序共享同一個後台服務(遠程服務)

即一個遠程Service與多個應用程序的組件(四大組件)進行跨進程通信

使用場景


3. 具體使用

為了讓遠程Service與多個應用程序的組件(四大組件)進行跨進程通信(IPC),需要使用AIDL

IPC:Inter-Process Communication,即跨進程通信 AIDL:Android Interface Definition Language,即Android接口定義語言;用於讓某個Service與多個應用程序組件之間進行跨進程通信,從而可以實現多個應用程序共享同一個Service的功能。

在多進程通信中,存在兩個進程角色(以最簡單的為例):服務器端和客戶端

以下是兩個進程角色的具體使用步驟:
服務器端(Service)
步驟1:新建定義AIDL文件,並聲明該服務需要向客戶端提供的接口
步驟2:在Service子類中實現AIDL中定義的接口方法,並定義生命周期的方法(onCreat、onBind()、blabla)
步驟3:在AndroidMainfest.xml中注冊服務 & 聲明為遠程服務

客戶端(Client)
步驟1:拷貝服務端的AIDL文件到目錄下
步驟2:使用Stub.asInterface接口獲取服務器的Binder,根據需要調用服務提供的接口方法
步驟3:通過Intent指定服務端的服務名稱和所在包,綁定遠程Service

接下來,我將用一個具體實例來介紹遠程Service的使用


4. 具體實例

實例描述:客戶端遠程調用服務器端的遠程Service 具體使用:

4.1 服務器端(Service)

新建一個服務器端的工程:Service - server

先下Demo再看,效果會更好:Github_RemoteService_Server

步驟1. 新建一個AIDL文件

新建AIDL文件

步驟2. 在新建AIDL文件裡定義Service需要與Activity進行通信的內容(方法),並進行編譯(Make Project)<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> // 在新建的AIDL_Service1.aidl裡聲明需要與Activity進行通信的方法 package scut.carson_ho.demo_service; interface AIDL_Service1 { void AIDL_Service(); } //AIDL中支持以下的數據類型 //1. 基本數據類型 //2. String 和CharSequence //3. List 和 Map ,List和Map 對象的元素必須是AIDL支持的數據類型; //4. AIDL自動生成的接口(需要導入-import) //5. 實現android.os.Parcelable 接口的類(需要導入-import)

編譯

步驟3:在Service子類中實現AIDL中定義的接口方法,並定義生命周期的方法(onCreat、onBind()、blabla)
MyService.java

public class MyService extends Service {

    // 實例化AIDL的Stub類(Binder的子類)
    AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {

        //重寫接口裡定義的方法
        @Override
        public void AIDL_Service() throws RemoteException {
            System.out.println("客戶端通過AIDL與遠程後台成功通信");
        }
    };

//重寫與Service生命周期的相關方法
    @Override
    public void onCreate() {
        super.onCreate();

        System.out.println("執行了onCreat()");

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("執行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("執行了onDestory()");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        System.out.println("執行了onBind()");
    //在onBind()返回繼承自Binder的Stub類型的Binder,非常重要
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("執行了onUnbind()");
        return super.onUnbind(intent);
    }

}

步驟4:在AndroidMainfest.xml中注冊服務 & 聲明為遠程服務


            //該Service可以響應帶有scut.carson_ho.service_server.AIDL_Service1這個action的Intent。
            //此處Intent的action必須寫成“服務器端包名.aidl文件名”
            
                
            

        

至此,服務器端(遠程Service)已經完成了。

4.2 客戶端(Client)

新建一個客戶端的工程:Service - Client

先下Demo再看,效果會更好:Github_RemoteService_Client

步驟1:將服務端的AIDL文件所在的包復制到客戶端目錄下(Project/app/src/main),並進行編譯

注:記得要原封不動地復制!!什麼都不要改!

復制後的目錄

步驟2:在主布局文件定義“綁定服務”的按鈕
MainActivity.xml


步驟3:在MainActivity.java裡

使用Stub.asInterface接口獲取服務器的Binder; 通過Intent指定服務端的服務名稱和所在包,進行Service綁定; 根據需要調用服務提供的接口方法。

MainActivity.java

public class MainActivity extends AppCompatActivity {

        private Button bindService;

        //定義aidl接口變量
        private AIDL_Service1 mAIDL_Service;

        //創建ServiceConnection的匿名類
        private ServiceConnection connection = new ServiceConnection() {

            //重寫onServiceConnected()方法和onServiceDisconnected()方法
            //在Activity與Service建立關聯和解除關聯的時候調用
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }

            //在Activity與Service建立關聯時調用
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

                //使用AIDLService1.Stub.asInterface()方法獲取服務器端返回的IBinder對象
                //將IBinder對象傳換成了mAIDL_Service接口對象
                mAIDL_Service = AIDL_Service1.Stub.asInterface(service);

                try {

                    //通過該對象調用在MyAIDLService.aidl文件中定義的接口方法,從而實現跨進程通信
                    mAIDL_Service.AIDL_Service();

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        };


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            bindService = (Button) findViewById(R.id.bind_service);

            //設置綁定服務的按鈕
            bindService.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    //通過Intent指定服務端的服務名稱和所在包,與遠程Service進行綁定
                    //參數與服務器端的action要一致,即"服務器包名.aidl接口文件名"
                    Intent intent = new Intent("scut.carson_ho.service_server.AIDL_Service1");

                    //Android5.0後無法只通過隱式Intent綁定遠程Service
                    //需要通過setPackage()方法指定包名
                    intent.setPackage("scut.carson_ho.service_server");

                    //綁定服務,傳入intent和ServiceConnection對象
                    bindService(intent, connection, Context.BIND_AUTO_CREATE);

                }
            });
        }

    }

4.3 測試結果

點擊綁定服務按鈕

從上面測試結果可以看出:

打印的語句分別運行在不同進程(看語句前面的包名); 客戶端調用了服務端Service的方法

客戶端和服務端進行了跨進程通信

4.4 Demo地址

客戶端:Github_RemoteService_Client 服務端:Github_RemoteService_Server
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved