摘要:用戶(hù)可以手動(dòng)添加自啟動(dòng)應(yīng)用,添加后的應(yīng)用中如果回調(diào)返回值是或,當(dāng)用戶(hù)在小米手機(jī)上長(zhǎng)按鍵結(jié)束后,接下來(lái)未來(lái)的某個(gè)時(shí)間內(nèi),當(dāng)系統(tǒng)內(nèi)存足夠可用時(shí),依然可以按照上述規(guī)定重啟。
Android Service
Service通??偸欠Q(chēng)之為“后臺(tái)服務(wù)”,其中“后臺(tái)”一詞是相對(duì)于前臺(tái)而言的,具體是指其本身的運(yùn)行并不依賴(lài)于用戶(hù)可視的UI界面,因此,從實(shí)際業(yè)務(wù)需求上來(lái)理解,Service的適用場(chǎng)景應(yīng)該具備以下條件:
并不依賴(lài)于用戶(hù)可視的UI界面(當(dāng)然,這一條其實(shí)也不是絕對(duì)的,如前臺(tái)Service就是與Notification界面結(jié)合使用的)
具有較長(zhǎng)時(shí)間的運(yùn)行特性
基礎(chǔ)知識(shí)定義:Android中的計(jì)算型組件
作用:提供需要在后臺(tái)長(zhǎng)期運(yùn)行的服務(wù)(如復(fù)雜計(jì)算、下載等等)
特點(diǎn):長(zhǎng)生命周期的、沒(méi)有用戶(hù)界面、在后臺(tái)運(yùn)行
定義Service下面代碼片段顯示的是一個(gè)最基本的Started Service的自定義方式:
public class MyService extends Service { public static final String TAG = "MyService"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.w(TAG, "in onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.w(TAG, "in onStartCommand"); Log.w(TAG, "MyService:" + this); String name = intent.getStringExtra("name"); Log.w(TAG, "name:" + name); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); Log.w(TAG, "in onDestroy"); } }
onBind(...)函數(shù)是Service基類(lèi)中的唯一抽象方法,子類(lèi)都必須重寫(xiě)實(shí)現(xiàn),此函數(shù)的返回值是針對(duì)Bound Service類(lèi)型的Service才有用的,在Started Service類(lèi)型中,此函數(shù)直接返回 null 即可。
onCreate(...)、onStartCommand(...)和onDestroy()都是Started Service相應(yīng)生命周期階段的回調(diào)函數(shù)。
一般而言,從Service的啟動(dòng)方式上,可以將Service分為Started Service和Bound Service。無(wú)論哪種具體的Service啟動(dòng)類(lèi)型,都是通過(guò)繼承Service基類(lèi)自定義而來(lái)。在使用Service時(shí),要想系統(tǒng)能夠找到此自定義Service,無(wú)論哪種類(lèi)型,都需要在AndroidManifest.xml中聲明,語(yǔ)法格式如下:
android:exported=["true" | "false"] android:icon="drawable resource" android:isolatedProcess=["true" | "false"] android:label="string resource" android:name="string" android:permission="string" android:process="string" > . . .
android:exported——能否接收其他App的發(fā)出的信息,這個(gè)屬性默認(rèn)值有點(diǎn)意思,其默認(rèn)值是由有無(wú)intent-filter決定的,如果有intent-filter,默認(rèn)值為true,否則為false。(receiver/activity/service中的此屬性默認(rèn)值遵循此規(guī)則)同時(shí),需要注意的是,這個(gè)值的設(shè)定是以application或者application user id為界的,而非進(jìn)程為界(一個(gè)應(yīng)用中可能含有多個(gè)進(jìn)程)
android:name ——對(duì)應(yīng)Service類(lèi)名
android:permission ——是權(quán)限聲明
android:process ——詳情
Started Service相對(duì)比較簡(jiǎn)單,通過(guò)context.startService(Intent serviceIntent)啟動(dòng)Service,context.stopService(Intent serviceIntent)停止此Service。當(dāng)然,在Service內(nèi)部,也可以通過(guò)stopSelf(...)方式停止其本身。
以下是代碼測(cè)試片段:
public class MainActivity extends Activity { public static final String TAG = "MainActivity"; private Button startServiceBtn; private Button stopServideBtn; private Intent serviceIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startServiceBtn = (Button) findViewById(R.id.start_service); stopServideBtn = (Button) findViewById(R.id.stop_service); startServiceBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { serviceIntent = new Intent(MainActivity.this, MyService.class); startService(serviceIntent); } }); stopServideBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(serviceIntent); } }); } @Override protected void onDestroy() { super.onDestroy(); Log.w(TAG, "in onDestroy"); } }調(diào)用流程
當(dāng)Client調(diào)用startService(Intent serviceIntent)后,如果MyService是第一次啟動(dòng),首先會(huì)執(zhí)行 onCreate()回調(diào),然后再執(zhí)行onStartCommand(Intent intent, int flags, int startId),當(dāng)Client再次調(diào)用startService(Intent serviceIntent),將只執(zhí)行onStartCommand(Intent intent, int flags, int startId),因?yàn)榇藭r(shí)Service已經(jīng)創(chuàng)建了,無(wú)需執(zhí)行onCreate()回調(diào)。無(wú)論多少次的startService,只需要一次stopService()即可將此Service終止,執(zhí)行onDestroy()函數(shù)(其實(shí)很好理解,因?yàn)閛nDestroy()與onCreate()回調(diào)是相對(duì)的)
onStartCommand方法onStartCommand(Intent intent, int flags, int startId)
其中參數(shù)flags默認(rèn)情況下是0,對(duì)應(yīng)的常量名為START_STICKY_COMPATIBILITY
startId是一個(gè)唯一的整型,用于表示此次Client執(zhí)行startService(...)的請(qǐng)求請(qǐng)求標(biāo)識(shí),在多次startService(...)的情況下,呈現(xiàn)0,1,2....遞增。
另外,此函數(shù)具有一個(gè)int型的返回值,具體的可選值及含義如下:
START_NOT_STICKY :當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后,接下來(lái)未來(lái)的某個(gè)時(shí)間內(nèi),即使系統(tǒng)內(nèi)存足夠可用,系統(tǒng)也不會(huì)嘗試重新創(chuàng)建此Service。除非程序中Client明確再次調(diào)用startService(...)啟動(dòng)此Service。
START_STICKY :當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后,接下來(lái)未來(lái)的某個(gè)時(shí)間內(nèi),當(dāng)系統(tǒng)內(nèi)存足夠可用的情況下,系統(tǒng)將會(huì)嘗試重新創(chuàng)建此Service,一旦創(chuàng)建成功后將回調(diào)onStartCommand(...)方法,但其中的Intent將是null,pendingintent除外。
START_REDELIVER_INTENT :與START_STICKY唯一不同的是,回調(diào)onStartCommand(...)方法時(shí),其中的Intent將是非空,將是最后一次調(diào)用startService(...)中的intent。
START_STICKY_COMPATIBILITY :此值一般不會(huì)使用,所以注意前面三種情形就好。
以上的描述中,”當(dāng)Service因?yàn)閮?nèi)存不足而被系統(tǒng)kill后“一定要非常注意,因?yàn)榇撕瘮?shù)的返回值設(shè)定只是針對(duì)此種情況才有意義的,換言之,當(dāng)認(rèn)為的kill掉Service進(jìn)程,此函數(shù)返回值無(wú)論怎么設(shè)定,接下來(lái)未來(lái)的某個(gè)時(shí)間內(nèi),即使系統(tǒng)內(nèi)存足夠可用,Service也不會(huì)重啟。
小米手機(jī)針對(duì)此處做了變更:
另外,需要注意的是,小米手機(jī)針對(duì)此處做了一定的修改。在“自啟動(dòng)管理”中有一個(gè)自啟動(dòng)應(yīng)用列表,默認(rèn)情況下,只有少應(yīng)用(如微信、QQ、YY、360等)默認(rèn)是可以自啟動(dòng)的,其他應(yīng)用默認(rèn)都是禁止的。用戶(hù)可以手動(dòng)添加自啟動(dòng)應(yīng)用,添加后的應(yīng)用中如果Started Service onStartCommand(...)回調(diào)返回值是START_STICKY或START_REDELIVER_INTENT,當(dāng)用戶(hù)在小米手機(jī)上長(zhǎng)按Home鍵結(jié)束App后,接下來(lái)未來(lái)的某個(gè)時(shí)間內(nèi),當(dāng)系統(tǒng)內(nèi)存足夠可用時(shí),Service依然可以按照上述規(guī)定重啟。當(dāng)然,如果用戶(hù)在 設(shè)置 >> 應(yīng)用 >> 強(qiáng)制kill掉App進(jìn)程,此時(shí)Service是不會(huì)重啟的。
注:以上實(shí)驗(yàn)結(jié)論基于小米2S親測(cè)。
官方教程
郭霖(Service教程)
Service生命周期圖解
Android總結(jié)篇系列:Android Service
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/66412.html
摘要:只能執(zhí)行單一操作,無(wú)法返回結(jié)果給調(diào)用方,常用于網(wǎng)絡(luò)下載上傳文件,播放音樂(lè)等。綁定模式此模式通過(guò)綁定組件等調(diào)用啟動(dòng)此服務(wù)隨綁定組件的消亡而解除綁定。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏Android 干貨分享 showImg(https://segme...
摘要:靜態(tài)注冊(cè)廣播的方法動(dòng)態(tài)注冊(cè)廣播在中動(dòng)態(tài)注冊(cè)廣播,通常格式如下動(dòng)態(tài)注冊(cè)廣播動(dòng)態(tài)注冊(cè)監(jiān)聽(tīng)滅屏點(diǎn)亮屏幕的廣播在廣播中動(dòng)態(tài)注冊(cè)廣播請(qǐng)注意一定要使用,防止為空,引起空指針異常。綁定模式此模式通過(guò)綁定組件等調(diào)用啟動(dòng)此服務(wù)隨綁定組件的消亡而解除綁定。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極...
閱讀 4112·2023-04-26 02:07
閱讀 3741·2021-10-27 14:14
閱讀 2964·2021-10-14 09:49
閱讀 1685·2019-08-30 15:43
閱讀 2695·2019-08-29 18:33
閱讀 2431·2019-08-29 17:01
閱讀 974·2019-08-29 15:11
閱讀 675·2019-08-29 11:06