亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android創建服務之started service詳細介紹

2020-04-11 11:55:25
字體:
來源:轉載
供稿:網友

創建started service

       應用組件(例如Activity)調用startService()來啟動一個Service,將需要的參數通過Intent傳給Service,Service將會在onStartCommand函數中獲得Intent。

有兩種方式可以創建started service,一種是擴展Service類,另外一種是擴展IntentService類

擴展Service
       這是所有服務的基類。擴展這個類的時候,特別重要的一點是,需要創建一個新的線程來做服務任務,因為service默認是運行在你的主線程(UI線程)中的,它會使你的主線程運行緩慢。

擴展IntentService
       這是一個service的子類,他可以在一個工作線程中處理所有的啟動請求。如果你不需要同一時刻出來所有的服務請求,使用IntentService是一個很好的選擇。你需要做的僅僅是實現onHandlerIntent()方法,通過這個函數處理接受的每一個啟動請求。


下面我們學習如何擴展IntentService類和Service類

擴展IntentService類

IntentService做了什么?
1.創建一個獨立于主線程的工作線程,用于執行通過onStartCommand()傳來的所有的intent。
2.創建一個工作隊列,將接受的所有intent一個一個的傳給onHandlerIntent(),所以同一時間內你只處理一個intent,不用擔心多線程的問題。
3.當所有的請求都處理完后,停止服務,所以你不需要手動調用stopSelf()。
4.提供onBind()函數的默認實現,返回null
5.提供onStartCommand()函數的默認實現,它把intent發送到工作隊列中去,然后工作隊列再發送到你的onHandlerIntent()函數中。

有了上面的基礎,你僅僅要做的就是實現onHandlerIntent()。并且實現一個小小的構造函數。

參考下面的例子:

復制代碼 代碼如下:

public class HelloIntentService extends IntentService {

  /**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      long endTime = System.currentTimeMillis() + 5*1000;
      while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
              try {
                  wait(endTime - System.currentTimeMillis());
              } catch (Exception e) {
              }
          }
      }
  }
}

如果你要實現其他的回調函數,例如 onCreate , onStartCommand ,onDestroy 一定記得調用父類相應的函數,這樣IntentService才能正確的處理工作線程。

例如,你需要在onStartCommand函數中彈出一個提示,那么你可以這樣寫:

復制代碼 代碼如下:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
    return super.onStartCommand(intent,flags,startId);
}

有一點例外的是,如果你需要其他組件綁定服務,那么你的onBind函數不需要調用父類的onBind。

在下一節中,你將會看到通過擴展service類來實現與本節相同的服務,所不同的是代碼會更多,但是同樣意味著更靈活,特別是你需要同時處理多個請求時,比較適合直接擴展Service。

擴展Service類

如同你在上一節看到的一樣,使用IntentService來實現一個started service非常簡單。如果你需要你的service來執行多個線程,那么你需要擴展Service類去處理每個intent。

作為對比,下面的例子用Service類實現了和上一節中一樣功能的服務。

復制代碼 代碼如下:

public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          long endTime = System.currentTimeMillis() + 5*1000;
          while (System.currentTimeMillis() < endTime) {
              synchronized (this) {
                  try {
                      wait(endTime - System.currentTimeMillis());
                  } catch (Exception e) {
                  }
              }
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);

      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }

  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}

如同你看到的,比IntentService的例子多了好多代碼。

因為你自己處理每次的onStartcommand(),所以你可以在同一時間處理多個請求。這個例子沒有這樣做,但是如果你愿意,你完全可以每收到一個請求的時候,創建一個新線程并且立即運行,而不是等到上一個請求處理完成后再運行。

注意,onStartCommand()函數必須返回一個整數。這個整數描述了當系統殺死該服務時將要如何處理該服務。返回值必須是下面幾個值:
START_NOT_STICKY
在onStartCommand()返回后,系統殺死服務,服務將不會重啟,除非有pending intents(目前筆者還不懂什么是pending Intents)要投遞。這比較適合非常容易就可以重新啟動未完成任務的情況。

START_STICKY
        在系統殺死服務后,重啟服務并且調用onStartCommand(),但是不重新投遞上一次的intent。系統會傳給onStartCommand()函數null,除非有pending intent來啟動服務,會傳給onStartCommand()相應的intent。這種做法比較適合媒體播放服務,不需要執行命令,但是獨立運行,常處于等待任務的服務。

START_REDELIVER_INTENT
在系統殺死服務后,重啟服務并且調用onStartCommand(),參數傳入上一次的intent,然后接下來是pending intent傳入onStartCommand()。這比較適合于正在執行一項工作,它不能被立刻恢復,例如下載文件。

啟動Service

你可以從一個Activity或者其他組件調用startService(intent)來啟動服務。Android系統會調用服務的onStartCommand()函數并且傳給它intent。

用上一節的HelloService來做個例子:
Intent intent = new Intent(this, HelloService.class);
startService(intent);
startService()會立刻返回,Android系統會調用服務的onStartCommand()函數。如果這是服務沒有在運行,系統會首先調用onCreate()函數,然后會緊接著調用onStartCommand()函數。

如果服務沒有提供綁定,那么通過startService()函數傳入的intent就是應用組件和服務進行交互的唯一途徑。如果你想服務發送結果給客戶組件,那么客戶組件需要在啟動服務時,創建一個用于廣播的PendingIntent,通過intent投遞給服務。這樣,服務就可以利用廣播把結果發送給客戶組件。

多個請求會導致服務的onStartCommand()被調用多次。但是,只需要一個停止請求(stopSelf() 或 stopService())就會使服務停止。

停止服務

一個啟動的服務必須管理自己的生命周期。因為除非系統需要回收資源的時候,系統不會停止或者銷毀服務。所以,服務必須通過調用stopSelf()來停止自己,或者有其他組件調用stopService()。

一擔收到stopSelf()或stopService()的停止請求,系統會立刻銷毀服務。

如果你的服務同時處理多個服務請求,當某個請求完成時就不能馬上停止服務,因為你可能已經又接受了一個新的請求(在第一個請求完成時結束服務會終止第二個請求)。為了解決這個問題,你可以調用stopSelf(int)函數來保證你的停止請求總是基于最近的一次服務請求。這是因為,調用stopSelf(int)函數
會把onStartCommand()函數傳入的startId傳給停止請求。當你的startId和最近一次接受的服務請求不匹配時,服務不會結束。

注意:stopSelf(int)函數只是簡單的與最近一次收到的startId比較,如果你的服務處理過程是多線程的,可能后收到的服務請求先完成,那stopSelf(int)的方案不適合你,你應該手動管理接受到的服務請求和完成的服務,比如在onStartCommand()函數中把startId記錄到一個表中,在完成服務任務時在表中記錄完成狀態,在確保表中任務都完成的情況下直接調用stopSelf()來停止服務。

在前臺運行服務

一個前臺服務是用戶能夠很明顯意識到的服務,當可用內存比較低的時候,系統不會殺掉前臺服務。一個前臺服務必須提供一個狀態欄通知,放在正在運行條目里,這意味著只要服務沒有停止或者一直是前臺服務,這個通知就不會被消失。

舉個例子,一個音樂播放器服務應該被設置為前臺運行,因為用戶非常明顯知道他在運行。這個狀態欄通知可以顯示正在播放的歌曲,并且可以允許用戶點擊進入音樂播放界面。

要使服務運行在前臺只要調用startForeground()。這個方法有兩個參數:一個通知的整數ID和一個狀態欄通知。代碼片段:

復制代碼 代碼如下:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

使用stopForeground()函數可以把服務從前臺移除。這個函數帶一個布爾值參數,來表示是否從狀態欄移除通知。這個函數不會使服務停止。如果把前臺服務停止掉,那么通知也會同時被移除。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线视频一二三| 久久精品国产久精国产一老狼| 精品美女永久免费视频| 在线观看久久久久久| 欧美专区在线观看| 亚洲国产精品久久久久秋霞蜜臀| 中文字幕欧美日韩精品| 91国产精品电影| 国产日产欧美精品| 精品一区二区三区电影| 精品久久香蕉国产线看观看亚洲| 亚洲欧美成人精品| 久久久久久久久久久免费精品| 国产99久久精品一区二区 夜夜躁日日躁| 中文字幕久精品免费视频| 欧美激情图片区| 精品亚洲一区二区三区| 亚洲人成亚洲人成在线观看| 国产在线久久久| 日韩福利视频在线观看| 欧美人与性动交a欧美精品| 亚洲高清在线观看| 久久99视频精品| 91精品久久久久久久久不口人| 欧美日韩激情网| 亚洲四色影视在线观看| 91精品久久久久久久久不口人| 国产v综合ⅴ日韩v欧美大片| 日韩在线观看免费高清完整版| 91精品国产乱码久久久久久久久| 亚洲精品www| 成人黄色午夜影院| 亚洲自拍中文字幕| 亚洲91精品在线| 成人免费看黄网站| 91在线精品视频| 成人高h视频在线| 热久久免费国产视频| 中文字幕亚洲国产| …久久精品99久久香蕉国产| 成人情趣片在线观看免费| 国产精品久久久久av免费| 色妞久久福利网| 国产精品普通话| 精品毛片三在线观看| 亚洲天堂男人的天堂| 日韩精品中文字| 国产精品日韩欧美| 久久久av电影| 欧美久久精品午夜青青大伊人| 日韩在线观看网址| 国产国产精品人在线视| 久久成人一区二区| 国产精品91久久久久久| 国产99久久精品一区二区 夜夜躁日日躁| 亚洲成人久久久久| 久久天天躁狠狠躁夜夜躁| 亚洲国产成人久久| 精品自拍视频在线观看| 亚洲第一区中文99精品| 日韩av一区二区在线观看| 日韩精品中文字幕在线| 在线亚洲午夜片av大片| 日韩中文字幕视频在线| 亚洲电影免费观看高清完整版| 亚洲人成在线一二| 亚洲自拍小视频| 久久亚洲影音av资源网| 久久久国产一区二区三区| 日韩精品在线视频美女| 性欧美亚洲xxxx乳在线观看| 国产999视频| 欧美性理论片在线观看片免费| 久久久久久国产精品美女| 97视频免费在线观看| 久久视频国产精品免费视频在线| 欧美综合在线第二页| 国产噜噜噜噜久久久久久久久| 欧美二区乱c黑人| 国产日韩在线看片| 国产日韩欧美黄色| 日韩av中文在线| 日韩性生活视频| 精品毛片网大全| 日本91av在线播放| 欧美诱惑福利视频| 亚洲a区在线视频| 国产成人精品一区二区在线| 国产亚洲综合久久| 久久精品视频中文字幕| 国产精品高清在线| 精品福利樱桃av导航| 久久成人av网站| 亚洲精品一区在线观看香蕉| 久久久精品国产| 欧美午夜女人视频在线| 欧美巨大黑人极品精男| 久久99亚洲精品| 国产精品电影网站| 久久精品91久久久久久再现| 国产精品99久久久久久久久久久久| 日本久久中文字幕| 成人写真视频福利网| 57pao国产精品一区| 亚洲精品一区av在线播放| 69精品小视频| 亚洲自拍偷拍区| 欧美激情一区二区三区在线视频观看| 在线观看不卡av| 91久久精品久久国产性色也91| 午夜精品福利视频| 久久久999国产| 欧美成人免费网| 久久在精品线影院精品国产| 亚洲区一区二区| 久久人人爽人人爽人人片av高清| 91久久久久久久久久久| 日韩成人av在线| 国产91网红主播在线观看| 久久国产色av| 韩国精品久久久999| 成人免费在线网址| 欧美激情精品久久久久久免费印度| 日韩欧美中文第一页| 国产日韩欧美中文| 伊人伊成久久人综合网站| 国产精品欧美在线| 日本中文字幕不卡免费| 欧美成人精品在线| 97热在线精品视频在线观看| 91九色蝌蚪国产| 欧美高清性猛交| 欧美激情亚洲另类| 97精品伊人久久久大香线蕉| 国产精品美女久久久久av超清| 久久天天躁狠狠躁夜夜躁| 国内精品400部情侣激情| 久久久99久久精品女同性| 国产精品大陆在线观看| 日韩精品中文在线观看| 福利二区91精品bt7086| 九九精品视频在线观看| 欧美黄色www| 国产精品第3页| 国产在线拍揄自揄视频不卡99| 国产成人aa精品一区在线播放| 日韩免费av在线| 久久免费高清视频| 亚洲欧美日本精品| 欧美极品少妇与黑人| 国产精品久久久久久久久久尿| 欧美日韩成人在线视频| 91欧美精品午夜性色福利在线| 上原亚衣av一区二区三区| 国产精品久久久久久久久久免费| 亚洲精品电影在线观看| 亚洲激情在线视频| 亚洲精品国产综合区久久久久久久| 国产精品h在线观看| 亚洲免费伊人电影在线观看av| 国产成人欧美在线观看| 91精品成人久久| 久久久久久亚洲| 国产成人中文字幕|