Android——Service介紹與例子


    官方定義:Service(服務)是一個沒有用戶界面的在后台運行執行耗時操作的應用組件。其他應用組件能夠啟動Service,並且當用戶切換到另外的應用場景,Service將持續在后台運行。另外,一個組件能夠綁定到一個service與之交互(IPC機制),例如,一個service可能會處理網絡操作,播放音樂,操作文件I/O或者與內容提供者(content provider)交互,所有這些活動都是在后台進行。

Service有兩種狀態,“啟動的”和“綁定”

 

其中涉及到了Service的兩種狀態:(Started)、(Bound

  1. Started:

    通過startService()啟動的服務處於“啟動的”狀態,一旦啟動,service就在后台運行,即使啟動它的應用組件已經被銷毀了。通常started狀態的service執行單任務並且不返回任何結果給啟動者。比如當下載或上傳一個文件,當這項操作完成時,service應該停止它本身。

  2. Bound:

    “綁定”狀態的service,通過調用bindService()來啟動,一個綁定的service提供一個允許組件與service交互的接口,可以發送請求、獲取返回結果,還可以通過誇進程通信來交互(IPC)。綁定的service只有當應用組件綁定后才能運行,多個組件可以綁定一個service,當調用unbind()方法時,這個service就會被銷毀了。

     

    注意:

    a.一個服務在進程中的主線程運行——一個服務不會創建自己的線程,也不會在另外的進程運行。

    b.還有就是不要把Service理解成線程,你可以把 Service 想象成一種消息服務,而你可以在任何有 Context 的地方調用 Context.startServiceContext.stopServiceContext.bindServiceContext.unbindService,來控制它,你也可以在 Service 里注冊 BroadcastReceiver,在其他地方通過發送 broadcast 來控制它,當然這些都是 Thread 做不到的。舉個簡單的小例子:如果你的 Thread 需要不停地隔一段時間就要連接服務器做某種同步的話,該 Thread 需要在 Activity 沒有start的時候也在運行。這個時候當你 start 一個 Activity 就沒有辦法在該 Activity 里面控制之前創建的 Thread。因此你便需要創建並啟動一個 Service ,在 Service 里面創建、運行並控制該 Thread,這樣便解決了該問題(因為任何 Activity 都可以控制同一 Service,而系統也只會創建一個對應 Service 的實例)。

具體例子:在布局文件中添加兩個按鈕(啟動服務,停止服務),添加點擊事件(具體findById獲取,再添加監聽事件)

創建一個Service

package com.example.test_myservice_demo01;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("創建服務");
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {
        System.out.println("啟動服務...");      //這里實現服務的核心業務
        for (int i=0;i<50;i++){
            System.out.println("i="+i);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        System.out.println("停止服務");
        super.onDestroy();
    }
}

 

MainActivity文件

...

public void onClick(View v) {
    switch (v.getId()){
        case R.id.button_start:
            Intent startIntent = new Intent(this,MyService.class);
            startService(startIntent);     //啟動服務
            break;
        case R.id.button_stop:
            Intent stopIntent = new Intent(this,MyService.class);
            stopService(stopIntent);   //停止服務
            break;

       default:
            break;
    }
}

 

manifest清單文件中可以看到:

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true" />

實驗結果:如果不點擊停止服務,就會一直在運行狀態,有什么辦法可以能讓服務停止下來,只需要在MyService的任何位置調用stopSelf()就能停止服務。

 

 04-17 06:12:36.755 2909-2909/com.example.test_myservice_demo01 I/System.out: 創建服務
04-17 06:12:36.755 2909-2909/com.example.test_myservice_demo01 I/System.out: 啟動服務...
04-17 06:12:36.755 2909-2909/com.example.test_myservice_demo01 I/System.out: i=0
04-17 06:12:36.756 2909-2909/com.example.test_myservice_demo01 I/System.out: i=1
04-17 06:12:36.756 2909-2909/com.example.test_myservice_demo01 I/System.out: i=2
04-17 06:12:36.756 2909-2909/com.example.test_myservice_demo01 I/System.out: i=3

...
04-17 06:12:36.757 2909-2909/com.example.test_myservice_demo01 I/System.out: i=47
04-17 06:12:36.757 2909-2909/com.example.test_myservice_demo01 I/System.out: i=48
04-17 06:12:36.757 2909-2909/com.example.test_myservice_demo01 I/System.out: i=49

點擊停止按鈕后之后
04-17 06:12:43.282 2909-2909/com.example.test_myservice_demo01 I/System.out: 停止服務

...

 

IntentService服務

這是一個Service的子類,IntentService使用隊列的方式將請求的Intent加入隊列,然后開啟一個worker thread(線程)來處理隊列中的Intent,對於異步的startService請求,IntentService會處理完成一個之后再處理第二個,每一個請求都會在一個單獨的worker thread中處理,不會阻塞應用程序的主線程,這里就給我們提供了一個思路,如果有耗時的操作與其在Service里面開啟新線程還不如使用IntentService來處理耗時操作。而在一般的繼承Service里面如果要進行耗時操作就必須另開線程,但是使用IntentService就可以直接在里面進行耗時操作,因為默認實現了一個worker thread。對於異步的startService請求,IntentService會處理完成一個之后再處理第二個。

 

例子:

Service

package com.example.test_myservice_demo01;
import android.app.IntentService;
import android.content.Intent;
/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 * <p>
 * TODO: Customize class - update intent actions and extra parameters.
 * 內部類只有一個工作線程來完成耗時操作,只需要實現HandleIntent方法就行
 */
public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        System.out.println(intent.getStringExtra("info"));
        for (int i =0;i<15;i++){
            System.out.println("onHandleIntent-"+i+"-"+Thread.currentThread().getName());
            try {
                Thread.sleep(500);  //模擬延遲
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            if (i==10){
//                stopSelf(); //如果添加,便會停止服務
//                break;
//            }
        }
    }
}

MainActivity同上加上一個點擊按鈕

case R.id.button_3:
    Intent startIntentService = new Intent(this,MyIntentService.class);
    startIntentService.putExtra("info","這個是 我的第一個IntentService");
    startService(startIntentService);
    break;

-----------------分割線---------------------------

 

Bound還有就是綁定服務、解綁

不同於以上服務,在MainActivity中加按鈕點擊事件(bindunbind

case R.id.button_bind:
    Intent intent = new Intent(this,MyBoundService.class);
    //異步
    bindService(intent,connection, Context.BIND_AUTO_CREATE);            //綁定服務
    break;
case R.id.button_unbind:
    unbindService(connection);                                  //解除服務
    break;

還需要:

//綁定服務的連接回調方法
private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //綁定成功后回調方法
        downloadBinder = (MyBoundService.DownloadBinder) service;
        downloadBinder.startDownload();
        downloadBinder.getProgress();
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        //服務異常調用
    }
};

 

Service類:

package com.example.test_myservice_demo01;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyBoundService extends Service {
    private DownloadBinder mBinder = new DownloadBinder();
    class DownloadBinder extends Binder{
        public void startDownload(){
            Log.d("MyService","startDownload executed");
        }
        public int getProgress(){
            Log.d("MyService","getProgress executed");
         return 0;
        }
    }
    public MyBoundService() {
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
//        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("已經解除綁定");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

實驗結果:

綁定:

04-17 06:50:08.346 23840-23840/com.example.test_myservice_demo01 D/MyService: startDownload executed

04-17 06:50:08.346 23840-23840/com.example.test_myservice_demo01 D/MyService: getProgress executed

解綁:

04-17 06:50:58.931 23840-23840/com.example.test_myservice_demo01 I/System.out: 已經解除綁定

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM