綁定服務

綁定服務是客戶端-服務器接口中的服務器。綁定服務可讓組件(例如 Activity)綁定到服務、發送請求、接收響應,甚至執行進程間通信 (IPC)。 綁定服務通常只在為其他應用組件服務時處于活動狀態,不會無限期在后臺運行。

綁定服務是 Service類的實現,可讓其他應用與其綁定和交互。要提供服務綁定,您必須實現 onBind()回調方法。該方法返回的 IBinder
對象定義了客戶端用來與服務進行交互的編程接口。

 public class LocalService extends Service {

    private IBinder mBind=new LocalBinder();
    /**
     * 返回的 IBinder 對象定義了客戶端用來與服務進行交互的編程接口
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBind;
    }

    /**
     * LocalBinder 為客戶端提供 getService() 方法,以檢索 LocalService 的當前實例
    */
    public class LocalBinder extends Binder{
        LocalService getService(){
            return LocalService.this;
        }
    }

    public void getLog(){
        Log.d("TAG", "getLog: 我是LocalService的log");
    }
}

客戶端可通過調用 [bindService()](https://developer.android.com/reference/android/content/Context.html?hl=zh-cn#bindService(android.content.Intent, android.content.ServiceConnection, int))綁定到服務。調用時,它必須提供 ServiceConnection的實現,后者會監控與服務的連接。[bindService()](https://developer.android.com/reference/android/content/Context.html?hl=zh-cn#bindService(android.content.Intent, android.content.ServiceConnection, int))方法會立即無值返回,但當 Android 系統創建客戶端與服務之間的連接時,會對 ServiceConnection
調用 [onServiceConnected()](https://developer.android.com/reference/android/content/ServiceConnection.html?hl=zh-cn#onServiceConnected(android.content.ComponentName, android.os.IBinder)),向客戶端傳遞用來與服務通信的 IBinder

public class MainActivity extends AppCompatActivity {
    LocalService service;
    boolean mBound = false;
    private ServiceConnection mConnection = new ServiceConnection() {
       @Override
        public void onServiceConnected(ComponentName name, IBinder iBinder) {
            LocalService.LocalBinder binder = (LocalService.LocalBinder) iBinder;
            service = binder.getService();
            service.getLog();
            mBound = true;
        }

        @Override
       public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

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

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

使用 Messenger

與 AIDL 比較

當您需要執行 IPC 時,為您的接口使用Messenger要比使用 AIDL 實現它更加簡單,因為 Messenger會將所有服務調用排入隊列,而純粹的 AIDL 接口會同時向服務發送多個請求,服務隨后必須應對多線程處理。
對于大多數應用,服務不需要執行多線程處理,因此使用 Messenger可讓服務一次處理一個調用。如果您的服務必須執行多線程處理,則應使用 AIDL 來定義接口。

如需讓服務與遠程進程通信,則可使用 Messenger 為您的服務提供接口。利用此方法,您無需使用 AIDL 便可執行進程間通信 (IPC)。

  • 服務實現一個 Handler,由其接收來自客戶端的每個調用的回調

  • Handler用于創建 Messenger對象(對 Handler的引用)

  • Messenger創建一個 IBinder,服務通過 onBind()使其返回客戶端

    public class MessengerService extends Service {
      /** Command to the service to display a message */
      static final int MSG_SAY_HELLO = 1;
    
      /**
       * Handler of incoming messages from clients.
       */
      class IncomingHandler extends Handler {
          @Override
          public void handleMessage(Message msg) {
              switch (msg.what) {
                  case MSG_SAY_HELLO:
                      Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                      break;
                  default:
                      super.handleMessage(msg);
              }
          }
      }
    
      /**
       * Target we publish for clients to send messages to IncomingHandler.
       */
      final Messenger mMessenger = new Messenger(new IncomingHandler());
    
      /**
       * 綁定到服務時,我們返回一個接口給我們的messenger為服務發送消息。
       */
      @Override
      public IBinder onBind(Intent intent) {
          Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
          return mMessenger.getBinder();
      }
     }
    
  • messenger類方法
    public IBinder getBinder() {
    return mTarget.asBinder();
    }
    public Messenger(Handler target) {
    mTarget = target.getIMessenger();
    }

客戶端只需根據服務返回的IBInder創建一個 Messenger,然后利用 send()發送一條消息。

public class ActivityMessenger extends Activity {
    /** Messenger for communicating with the service. */
    Messenger mService = null;

    /** Flag indicating whether we have called bind on the service. */
    boolean mBound;

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

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

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to the service
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

管理綁定服務的生命周期

當服務與所有客戶端之間的綁定全部取消時,Android 系統便會銷毀服務(除非還使用 [onStartCommand()](https://developer.android.com/reference/android/app/Service.html?hl=zh-cn#onStartCommand(android.content.Intent, int, int))啟動了該服務)。因此,如果您的服務是純粹的綁定服務,則無需對其生命周期進行管理 — Android 系統會根據它是否綁定到任何客戶端代您管理。
不過,如果您選擇實現 [onStartCommand()](https://developer.android.com/reference/android/app/Service.html?hl=zh-cn#onStartCommand(android.content.Intent, int, int))回調方法,則您必須顯式停止服務,因為系統現在已將服務視為已啟動。在此情況下,服務將一直運行到其通過 stopSelf()自行停止,或其他組件調用 stopService()為止,無論其是否綁定到任何客戶端。
此外,如果您的服務已啟動并接受綁定,則當系統調用您的 onUnbind()方法時,如果您想在客戶端下一次綁定到服務時接收 onRebind()調用,則可選擇返回 true。onRebind() 返回空值,但客戶端仍在其 [onServiceConnected()](https://developer.android.com/reference/android/content/ServiceConnection.html?hl=zh-cn#onServiceConnected(android.content.ComponentName, android.os.IBinder))
回調中接收 IBinder

生命周期
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容