12.Android学习之Service应用(一)
目錄
12.Service應用(一)
1.Service概述
1-1.Service 的分類
1-2.Service的生命周期
2.Service 的基本用法
2-1.創建與配置Service
2-2.啟動和停止Service
12.Service應用(一)
1.Service概述
Service (服務)是能夠在后臺長時間運行,并且不提供用戶界面的應用程序組件。其他應用程序組件能啟動Service,并且即便用戶切換到另一個應用程序,Service 還可以在后臺運行。此外,組件能夠綁定到Service并與之交互,甚至執行進程間通信(IPC)。例如,Service 能在后臺處理網絡事務、播放音樂、執行文件操作或者與Content Provider通信。
1-1.Service 的分類
Service按照啟動方式可以分為以下兩種類型。
◆Started Service:當應用程序組件(如Activity)通過調用startService() 方法啟動Service時,Service處于啟動狀態。一旦啟動, Service 能在后臺無限期運行。
◆Bound Service:當應用程序組件通過調用bindService()方法綁定到Service時,Service處于綁定狀態。多個組件可以同時綁定到一個Service 上,當它們都解除綁定時,Service 被銷毀。
Started Service與Bound Service的區別如表12.1所示。
表12.1 Started Service與Bound Service的區別
| 使用startService()方法啟動 | 調用bindService()方法綁定 |
| 通常只啟動,不返回值 | 發送請求,得到返回值 |
| 啟動Service的組件與Service之間沒有關聯,即使關閉該組件,Service也會一直運行 | 啟動Service的組件與Service綁定在一起, 如果關閉該組件,Service就會停止運行。 |
| 回調onStartCommand()方法,允許組件啟動Service | 目調onBind()方法,允許組件綁定Service |
注:Service可以同時屬于這兩種類型,既可以啟動(無限期運行)又能綁定。不管應用程序是否為啟動狀態、綁定狀態或者兩者兼有,都能通過Intent對象使用Service,就像使用Activity那樣。然而,開發人員可以在配置文件中將Service聲明為私有的,從而阻止其他應用程序訪問。
1-2.Service的生命周期
Service的生命周期比Activity簡單很多,但是卻需要開發人員更加關注Service如何創建和銷毀,因為Service可能在用戶不知情的情況下在后臺運行。
Service的生命周期可以分成兩個不同的路徑:
◆通過startService()方法啟動Service
當其他組件調用startService()方法時,Service 被創建,并且無限期運行,其自身必須調用stopSelf()方法或者其他組件調用stopService()方法來停止Service。當Service停止時,系統將其銷毀。
◆通過bindService()方法啟動Service
當其他組件調用bindService()方法時,Service 被創建,接著客戶端通過IBinder接口與Service通信,客戶端通過unbindService()方法關閉連接。多個客戶端能綁定到同一個Service,并且當它們都解綁定時,系統銷毀Service (Service 不需要被停止)。
這兩條路徑并非完全獨立,即開發人員可以綁定已經使用startService()方法啟動的Service。例如,后臺音樂Service能使用包含音樂信息的Intent 通過調用startService()方法啟動。當用戶需要控制播放器或者獲得當前音樂信息時,可以調用bindService()方法綁定Activity到Service。此時,只有stopService()和stopSelf()方法全部被客戶端解綁定時才能停止Service。
為了創建Service,開發人員需要創建Service類或其子類的子類。在實現類中,需要重寫一些處理Service生命周期重要方面的回調方法,并根據需要提供組件綁定到Service的機制。需要重寫的重要回調方法如表12.2所示。
| void onCreate() | 當Service第一次創建時, 系統調用該方法執行一次性建立過程(在系統調用onStartCommand() 或onBind()方法前)。如果Service已經運行,該方法不被調用 |
| void onStartCommand(Intent intent, int flags, int startld) | 當其他組件(如Activity)調用startService()方法請求Service啟動時,系統調用該方法。一且該方法執行,Service 就啟動并在后臺無限期運行 |
| IBinder onBind(Intent intent) | 該方法是Service子類必須實現的方法,該方法返回一個IBinder對象,應用程序可以通過該對象與Service組件進行通信 |
| void onDestroy() | 當Service不再使用并即將銷毀時,系統調用該方法 |
2.Service 的基本用法
應用程序組件(如Activity)能通過調用startService() 方法和傳遞Intent對象來啟動Service。在Intent對象中指定了Service 并且包含Service 需要使用的全部數據。Service 使用onStartCommand() 方法接收Intent。
Android提供了兩個類供開發人員繼承用于創建和啟動Service。
◆Service:這是所有Service 的基類。當繼承該類時,創建新線程來執行Service的全部工作是非常重要的。因為Service默認使用應用程序主線程,這可能降低應用程序Activity 的運行性能。
◆IntentService:這是Service 類的子類,它每次使用一個Worker線程來處理全部啟動請求。在不必同時處理多個請求時,這是最佳選擇。開發人員僅需要實現onHandleIntent() 方法,該方法接收每次啟動請求的Intent以便完成后臺任務。
2-1.創建與配置Service
使用Android Studio可以很方便地創建并配置Service,具體步驟如下:
在Module的包名(如com.example)節點上單擊鼠標右鍵,然后依次選擇New->Service->Service菜單項。
?注:如果選擇New->Service->Service(IntentService)菜單項,可以創建繼承IntentService的Service。
創建完成Service后,通常情況下,經常會重寫以下3個方法:
◆onCreate():在Service創建時調用。
◆onStartCommand():在每次啟動Service時調用。
◆onDestroy():在Service銷毀時調用。
例如,在創建的MyService中重寫這3個方法,實現開啟新線程模擬一段耗時操作,同時監控Service的狀態,具體代碼如下:
package com.example.demo01; ? import android.app.ActivityManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.util.Log; ? import java.util.ArrayList; ? public class MyService extends Service { ?public MyService() {} ?@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");} ?@Overridepublic void onCreate() {Log.i("Service","Service已創建");super.onCreate();} ?@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {Log.i("Service","Service已開啟");//模擬一段耗時任務long endTime=System.currentTimeMillis()+5*1000;while (System.currentTimeMillis()<endTime){synchronized (this){try {wait(endTime-System.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}stopSelf();//停止Service}}).start();return super.onStartCommand(intent, flags, startId);} ?@Overridepublic void onDestroy() {Log.i("Service","Service已停止");super.onDestroy();} }在創建Service之后,系統會自動在AndroidManifest.xml文件中配置Service,配置Service使用<service></service>標記。
?其中,enabled、exported兩個屬性的說明如下:
◆android:enabled
用于指定Service能否被實例化,true表示能,false表示不能,默認值是true。<application>標記也有自己的enabled屬性,適用于應用中所有的組件。當Service被啟用時,只有<application>和<service>標記的enabled屬性同時設置為true(兩者的默認值都是true)時,才能讓S<service>可用,非且能被實例化;任何一個是false,Service 都將被禁用。
◆android:exported
用于指定其他應用程序組件能否調用Service或者與其交互,true 表示能,false 表示不能。當該值是false時,只有同一個應用程序的組件或者具有相同用戶ID的應用程序啟動或者綁定到Service。
android:exported屬性的默認值依賴于Service是否包含Intent過濾器。若沒有過濾器,說明Service僅能通過精確類名調用,這意味著Service僅用于應用程序內部(因為其他程序可能不知道類名)。此時,默認值是false;若存在至少一個過濾器,暗示Service可以用于外部,因此默認值是true。
2-2.啟動和停止Service
1.啟動Service
可以通過Activity或者其他應用程序組件將Intent對象(要啟動的Service)傳遞到startService()方法中來啟動Service。Android 系統調用Service的onStartCommand()方法并將Intem傳遞給它。
例如,Activity 能使用顯式Intent和startService()方法啟動2-1小節中創建的Service(MyService),其代碼如下:
Intent Intent = new Intent(this,Myservice.class); ? startService(Intent);啟動MyService后,在Logcat中會輸出如圖所示的日志信息。
?在執行startService()方法后,Android 系統調用Service的onStartCommand()方法。如果Service還沒有運行,系統首先調onCreate()方法,接著調用onStartCommand()方法。
如果Service沒有提供綁定,startService() 方法發送的Intent 是應用程序組件和Service之間唯一的通信模式。然而,如果需要Service返回結果,則啟動該Service的客戶端能為廣播創建PendingIntent(使用getBradcast()方法)并通過啟動Service的Intent進行發送。Service接下來便能使用廣播來發送結果。
多次啟動Service的請求會導致Service的onStartCommand()方法被多次調用。
2.停止Service
已啟動的Service必須管理自己的生命周期,系統不會停止或銷毀Service,除非系統必須回收系統內存而且在onStartCommand()方法返回后Service繼續運行。因此,Service 必須調用stopSelf() 方法停止自身,或者其他組件調用stopService()方法停止Service。當多次啟動Service后,僅需要一個停止方法來停止Service。
當使用stopSelf()或stopService()方法請求停止時,系統會盡快銷毀Service。
注:應用程序應該在任務完成后停止Service,來避免系統資源浪費和電池消耗。即便是綁定Service,如果調用了onStartCommand()方法也必須停止Service。
例:
?MusicService.java
package com.example.backgroundmusicservice; ? import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; ? public class MusicService extends Service {public MusicService() {}static boolean isplay;//定義當前播放狀態MediaPlayer mediaPlayer;//聲明MediaPlayer對象 ?@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");} ?@Overridepublic void onCreate() {super.onCreate();//創建MediaPlayer對象并加載播放的音樂文件mediaPlayer=MediaPlayer.create(this,R.raw.music);} ?/******************實現音樂播放********************/@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if(!mediaPlayer.isPlaying()){//如果沒有播放音樂mediaPlayer.start();//播放音樂isplay=mediaPlayer.isPlaying();//當前狀態為正在播放音樂}return super.onStartCommand(intent, flags, startId);}/************************************************/ ?@Overridepublic void onDestroy() {mediaPlayer.stop();//停止音樂播放isplay=mediaPlayer.isPlaying();//當前狀態為沒有播放音樂mediaPlayer.release();//釋放資源super.onDestroy();} }MainActivity.java
package com.example.backgroundmusicservice; ? import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; ? import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ImageButton; ? public class MainActivity extends AppCompatActivity { ?@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ActionBar actionBar=getSupportActionBar();actionBar.hide(); ?ImageButton imageButton=findViewById(R.id.main_ib1);Intent intent=new Intent(MainActivity.this,MusicService.class); ?imageButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//啟動和停止MusicServiceif(MusicService.isplay==false){startService(intent);//啟動Service((ImageButton)view).setImageDrawable(getResources().getDrawable(R.drawable.play,null));}else {stopService(intent);//停止Service((ImageButton)view).setImageDrawable(getResources().getDrawable(R.drawable.stop,null));}}});} ?@Overrideprotected void onStart() {startService(new Intent(MainActivity.this,MusicService.class));//設置進入頁面默認啟動Servicesuper.onStart();} }注:如果沒有停止Service,即使關閉當前應用,音樂也將繼續播放。
總結
以上是生活随笔為你收集整理的12.Android学习之Service应用(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何进行WEB安全测试
- 下一篇: Android实验二:Activity的