Service跨應用的用法和通信

一)跨應用啓動Service

有時候我們需要在一個程序裏面啓動另一個程序的服務,在Android5.0之前可以跟跨應用啓動Activity的方法相似,使用action的隱式Intent來啓動,但是現在5.0之後必須用顯示Intent來啓動,那麼怎麼顯式啓動一個跨程序的Service呢?

答案是通過Intent的setComponent(),傳入的ComponetName()第一個參數是要啓動的Service所在的程序包名,第二個通過全路徑名字傳入Service。這樣就是顯示使用Intent.

 serviceIntent = new Intent();
        serviceIntent.setComponent(new ComponentName("demo.com.servicetest",
                "demo.com.servicetest.MyService"));
然後在按鈕裏就可以直接啓動

 btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(serviceIntent);
            }
        });

        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(serviceIntent);
            }
        });

二)跨應用綁定Service

先在Service裏面新建一個AIDL文件,系統會自動的實現一些抽象類,然後我們可以在onBind()裏返回這個AIDL文件的類型

  return new IMyAidlInterface.Stub() {
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

            }
        };
    }
如果系統沒有找到這個AIDL名字,我們需要在build選項裏選擇ReBuild Project.

然後在另一個程序裏啓動Service

   serviceIntent=new Intent();
        serviceIntent.setComponent(new ComponentName("demo.com.servicetest","demo.com.servicetest.MyService"));
        bindService= (Button) findViewById(R.id.btn_bindService);
        bindService .setOnClickListener(this);
        unbindService= (Button) findViewById(R.id.btn_unbindService);
        unbindService.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_bindService:
                bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btn_unbindService:
                unbindService(this);
        }
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        System.out.println("Bind Service");
        System.out.println(service);

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
bindService()傳入的三個參數,第一個是Intent,第二個是ServiceConnection,傳入this需要重寫它的兩個方法

onServiceConnected
還有
onServiceDisconnected
第三個參數是綁定的類型

然後unbindService()傳入的參數也是Service Connection.

這樣就實現跨程序綁定服務了。

三)跨程序綁定Service並且通信

綁定服務的目的就是爲了通信,那麼如何在另一個程序裏實現跨程序通信呢?答案仍然是AIDL機制。

比如我們在某個Service裏打印數據出來,在已經綁定此服務的另一個程序裏面進行改變數據,使Service輸出的數據發生改變。

首先在AIDL文件裏定義一個設置數據方法setData()

// IMyAidlInterface.aidl
package demo.com.servicetest;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    setData(String data);

然後ReBuild Project會報錯,因爲在Service裏面沒有這個方法,我們需要在Service裏聲明setData(),在這個方法裏實現改變數據的功能。

 @Override
    public IBinder onBind(Intent intent) {

        return new IMyAidlInterface.Stub() {
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

            }

         @Override
            public void setData(String data) throws RemoteException {
                MyService.this.data=data;
            }
        };
    }

在Service的onCreate()裏開一個線程,每隔一秒鐘打印一次data,方便我們觀察結果

 @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("create service");
  
          new Thread(){
            @Override
            public void run() {
                super.run();

                 runing=true;
                while (runing){
                    System.out.println(data);

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("destory service");
        runing=false;
    }

然後要在另一個程序裏綁定Service,並且改變data的值,綁定Service的方法本文第二條剛剛寫過,那麼如何進行通信呢?

我們需要新建AIDL文件,並且包名要和Service所在程序的AIDL文件所在的包名一樣,然後將AIDL文件複製到這個包下面即可。

然後定義AIDL對象binder,設置爲null,注意在onSerivceConnected()裏給binder實例化,不能直接把service賦值給它強制類型轉換,因爲AIDL是在兩個不同的程序聲明的,雖然內容一樣,但是內存不一樣,不是同一個,不能直接強制轉換類型。

  private IMyAidlInterface binder=null;

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        System.out.println("Bind Service");
        System.out.println(service);

      binder=IMyAidlInterface.Stub.asInterface(service);
    }
在按鈕的點擊事件裏將EditText的內容傳給AIDL的setData()

注意setData要進行捕獲異常,如果在Android Studio裏面,alt+enter可以方便的進行捕獲異常

case R.id.btn_sync:
                   if (binder!=null){
                       try {
                           binder.setData(et.getText().toString());
                       } catch (RemoteException e) {
                           e.printStackTrace();
                       }
                   }
這個時候編譯運行程序,點擊btn_sync的話,Service所在的程序就會輸出我們傳進去的值,而原來的值被改變,這也就是實現了跨程序綁定服務的通信功能,主要運用了安卓的AIDL機制,注意AIDL的使用方法。




發佈了49 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章