1. 程式人生 > >Service 服務

Service 服務

一.Service是四大元件之一,是沒有介面的activity,可以用於做一些耗時的操作,比如後臺下載等

生命週期如下

 

二.如何定義一個Service

  1.建立一個類繼承android:app.Service類,並實現抽象方法,onCreate(),OnStartCommand,onBind(),onUnBind(),onDestry;

 1 package com.example.servicetest;
 2 
 3 import android.app.Service;
 4 import android.content.Intent;
 5 import
android.os.IBinder; 6 import android.util.Log; 7 8 public class MyService extends Service { 9 10 public static final String TAG = "MyService"; 11 12 //建立服務時呼叫 13 @Override 14 public void onCreate() { 15 super.onCreate(); 16 Log.d(TAG, "onCreate");
17 } 18 19 //服務執行的操作 20 @Override 21 public int onStartCommand(Intent intent, int flags, int startId) { 22 Log.d(TAG, "onStartCommand"); 23 return super.onStartCommand(intent, flags, startId); 24 } 25 26 //銷燬服務時呼叫 27 @Override 28 public
void onDestroy() { 29 super.onDestroy(); 30 Log.d(TAG, "onDestroy"); 31 } 32 33 @Override 34 public IBinder onBind(Intent intent) { 35 return null; 36 } 37 }

  2.在清單檔案中配置Service

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

三.服務的啟動,停止,繫結,和解綁

  case R.id.start:
                //啟動服務  服務建立--->啟動
                // 如果服務已經建立再次啟動時不會執行建立,操作還是同一個服務,除非銷燬已存在的服務
                Intent intent = new Intent(this, MyService.class);
                startService(intent);
                break;
            case R.id.stop:
                //停止服務
                Intent intent1 = new Intent(this, MyService.class);
                stopService(intent1);
                break;
            case R.id.bind:
                //繫結服務
                Intent intent2 = new Intent(this, MyService.class);
                //bindService()中的引數依次是Intent,ServiceConnection和繫結時自動建立服務的標記位
                //如果繫結服務沒有被啟動,那麼他會隨著activity的銷燬而銷燬
                bindService(intent2, serviceConnection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind:
                //解綁服務
                Intent intent3 = new Intent(this, MyService.class);
                unbindService(serviceConnection);
                break;

事實上,onCreate()方法只會在Service第一次被建立的時候呼叫,而onStartCommand()方法在每次啟動服務的時候都會呼叫

停止服務的兩種方式:

  1.在外部使用stopService()

  2.在服務的(onStartCommand方法)內部使用stopSelf()方法

onStartCommand方法執行時,返回的是一個int型。這個整型可以有三個返回值:START_NOT_STICKY、START_STICKY、START_REDELIVER_INTENT

  START_NOT_STICKY:執行完onStartCommand()方法後,服務被異常kill掉了,不會自動重啟服務

  START_STICKY:如果Service程序被kill掉,保留Service的狀態為開始狀態,但不保留遞送的intent物件。隨後系統會嘗試重新建立Service,由於服務狀態為開始狀態,所以建立服務後一定會呼叫onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到Service,那麼引數Intent將為nul

  START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,系統會自動重啟該服務,並將Intent的值傳入。

四:使用Bind Service完成Service和Activity之間的通訊

應用程式元件(客戶端)通過呼叫bindService()方法能夠繫結服務,然後Android系統會呼叫服務的onBind()回撥方法,則個方法會返回一個跟伺服器端互動的Binder物件。

這個繫結是非同步的,bindService()方法立即返回,並且不給客戶端返回IBinder物件。要接收IBinder物件,客戶端必須建立一個ServiceConnection類的例項,並且把這個例項傳遞給bindService()方法。ServiceConnection物件包含了一個系統呼叫的傳遞IBinder物件的回撥方法。

注意:只有Activity、Service、Content Provider能夠繫結服務;BroadcastReceiver廣播接收器不能繫結服務。

進度監控示例

public class MyService extends Service {

    private int i;

    public MyService() {
    }

    @Override
    public void onCreate() {
        Log.d("TAG", "服務建立了");
        //開啟一個執行緒 進度,從1數到100
        new Thread(){
            @Override
            public void run() {
                super.run();
                for (i = 1; i <=100 ; i++) {
                    try {
                        sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TAG", "服務啟動了");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.d("TAG", "繫結");
        return new MyBind();
    }
    /**
     * 由於IBinder介面中需要實現的方法太多,而Binder實現了IBinder介面
     * 所以我麼你自定義一個內部類繼承他,並寫入我們所需要的方法
     */
    class MyBind extends Binder{
        //自定義方法獲取進度
        public int getProgress(){
            return i;
        }

    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("TAG", "解綁");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.d("TAG", "銷燬");
        super.onDestroy();
    }
}

在MainActivity中

public class MainActivity extends AppCompatActivity {
    //ibind
    //ServiceConnection  一個介面 用於繫結服務與客戶端
    //進度監控
    MyHandler myHandler = new MyHandler(this);
    ServiceConnection serviceConnection = new ServiceConnection() {
        //當客戶端與服務正常連線時,執行服務的繫結操作會被呼叫
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            MyService.MyBind myBind = (MyService.MyBind) iBinder;
            int progress = myBind.getProgress();
            Log.d("TAg", "handleMessage: " + progress);
            if (progress <= 100) {
                Message message = new Message();
                message.arg1 = progress;
                myHandler.sendMessage(message);
            }

        }

        //當客戶端與服務的連線丟失時
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };