androidservice啟動
『壹』 Android中服務service
本文原文連接 https://blog.csdn.net/wen20102321/article/details/53155736
Service是Android中的四大組件之一,它的級別和Activity差不多。只不過Service沒有頁面顯示,只能後台運行,可以和其他組件進行交互。
Service的後台運行並不是子線程,是在主線程中進行的,只是它沒有界面顯示。如果Service進行了耗時操作同樣需要開啟子線程,否則會跟Activity一樣出現ANR問題(application not response–程序沒有響應)。
補充說明:
主線程的內容包括UI和後台,只要程序中的UI或者後台其中一個在跑,程序都算是在運行狀態。
1,創建一個自己的TestService繼承Service
2,必須實現重寫其中的onBind方法,可以在里邊做各種操作,也可以接收傳遞過來的Intent的數據。
(在Android Studio中可以直接新建一個Service)
服務的注冊是四大組件中最簡單的一個,一般只要設置name屬性就可以了。
1,startService()啟動
(1)啟動服務startService:onCerate(),onStart()
(2)停止服務stopService:onDestroy()
此方法啟動服務,服務如果未被創建,系統會先調用onCreate()方法,接著調用onStrat()方法。如果調用startService前服務已經被啟動,多次調用啟動方法,不會多次調用onCreate,但會導致多次調用onStrat。
2,bindService()啟動
(1)綁定bindService:onCreate(),onBind()
(2)解除綁定unbindService:onUnbind()
(3)正常停止程序服務的方法是先接觸綁定unbindService,在停止服務stopService
綁定後調用stopService方法,這時候是不能停止服務的,如果這時再調用解綁unbindService,程序會先解綁,後停止服務。
用此方法啟動服務,在服務未被創建時,會先調用onCreate(),接著調用onBind()方法,這時候調用者和服務綁定在一起,調用者退出,系統會先調用服務的onUnbind(),然後onDestroy()。如果調用bindService之前服務已經被綁定,多次調用bindService並不會導致onCreate()和onBind()方法被多次調用。如果調用者想與正在綁定的服務解除綁定,可以調用unbindService()。
(1),onCerate()服務第一次被創建
(2),onStartComand()服務開始工作
(3),onBind()服務已經綁定
(4),onUnBind()服務解綁
(5),onDestroy()服務已經停止
普通的Service進行耗時操作要創建一個線程去完成,因為service是在主線程運行的,並且這個子線程完成工作要手動停止 。IntentService是繼承了Service並處理起步請求的一個類,在IntentService內有一個工作線程,來處理耗時操作,啟動IntentService的方式和啟動傳統的Service是一樣,當任務執行完成後,IntentService會自動停止,而不需要我們去控制。
可以啟動多次IntentService,每一個耗時操作會以工作隊列的方式在IntentService的onHandleIntent回調方法中執行,並且每次只會執行一個工作線程,執行完第一個再執行第二個,以此類推,而且,所有請求都在一個單線程中,不會阻塞主線程,同一時間只處理一個請求。
IntentService優點
1,省去了在Service中開線程的麻煩
2,當操作完成時,不用手動停止Service。IntentService是Service,但是比Service更智能。
『貳』 Android Service啟動Activity
Android Service 基礎知識點
我們都知道Activity中啟動Activity,只需要startActivity,如果在Service中啟動Activity呢?
在Service中啟動Activity,很多人說在非Activity中啟動Activity需要加FLAG_ACTIVITY_NEW_TASK flag,如果我不加會怎麼樣呢?
並沒有出現異常和崩潰,跳轉也是正常的,但是與之前所說的會崩潰報出異常不符合啊?!難道是與版本有關嗎?於是我使用了Android 23去測試果然拋出了異常
ContextImpl在Android studio中屬於隱藏源碼,在IDE中可能看不到,那就需要在SDK中去找 我的是:D:\AndroidSdk\sources\android-23\android\app\ContextImpl.java
可以看到只是判斷條件不同而已,android-23中發現沒有Intent.FLAG_ACTIVITY_NEW_TASK會直接拋出異常,而android-26中我們在非 Activity 調用 startActivity() 的時候,我們這個 options 通常是 null 的,所以在 26 之間的時候,誤把判斷條件 options == null 寫成了 options != null 導致進不去 if,從而不會拋出異常
附加:在android 24-android 27(即android N-android O)之間出現了bug,也就是說即使沒有加Intent.FLAG_ACTIVITY_NEW_TASK也會正常跳轉
可以很明顯看到判斷條件targetSdkVersion < Build.VERSION_CODES.N || targetSdkVersion >= Build.VERSION_CODES.P 即在24-27
看Activity中啟動Activity的源碼
Activity.startActivity() ->startActivityForResult()->mInstrumentation.execStartActivity() ...最終還是Ams去啟動Activity 也就是Activity中重寫了startActivity()方法所以不會出現這個異常
其實直觀很好理解,如果不是在Activity中啟動的,那就可以看做不是用戶主動的行為,也就說這個界面可能出現在任何APP之上,如果不用Intent.FLAG_ACTIVITY_NEW_TASK將其限制在自己的Task中,那用戶可能會認為該Activity是當前可見APP的頁面,這是不合理的。舉個例子:我們在聽音樂,這個時候如果郵件Service突然要打開一個Activity,如果不用Intent.FLAG_ACTIVITY_NEW_TASK做限制,那用戶可能認為這個Activity是屬於音樂APP的,因為用戶點擊返回的時候,可能會回到音樂,而不是郵件(如果郵件之前就有界面)
對比源碼發現,在我們非 Activity 調用 startActivity() 的時候,我們這個 options 通常是 null 的,所以在 24~27 之間的時候,誤把判斷條件 options == null 寫成了 options != null 導致進不去 if,從而不會拋出異常,如此我們使用 Context.startActivity() 的時候是一定要加上 FLAG_ACTIVITY_NEW_TASK 的,但是在 Android N 到 O-MR1,即 24~27 之間卻出現了 bug,即使沒有加也會正確跳轉
結語:感謝各位大佬的分享,對此有疑問的可以去運行跑一下,看一下相關的源碼,如有錯誤的需要改進的地方,請留言評論指出,謝謝!
參考文章:
『叄』 Android 開機自啟動service實踐
Android 設備啟動的時候,會發送android.intent.action.BOOT_COMPLETED的廣播,監聽這個廣播來實現開機自啟動。
1) 創建需要的service和 BroadcastReceiver
2) 在AndroidManifest.xml 注冊service 和BroadcastReceiver
3)申明許可權
```
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
}
『肆』 Android Service啟動方式
1.startService
①.定義一個類繼承service
②.在manifest.xml文件中配置該service
③.使用context的startService(intent)啟動該service
④.不再使用時,調用stopService(Intent)停止該服務
2.bindService
①.創建bindService服務段,繼承自service並在類中,創建一個實現binder介面的實例對象並提供公共方法給客戶端調用
②.從onbind()回調方法返回此binder實例
③.在客戶端中,從onserviceconnected()回調方法接收binder,並使用提供的方法調用綁定服務
『伍』 Android重學系列 Service 啟動和綁定原理
我們已經了解了BroadcastReceiver的原理,我們再來看看四大組件之一的Service是怎麼啟動的,以及怎麼運行的原理。
如果遇到什麼問題可以來到 https://www.jianshu.com/p/c4927c0b80a9 本文下進行交流
啟動Service的入口就是startService和bindService方法。我們先來看看startService在ContextImpl中做了什麼。
文件:/ frameworks / base / core / java / android / app / ContextImpl.java
此時調用的就是AMS的startService方法。
mServices是一個ActiveServices對象。這個對象是在AMS的構造函數中初始化好的。
這里調用了ActiveServices的startServiceLocked。
文件:/ frameworks / base / services / core / java / com / android / server / am / ActiveServices.java
核心流程有如下三個:
注意這里addToStarting是一個比較關鍵的判斷,addToStarting默認為false。
如果此時不是啟動前台服務,則需要進一步進行處理。如果ProcessRecord為空或者curProcState大於PROCESS_STATE_RECEIVER這個優先順序數值;也就是優先順序更小。
為了避免此時App應用是沒有任何的前台ui,或者App應用還沒有聲明。避免有的App通過startService進行應用的包活或者拉起應用。就會進行如下能夠存在的最大後台服務數量,則放入mDelayedStartList中進行延時啟動後台服務,現在直接返回了。
不然則說明能夠允許啟動後台服務, 就設置為addToStarting為true。
通過ComponentName也就是包名和類名查找ServiceRecord;通過Intent意圖過濾找到ServiceRecord。·
核心方法是bringUpServiceLocked。如果bringUpServiceLocked返回了異常,就返回一個特殊的ComponentName對象。
addToStarting為true,說明此時是一個能夠啟動的後台服務,則ServiceRecord添加到mStartingBackground中。如果mStartingBackground的數量為0,則直接調用ServiceMap的rescheleDelayedStartsLocked啟動後台服務。
這幾個關鍵的步驟,讓我們依次的考察,先來看看scheleCreateService中做了什麼。
如果第一次啟動就走第一個if的分支:
能看到和BroadcastReceiver的ANR思路一樣,通過一個延時的Handler,如果達到時間了還沒有移除這個Handler消息則報ANR異常。
這里根據啟動前台和後台分為兩種超時時間:
前台分別是10秒,後台服務不屬於後台進程組(判斷adj是否在SCHED_GROUP_BACKGROUND)是20秒,後台服務屬於後台進程組 200秒。
把數據封裝成CreateServiceData後,通過Handler調用如下方法:
透三點的核心原理可以看我寫的的Application創建和BroadcastReceiver原理兩篇文章。來看看Service中都做了什麼?
很簡單就是保存了傳遞過來的參數,值得注意的是這個IBinder對象其實就是指ServiceRecord對象。
接著執行Service.onCreate這個空實現的方法。
本質上還是調用了ActiveServices的serviceDoneExecutingLocked方法。
type是SERVICE_DONE_EXECUTING_ANON,所不會做更多的處理。 最後執行了serviceDoneExecutingLocked方法。
這個方法不斷的循環遍歷List<ServiceStartArgs>分發SERVICE_ARGS消息,這個消息通過主線程的Looper調用handleServiceArgs。
bindService在開發中用的不是很多,這里稍微提一下他的使用。
首先申明一個ServiceConnection對象,用於綁定服務端的Service。
調用bindService的方法綁定到某個Service中。當服務端的service成功回調onBind方法,我們只需要返回對應的Binder對象。就能使用調用bindService的客戶端在ServiceConnection的onServiceConnected的回調中獲得Binder對象。
之後就能通過這個Binder調用本進程或者其他進程的的方法了。實際上我們可以把這個過程看成一個多對多的服務-客戶端模型。多個客戶端通過Binder向多服務端Service通信,每一次我們都可以通過ComponentName判斷不同服務返回來的Binder對象。
這裡面很簡單,和BroadcastReceiver的思路很像。動態注冊的BroadcastReceiver會封裝成一個ReceiverDispatcher,而這里把ServiceConnection封裝成LoadedApk.ServiceDispatcher對象。
並且會把ServiceDispatcher作為value,ServiceConnection作為key緩存一個map中。並且以context為key,把這個臨時的map作為value緩存起來。這樣一個Context就映射有了多個ServiceDispatcher對象,也就可以注冊多個監聽被綁定Service狀態的監聽者了。
『陸』 android應用進程關閉怎麼啟動service
Service不是分離開的進程,除非其他特殊情況,它不會運行在自己的進程,而是作為啟動運行它的進程的一部分。
Service不是線程,這意味著它將在主線程里勞作。
啟動service有兩種方法:
Context.startService()調用者與服務之間沒有關聯,即使調用者退出,服務仍可運行
Context.bindService() 調用者與服務綁定在一起,調用者一旦退出,服務也就終止。
『柒』 Android如何啟用Service,如何停用Service。
1.第一種是通過調用Context.startService()啟動,調用Context.stopService()結束,startService()可以傳遞參數給Service
2.第二種方式是通過調用Context.bindService()啟動,調用Context.unbindservice()結束,還可以通過ServiceConnection訪問Service。
在Service每一次的開啟關閉過程中,只有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命周期中只能被調用一次。
『捌』 Android基礎:Service —— 默默為你服務
Service有兩種啟動方式,分別為 context.startService() 和 context.bindService() 。這里要提到Service的生命周期,兩種不同的啟動方式有不同的生命周期:
Tips:
首先創建自己的Service類,重寫其生命周期,並在mainfest.xml中進行注冊。
必須注冊Service,不然不會調用。簡單注冊:
補充下Service在manifest中的屬性以及作用:
接下來,我們就可以用下面的兩個方法來啟動和停止服務。
首先在我們的Activity中創建Service連接對象,重寫連接和斷開的方法。創建自定義的Binder對象,在 onServiceConnected() 中賦值然後可以調用自定義Binder中的方法。使用下方的bind()方法來綁定服務,使用 unBind() 來解綁服務。
這里會用到Service的 onBind() 和 onUnbind() 的生命周期,我們在TestService中重寫之。這里要注意的是,使用bindService()方法啟動的Service,不會調用 onStartCommand() 的生命周期。此外,創建自定義Binder類和對象。
這樣,當我們使用Activity中的bind()方法來綁定服務,會自動啟動服務,而我們又重寫了 onServiceConnected() 方法並使用myBinder來調用方法。這樣我們就可以用它來Activity和Service來進行通信。
特別Tips:
如果先使用 startService() 來開啟服務和 bindService() 來綁定服務,當使用 unbindService() 解綁時,Service並不會被銷毀。而是使用 stopService() 才能銷毀服務。
前台服務和後台服務的區別:
在Service中進行操作,將服務類型以前台的方式運行顯示在通知欄。
運行效果:
暫時引用吧,有空再實現一個:
參考資料: