Android 活動(activity)和服務(service)進行通訊
本片文章還是在Android 啟動和停止服務的基礎上進行修改,通過啟動和停止服務,不知道你有沒有發現,雖然服務是在活動裡啟動的,但是在啟動了服務之後,活動與服務基本就沒有什麼關係了,確實如此,我們在活動裡呼叫了startService()方法來啟動MyService這個服務,然後MyService的onCreate()和onStartCommand()方法就會得到執行,之後服務會一直處於執行狀態,但是具體執行的是什麼邏輯,活動就控制不了了,這就類似與活動通知了服務一下:"你可以啟動了!"然後服務就去忙自己的事情了,但活動並不知道服務到底去做什麼事情,以及完成得如何,
那麼有沒有什麼辦法能讓活動和服務的關係更緊密一些呢?例如在活動中指揮服務去幹什麼,服務就去幹什麼,當然可以,這就需要藉助我們剛剛忽略的onBind()方法了.
比如說,,目前我們希望在MyService裡提供一個下載功能,然後在活動中可以決定何時開始下載,以及隨時檢視下載進度,實現這個功能的思路是建立一個專門的Binder物件來對下載功能進行管理,修改MyService中的程式碼,如下:
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder{ public void startDownlad(){ Log.d(TAG, "startDownlad: executed"); } public int getProgress(){ Log.d(TAG, "getProgress: executed"); return 0; } } ... @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return mBinder; } ... }可以看到,這裡我們新建了一個DownloadBinder類,並讓它繼承自Binder,然後在它的內部提供了開始下載以及檢視下載進度的方法,當然這只是兩個模擬方法,並沒有實現真正的功能,我們在這兩個方法中分別列印了一行日誌.
接著,在MyService中建立了DownloadBinder的例項,然後在onBind()方法裡返回了這個例項,這樣MyService中的工作就全部完成了.
下面就要看一看,在活動中如何去呼叫服務裡的這寫方法了,首先需要在佈局檔案裡新增兩個按鈕,修改activity_main.xml中的程式碼,如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.servicetest.MainActivity"> ... <Button android:id="@+id/bind_service" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bind Service" android:textAllCaps="false" app:layout_constraintTop_toBottomOf="@id/stop_service"/> <Button android:id="@+id/unbind_service" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Unbind Service" android:textAllCaps="false" app:layout_constraintTop_toBottomOf="@id/bind_service"/> </android.support.constraint.ConstraintLayout>這兩個按鈕分別是用於繫結服務和取消服務的,那到底誰需要去和服務繫結呢?當然是活動了,當一個活動和服務繫結了之後,就可以呼叫該服務裡的Binder提供的方法了,修改MainActivity中的程式碼,如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private MyService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { downloadBinder = (MyService.DownloadBinder) iBinder; downloadBinder.startDownlad(); downloadBinder.getProgress(); } @Override public void onServiceDisconnected(ComponentName componentName) { } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... Button bindService = findViewById(R.id.bind_service); Button unbindService = findViewById(R.id.unbind_service); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ ... case R.id.bind_service: Intent bindIntent = new Intent(this,MyService.class); bindService(bindIntent,connection,BIND_AUTO_CREATE);//繫結服務 break; case R.id.unbind_service: unbindService(connection);//接觸繫結 break; default: break; } } }可以看到,這裡我們首先建立了一個ServiceConnection的匿名類,在裡面重寫了onServiceConnected()方法和onServiceDisConnected()方法,這兩個方法分別會在活動與服務成功繫結以及解除的時候呼叫,在onServiceConnected()方法中,我們又通過向下轉型得到了DownloadBinder的例項,有了這個例項,活動和服務之間的關係就變得非常緊密了,現在我們可以在活動中根據具體的場景來呼叫DownloadBinder中的任何public方法,即實現了指揮服務就去幹什麼的功能,這裡仍然只是做了個簡單的測試,在onServiceConnected()方法中呼叫了DownloadBinder的startDownload()和getProgress()方法.
當然,現在活動和服務其實還沒進行繫結呢,這個功能是在Bind Service按鈕的點選事件裡完成的,可以看到,這裡我們仍然是構建出了一個Intent物件,然後呼叫bindService()方法將MainActivity和MyService進行繫結,bindService()方法接收3個引數,第一個引數就是剛剛構建出的Intent物件,第二個引數是前面建立出的serviceConnection的例項,第三個引數則是一個標誌位,這裡傳入BIND_AUTO_CREATE表示在活動和服務進行繫結後自動建立服務,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行.
然後如果我們想接觸和服務之間的繫結該怎麼辦呢?呼叫一下unbindService()方法就可以了,這也是Unbind Service按鈕的點選事件裡實現的功能.
現在重新執行一下程式,如圖;
點選一下Bind Service按鈕,觀察logcat中的列印日誌,如圖:
可以看到,首先是MyService的onCreate()方法得到了執行,然後startDownload()和getProgress()方法都得到了執行,說明我們確實已經下活動裡成功呼叫了服務裡提供的方法了.
另外需要注意,任何一個服務在整個應用程式範圍內都是通用的,即MyService不僅可以和MainActivity繫結,還可以和任何一個其他的活動進行繫結,而且繫結完成後它們都可以獲取到相同的DownloadBinder例項.
相關文章
- Android中Service的啟動方式及Activity與Service的通訊方式Android
- ROS話題通訊和服務通訊的區別ROS
- Activity與Service通訊的方式有三種:
- Activity和Service跨程式通訊的兩種方式
- python實現兩臺不同主機之間進行通訊(客戶端和服務端)——SocketPython客戶端服務端
- android Fragments詳解五:與activity通訊AndroidFragment
- Android中活動間通訊總結Android
- Android 程式間通訊 Service、MessengerAndroidMessenger
- android native service編寫及兩個服務程式通訊Android
- Android Socket連線,使用Socket進行通訊(Android)Android
- Fragment與Activity通訊Fragment
- Android中使用HTTP和HttpClient進行通訊AndroidHTTPclient
- SpringCloud進行nacos的服務註冊和服務管理案例SpringGCCloud
- Android AIDL SERVICE 雙向通訊 詳解AndroidAI
- 通過串列埠進行通訊 :串列埠
- TCP通訊客戶端和服務端簡單程式碼實現TCP客戶端服務端
- Android Service 服務(一)—— ServiceAndroid
- Android Service 通知Activity更新介面的方法研究Android
- 基於node的tcp客戶端和服務端的簡單通訊TCP客戶端服務端
- Activity之間的通訊方式
- Android通過https協議與伺服器端進行通訊AndroidHTTP協議伺服器
- Android service裡面啟動activity和alertdialogAndroid
- Android中通過Messenger與Service實現程式間雙向通訊AndroidMessenger
- Android執行緒間通訊Android執行緒
- 活動(Activity)的基本操作
- 使用RSocket進行服務通訊的反應性服務簡介 - Rafał Kowalski
- Notification使用詳解之三:通過服務更新進度通知&在Activity中監聽服務進度
- 快速入門android AIDL(開啟多程式並進行通訊)AndroidAI
- Android中的執行緒通訊Android執行緒
- Android Service完全解析,關於服務你所需知道的一切(下)-程式間通訊Android
- 使用SuperSocket的FixedHeaderReceiveFilter進行通訊HeaderFilter
- 採用管道進行通訊的例子
- USB共享網路:android手機通過USB與Ubuntu進行socket網路通訊AndroidUbuntu
- Service Mesh大咖訪談:使用服務網格的微服務通訊與治理微服務
- Activity 與 Fragment 通訊(99%)完美解決方案Fragment
- 數字化轉型進行時:中企通訊量身定製雲服務
- $attrs 與 $listeners 進行「巢狀元件」通訊巢狀元件
- C++使用libcurl進行http通訊C++HTTP