Service基礎

基本介紹

Service是一個應用程序組件,四大組件之一,它能夠在後臺執行一些耗時較長的操作,並且不提供用戶界面。服務能被其它應用程序的組件啓動,即使用戶切換到另外的應用時還能保持後臺運行。此外,應用程序組件還能與服務綁定,並與服務進行交互,甚至能進行進程間通信(IPC)。

使用方式

Service有常見的兩種啓動方式,Started 和Bound 方式。

Started 方式

如果一個應用程序組件(比如一個activity)通過調用startService()來啓動服務,則該服務就是被“started”了。

一旦被啓動,服務就能在後臺一直運行下去,即使啓動它的組件已經被銷燬了。

通常,started的服務執行單一的操作並且不會向調用者返回結果。比如,它可以通過網絡下載或上傳文件。當操作完成後,服務應該自行終止。

執行順序: onCreate() -> onStartCommand() ->onDestroy();

銷燬方式 stopService()

區別: startService()之後,無論啓動的組件是否仍然存在,沒有調用stopService()方法,Service仍然存在。

    /**
     * 啓動服務
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:20
     */
    public void startService(View view) {
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    /**
     * 關閉服務
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:20
     */
    public void stopService(View view) {
        Intent intent = new Intent(this, MyService.class);
        stopService(intent);
    }

Bound 方式

如果一個應用程序組件通過調用bindService()綁定到服務上,則該服務就是被“bound”了。

bound服務提供了一個客戶端/服務器接口,允許組件與服務進行交互、發送請求、獲取結果,甚至可以利用進程間通信(IPC)跨進程執行這些操作。

綁定服務的生存期和被綁定的應用程序組件一致。 多個組件可以同時與一個服務綁定,不過所有的組件解除綁定後,服務也就會被銷燬。

執行順序: onCreate() -> onBind() ->onDestroy();

銷燬方式 unbindService()
注意:通過unbindService()取消Service需要判定是否bind,否則報異常

區別: bindService()即將調用綁定的組件與這個Service捆綁在一起,組件銷燬了Service也被銷燬,類似從屬關係。

Bound方式Service與Activity通訊

1.MyService中的onBind()返回IBind子類實例。

2.ServiceConnection的onServiceConnected()方法拿出IBinder,向下強轉爲MyService中的IBind子類,即可對Service進行操作。

    private ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("info", "onServiceConnected: ==++ 服務連接");
            MyService.MyBinder myBinder = (MyService.MyBinder) service;
            myBinder.doSomething();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("info", "onServiceDisconnected: ==++ 服務取消連接");
        }
    };

    // 標記服務是否綁定
    private boolean isBind = false;

    /**
     * 綁定服務
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:27
     */
    public void bindService(View view) {
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, mServiceConn, BIND_AUTO_CREATE);
        isBind = true;
    }

    /**
     * 取消綁定服務
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:28
     */
    public void unbindService(View view) {
        if (isBind) {
            isBind = false;
            unbindService(mServiceConn);
        }
    }

MyService

/**
 * 自定義Service
 *
 * @author fengzhen
 * @version 1.0, 2017/7/21
 */
public class MyService extends Service {

    @Override
    public void onCreate() {
        Log.i("info", "onCreate: ==++ 服務創建");
        Log.i("info", "onCreate: ==++ 當前線程:" + Thread.currentThread().getName());
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("info", "onStartCommand: ==++ 服務啓動");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("info", "onDestroy: ==++ 服務銷燬");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("info", "onBind: ==++ 綁定服務");
        return new MyBinder();
    }

    public class MyBinder extends Binder {
        public void doSomething() {
            Log.i("info", "doSomething: ==+++ 做具體的事");
        }
    }
}

運行線程

通過驗證可以發現,Service和Activity一樣,運行在主線程,所以在使用是需要創建一個新的線程完成服務的工作
也可以使用其子類:IntentService

IntentService

創建一個缺省的工作(worker)線程,它獨立於應用程序主線程來執行所有發送到onStartCommand()的intent。

創建一個工作隊列,每次向你的onHandleIntent()傳入一個intent,這樣你就永遠不必擔心多線程問題了。

在處理完所有的啓動請求後,終止服務,因此你就永遠不需調用stopSelf()了。

提供缺省的onBind()實現代碼,它返回null。

提供缺省的onStartCommand()實現代碼,它把intent送入工作隊列,稍後會再傳給你的onHandleIntent()實現代碼。

/**
 * Service服務擴展類
 *
 * @author fengzhen
 * @version v1.0, 2017/7/21
 */
public class MyIntentService extends IntentService {
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     * <p>
     * Used to name the worker thread, important only for debugging.
     */
    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * IntentService從缺省的工作線程中調用本方法,並用啓動服務的intent作爲參數
     * 本方法返回後,IntentService將適時終止這個服務。
     * <p>
     * 再次方法操作需要在子線程做的,使用循環的方式,直到任務完成
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 17:05
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("info", "onCreate: ==++ 當前線程:" + Thread.currentThread().getName());
        int i = 0;
        while (i < 10) {
            i++;
            // doSomething
        }
    }
}

進程間通信(IPC)

使用AIDL來進行進程間通信(IPC)

AIDL(Android Interface Definition Language):Android接口定義語言

1.更改Service在xml配置

        <service android:name=".MyService"
            android:process=":remote">
            <intent-filter>
                <action android:name="com.hftsoft.servicedemo.MyAidlInterface"/>
            </intent-filter>
        </service>

2.創建AIDL文件

這裏參數類型只能使用basecTypes中的所有參數類型

AS創建AIDL文件只有需要點擊 mudel 旁小錘子圖標 Make Project (Ctrl + f9)

interface MyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    /**
     * 自定義簡單方法
     */
    String getString(int a);
}

3.綁定Activity中實現

    private MyAidlInterface mMyAidlInterface;
    /**
     * PIC Conn
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 18:16
     */
    private ServiceConnection mServiceConnRemote = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMyAidlInterface = MyAidlInterface.Stub.asInterface(service);
            try {
                String string = mMyAidlInterface.getString(5);
                Log.i("info", "onServiceConnected: ==++" + string);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    // 標記服務是否綁定
    private boolean isBind = false;

    /**
     * 綁定服務 IPC
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:27
     */
    public void bindService(View view) {
        Intent intent = new Intent("com.hftsoft.servicedemo.MyAidlInterface");
        intent.setPackage(this.getPackageName());
        bindService(intent, mServiceConnRemote, BIND_AUTO_CREATE);
        isBind = true;
    }

    /**
     * 取消綁定服務 IPC
     *
     * @author fengzhen
     * @version v1.0, 2017/7/21 15:28
     */
    public void unbindService(View view) {
        if (isBind) {
            isBind = false;
            unbindService(mServiceConnRemote);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章