Service 學(xué)習(xí)

A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding <service> declaration in its package'sAndroidManifest.xml. Services can be started with Context.startService() and Context.bindService().
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.

從官方文檔上可以看出,Service服務(wù)是不與用戶交互肥卡,長時間在后臺運行的一個組件。但是所在線程是在主線程球涛,如果要處理耗時操作如播放音樂,處理網(wǎng)絡(luò)請求的話需要啟動一個子線程來處理苛秕。


一堕油、啟動與銷毀

  • 啟動Service
    啟動Service有兩種方法:
    ①startService()
Intent intent = new Intent(MainActivity.this,TestService.class);
startService(intent);

生命流程:onCreate() → onStartCommand() → onDestory()
注意: onCreate()方法只會執(zhí)行一次,多次調(diào)用StartService()方法只會在第一次調(diào)用onCreate()拇涤,而onStartCommand()會多次調(diào)用。
當(dāng)服務(wù)被啟動后誉结,Service與Activity就沒有了關(guān)系鹅士,Activity退出后Service還會執(zhí)行。
②bindService()

bindService(intent,mcon,BIND_AUTO_CREATE);
public MCon mcon = new MCon();
public class MCon implements ServiceConnection{     
      @Override    
      public void onServiceConnected(ComponentName name, IBinder service) {        
            myBinder = (TestService.MyBinder)service;    
      }    
      @Override    
      public void onServiceDisconnected(ComponentName name) {

      }
}
onServiceConnected()
系統(tǒng)調(diào)用這個來傳送在service的onBind()中返回的IBinder.
OnServiceDisconnected()
Android系統(tǒng)在同service的連接意外丟失時調(diào)用這個.比如當(dāng)service崩潰了或被強殺了.
當(dāng)客戶端解除綁定時惩坑,這個方法不會被調(diào)用. 類ServiceConnection中的onServiceDisconnected()方法在正常情況下是不被調(diào)用的掉盅,
它的調(diào)用時機是當(dāng)Service服務(wù)被異外銷毀時也拜,例如內(nèi)存的資源不足時這個方法才被自動調(diào)用。

生命流程: onCreate() → onBind() → onUnbind() → onDestory()
多次調(diào)用bindService()并不會再次調(diào)用onCreate() 和onBind()趾痘。
當(dāng)服務(wù)被啟動后慢哈,Service與Activity就綁定在了一起,當(dāng)Activity退出之后Service也退出永票。

  • 銷毀service
    使用startService()啟動之后調(diào)用stopService()來銷毀服務(wù)卵贱。
    使用bindService()綁定之后調(diào)用unbindService()來銷毀服務(wù)。
    如果同時調(diào)用startService()與bindService()侣集,銷毀時需要同時調(diào)用stopService()與unbindService()來銷毀键俱。
           
    1.如果先bindService,再startService:
    在bind的Activity退出的時候,Service會執(zhí)行unBind方法而不執(zhí)行onDestory方法,因為有startService方法調(diào)用過,所以Activity與Service解除綁定后會有一個與調(diào)用者沒有關(guān)連的Service存在
    2.如果先bindService,再startService,再調(diào)用Context.stopService
    Service的onDestory方法不會立刻執(zhí)行,因為有一個與Service綁定的Activity,但是在Activity退出的時候,會執(zhí)行onDestory,如果要立刻執(zhí)行stopService,就得先解除綁定 
     
    要注意合理中斷Service中的線程,最好設(shè)置變量檢測中斷(先挖個坑)世分。

  • onStartCommand返回值
    START_STICKY:如果service進(jìn)程被kill掉编振,保留service的狀態(tài)為開始狀態(tài),但不保留遞送的intent對象罚攀。隨后系統(tǒng)會嘗試重新創(chuàng)建service党觅,由于服務(wù)狀態(tài)為開始狀態(tài)雌澄,所以創(chuàng)建服務(wù)后一定會調(diào)用onStartCommand(Intent,int,int)方法斋泄。如果在此期間沒有任何啟動命令被傳遞到service,那么參數(shù)Intent將為null镐牺。
    START_NOT_STICKY:“非粘性的”炫掐。使用這個返回值時,如果在執(zhí)行完onStartCommand后睬涧,服務(wù)被異常kill掉募胃,系統(tǒng)不會自動重啟該服務(wù)
    START_REDELIVER_INTENT:重傳Intent。使用這個返回值時畦浓,如果在執(zhí)行完onStartCommand后痹束,服務(wù)被異常kill掉,系統(tǒng)會自動重啟該服務(wù)讶请,并將Intent的值傳入祷嘶。
    START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務(wù)被kill后一定能重啟夺溢。

  • **bindService參數(shù) **
    BIND_AUTO_CREATE:一般為這個论巍,代表Service不存在時自動創(chuàng)建該Service。

二风响、Service與Activity通信

  • 采用onBind與接口方式雙向通信
public interface BinderInterface {    
      int getI();    
      void setI(int a);
}          
            
class MyBinder extends Binder implements BinderInterface{    
      @Override    
      public int getI() {        
      return i;    
      }    
      @Override    
      public void setI(int a) {        
      i = a;        
      mtThread.interrupt();    
      }
}
   
public MyBinder mBinder = new MyBinder();    
public IBinder onBind(Intent intent) { 
      return mBinder;    
}

利用obBind()將一個Binder對象傳遞給Activity嘉汰。

public TestService.MyBinder myBinder;
public MCon mcon = new MCon();
public class MCon implements ServiceConnection{     
      @Override    
      public void onServiceConnected(ComponentName name, IBinder service) {        
            myBinder = (TestService.MyBinder)service;    
      }    
      @Override    
      public void onServiceDisconnected(ComponentName name) {

      }
}

轉(zhuǎn)化為MyBinder對象之后就可以使用MyBinder中的方法來相互通信了。

myBinder.setI(1000);
int i = myBinder.getI();
  • 使用Intent通信
    使用Intetnt在Activity啟動Service時状勤,將數(shù)據(jù)放入Intent之中鞋怀,之后在Service中的onStartCommand(Intent intent, int flags, int startId)方法中獲取到Intetnt并提取出數(shù)據(jù)双泪。
Activity中:
Intent intent = new Intent(MainActivity.this,TestService.class)
intent.putExtra("name","li");
startService(intent);
    
Service中
public int onStartCommand(Intent intent, int flags, int startId) {    
      String name  = (intent.getExtras()).getString("name");        
      return START_STICKY;
}

三、前臺服務(wù)

  • 提升為前臺服務(wù)
    什么是前臺服務(wù)

A foreground service(前臺服務(wù)) is a service that's considered to be(被用戶所認(rèn)可的) something the
user is actively aware of and thus not a candidate for(而不是一個候選的密似,可以在內(nèi)存不足時攒读,被系統(tǒng)殺死
的) the system to kill when low on memory. A foreground service must provide a notification for the status
bar(前臺服務(wù)必須提供一個顯示通知), which is placed under the "Ongoing" heading(它是不可以忽略的), >which means that the notification cannot be dismissed unless the service is either stopped or removed from >the foreground.(意思是通知信息不能被忽略,除非服務(wù)停止或主動移除辛友,否則將一直顯示)

前臺服務(wù)是那些被認(rèn)為用戶知道(用戶認(rèn)可所認(rèn)可)且在系統(tǒng)內(nèi)存不足的時候不允許系統(tǒng)殺死的服務(wù)薄扁。 前臺服務(wù)必須給狀態(tài)欄提供一個通知,它被放到正在運行(Ongoing)標(biāo)題之下——這就意味著通知只有在這個服務(wù)被終止或從前臺主動移除通知后才能被解除废累。
如果我們希望Service可以一直保持運行狀態(tài)且不會在內(nèi)存不足的情況下被回收時邓梅,可以選擇將需要保持運行的Service設(shè)置為前臺服務(wù)
   
創(chuàng)建Notifition

private void bulidNotifition() {    
      notificationBuilder = new Notification.Builder(this);    
      Intent intent = new Intent(this,MainActivity.class);    
      notification = notificationBuilder.setContentIntent(PendingIntent.getActivity(this,0,intent,0))
              .setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.mipmap.ic_launcher))
              .setContentTitle("前臺Serviece")            
              .setContentText("內(nèi)容")           
              .setWhen(System.currentTimeMillis()).build();
}

在onStartCommand中啟動前臺服務(wù)

public int onStartCommand(Intent intent, int flags, int startId) {    
      bulidNotifition();    
      startForeground(100,notification);    //100表示前臺服務(wù)的id  當(dāng)使用的通知ID一致時邑滨,只會更新當(dāng)前Notification
      return START_STICKY;
}

停止前臺服務(wù)

stopForeground(true);

啟動服務(wù)之后日缨,就會看到提示框那里有個提示欄,說明我們的Service已經(jīng)成為前臺服務(wù)了掖看。

四匣距、IntentService

開啟一個線程來處理用戶的intent請求,采用隊列等待哎壳,一個時間只有一個intent請求被執(zhí)行毅待。

主要方法:onHandleIntent(Intent intent)

此方法在具有請求的工作線程上被調(diào)用。 每次只處理一個Intent归榕,但是處理發(fā)生在獨立于其他應(yīng)用程序邏輯運行的工作線程上尸红。 所以,如果這段代碼需要很長時間刹泄,它會阻止對同一IntentService的其他請求外里,但它不會阻止任何其他。 當(dāng)所有請求都被處理后特石,IntentService停止自己盅蝗,所以你不應(yīng)該調(diào)用stopSelf()。

button1.setOnClickListener(new View.OnClickListener() {
    @Override    
    public void onClick(View v) {
        Intent intentservice1 = new Intent(MainActivity.this,MyIntentService.class);
        intentservice1.putExtra("action",1);
        startService(intentservice1);
    }
});

button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intentservice2 = new Intent(MainActivity.this,MyIntentService.class);
        intentservice2.putExtra("action",2);
        startService(intentservice2);
    }
}
);
protected void onHandleIntent(Intent intent) {
    Log.d("intent",intent.getIntExtra("action",0)+"");
    try {
         Log.d("A1sleep","A1sleep");
         Thread.sleep(2000);
         Log.d("sleep down","sleep down");
    } catch (InterruptedException e) {
         e.printStackTrace();
    }
}
依次按下按鈕姆蘸,intent依次執(zhí)行

五墩莫、跨進(jìn)程Service與通信

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市乞旦,隨后出現(xiàn)的幾起案子贼穆,更是在濱河造成了極大的恐慌,老刑警劉巖兰粉,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件故痊,死亡現(xiàn)場離奇詭異,居然都是意外死亡玖姑,警方通過查閱死者的電腦和手機愕秫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門慨菱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戴甩,你說我怎么就攤上這事符喝。” “怎么了甜孤?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵协饲,是天一觀的道長。 經(jīng)常有香客問我缴川,道長茉稠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任把夸,我火速辦了婚禮而线,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘恋日。我一直安慰自己膀篮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布岂膳。 她就那樣靜靜地躺著誓竿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闷营。 梳的紋絲不亂的頭發(fā)上烤黍,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機與錄音傻盟,去河邊找鬼。 笑死嫂丙,一個胖子當(dāng)著我的面吹牛娘赴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播跟啤,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼诽表,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了隅肥?” 一聲冷哼從身側(cè)響起竿奏,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腥放,沒想到半個月后泛啸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡秃症,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年候址,在試婚紗的時候發(fā)現(xiàn)自己被綠了吕粹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡岗仑,死狀恐怖匹耕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荠雕,我是刑警寧澤稳其,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站炸卑,受9級特大地震影響欢际,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜矾兜,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一损趋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧椅寺,春花似錦浑槽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荆萤,卻和暖如春镊靴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背链韭。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工偏竟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敞峭。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓踊谋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親旋讹。 傳聞我的和親對象是個殘疾皇子殖蚕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容