Android Service兩種啟動方式詳解(總結(jié)版)

Service生命周期.png

第一種方式:通過StartService啟動Service

通過startService啟動后熙揍,service會一直無限期運(yùn)行下去懂盐,只有外部調(diào)用了stopService()或stopSelf()方法時,該Service才會停止運(yùn)行并銷毀参淫。

要創(chuàng)建一個這樣的Service福稳,你需要讓該類繼承Service類,然后重寫以下方法:

  • onCreate()
    1.如果service沒被創(chuàng)建過途茫,調(diào)用startService()后會執(zhí)行onCreate()回調(diào)碟嘴;
    2.如果service已處于運(yùn)行中,調(diào)用startService()不會執(zhí)行onCreate()方法囊卜。
    也就是說娜扇,onCreate()只會在第一次創(chuàng)建service時候調(diào)用,多次執(zhí)行startService()不會重復(fù)調(diào)用onCreate()栅组,此方法適合完成一些初始化工作雀瓢。

  • onStartCommand()
    如果多次執(zhí)行了Context的startService()方法,那么Service的onStartCommand()方法也會相應(yīng)的多次調(diào)用玉掸。onStartCommand()方法很重要刃麸,我們在該方法中根據(jù)傳入的Intent參數(shù)進(jìn)行實(shí)際的操作,比如會在此處創(chuàng)建一個線程用于下載數(shù)據(jù)或播放音樂等司浪。

  • onBind()
    Service中的onBind()方法是抽象方法泊业,Service類本身就是抽象類,所以onBind()方法是必須重寫的啊易,即使我們用不到吁伺。

  • onDestory()
    在銷毀的時候會執(zhí)行Service該方法。

這幾個方法都是回調(diào)方法认罩,且在主線程中執(zhí)行箱蝠,由android操作系統(tǒng)在合適的時機(jī)調(diào)用。

startService代碼實(shí)例

創(chuàng)建TestOneService垦垂,并在manifest里注冊宦搬。
在MainActivty中操作TestOneService,code如下:

/**
 * Created by Kathy on 17-2-6.
 */

public class TestOneService extends Service{

    @Override
    public void onCreate() {
        Log.i("Kathy","onCreate - Thread ID = " + Thread.currentThread().getId());
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Kathy", "onStartCommand - startId = " + startId + ", Thread ID = " + Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("Kathy", "onBind - Thread ID = " + Thread.currentThread().getId());
        return null;
    }

    @Override
    public void onDestroy() {
        Log.i("Kathy", "onDestroy - Thread ID = " + Thread.currentThread().getId());
        super.onDestroy();
    }
}

在MainActivity中三次startService劫拗,之后stopService间校。

/**
 * Created by Kathy on 17-2-6.
 */

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("Kathy", "Thread ID = " + Thread.currentThread().getId());
        Log.i("Kathy", "before StartService");

        //連續(xù)啟動Service
        Intent intentOne = new Intent(this, TestOneService.class);
        startService(intentOne);
        Intent intentTwo = new Intent(this, TestOneService.class);
        startService(intentTwo);
        Intent intentThree = new Intent(this, TestOneService.class);
        startService(intentThree);

        //停止Service
        Intent intentFour = new Intent(this, TestOneService.class);
        stopService(intentFour);

        //再次啟動Service
        Intent intentFive = new Intent(this, TestOneService.class);
        startService(intentFive);

        Log.i("Kathy", "after StartService");
    }
}

打印出的Log如下:

        02-06 15:19:45.090 8938-8938/? I/Kathy: Thread ID = 1
        02-06 15:19:45.090 8938-8938/? I/Kathy: before StartService
        02-06 15:19:45.233 8938-8938/? I/Kathy: onCreate - Thread ID = 1
        02-06 15:19:45.234 8938-8938/? I/Kathy: onStartCommand - startId = 1, Thread ID = 1
        02-06 15:19:45.234 8938-8938/? I/Kathy: onStartCommand - startId = 2, Thread ID = 1
        02-06 15:19:45.235 8938-8938/? I/Kathy: onStartCommand - startId = 3, Thread ID = 1
        02-06 15:19:45.236 8938-8938/? I/Kathy: onDestroy - Thread ID = 1
        02-06 15:19:45.237 8938-8938/? I/Kathy: onCreate - Thread ID = 1
        02-06 15:19:45.237 8938-8938/? I/Kathy: onStartCommand - startId = 1, Thread ID = 1
        02-06 15:19:45.238 8938-8938/? I/Kathy: after StartService

分析:
1.主線程打印出是1,所有回調(diào)方法中打印出的執(zhí)行線程ID都是1页慷,證明回調(diào)方法都是在主線程中執(zhí)行的憔足。
2.三次調(diào)用startService,只觸發(fā)一次onCreate回調(diào)酒繁,觸發(fā)了三次onStartCommand回調(diào)滓彰,且startId分別為1州袒,2揭绑,3。證明 多次startService不會重復(fù)執(zhí)行onCreate回調(diào),但每次都會執(zhí)行onStartCommand回調(diào)他匪。

第二種方式:通過bindService啟動Service

bindService啟動服務(wù)特點(diǎn):
1.bindService啟動的服務(wù)和調(diào)用者之間是典型的client-server模式菇存。調(diào)用者是client,service則是server端邦蜜。service只有一個依鸥,但綁定到service上面的client可以有一個或很多個。這里所提到的client指的是組件悼沈,比如某個Activity贱迟。
2.client可以通過IBinder接口獲取Service實(shí)例,從而實(shí)現(xiàn)在client端直接調(diào)用Service中的方法以實(shí)現(xiàn)靈活交互絮供,這在通過startService方法啟動中是無法實(shí)現(xiàn)的关筒。
3.bindService啟動服務(wù)的生命周期與其綁定的client息息相關(guān)。當(dāng)client銷毀時杯缺,client會自動與Service解除綁定。當(dāng)然睡榆,client也可以明確調(diào)用Context的unbindService()方法與Service解除綁定萍肆。當(dāng)沒有任何client與Service綁定時,Service會自行銷毀胀屿。

bindService代碼實(shí)例

交互界面設(shè)計如下:


ActivityA界面布局.png

ActivityB界面布局.png

1.創(chuàng)建一個TestTwoService繼承Service(Server)
2.創(chuàng)建ActivityA塘揣,可以通過bindService綁定服務(wù)(client)
3.創(chuàng)建ActivityB,可以通過bindService綁定服務(wù)(client)
4.ActivityA可以跳轉(zhuǎn)到ActivityB

TestTwoService創(chuàng)建如下:
要想讓Service支持bindService調(diào)用方式宿崭,需要做以下事情:
1.在Service的onBind()方法中返回IBinder類型的實(shí)例亲铡。
2.onBInd()方法返回的IBinder的實(shí)例需要能夠返回Service實(shí)例本身。通常葡兑,最簡單的方法就是在service中創(chuàng)建binder的內(nèi)部類奖蔓,加入類似getService()的方法返回Service,這樣綁定的client就可以通過getService()方法獲得Service實(shí)例了讹堤。

/**
 * Created by Kathy on 17-2-6.
 */

public class TestTwoService extends Service{

    //client 可以通過Binder獲取Service實(shí)例
    public class MyBinder extends Binder {
        public TestTwoService getService() {
            return TestTwoService.this;
        }
    }

    //通過binder實(shí)現(xiàn)調(diào)用者client與Service之間的通信
    private MyBinder binder = new MyBinder();

    private final Random generator = new Random();

    @Override
    public void onCreate() {
        Log.i("Kathy","TestTwoService - onCreate - Thread = " + Thread.currentThread().getName());
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Kathy", "TestTwoService - onStartCommand - startId = " + startId + ", Thread = " + Thread.currentThread().getName());
        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("Kathy", "TestTwoService - onBind - Thread = " + Thread.currentThread().getName());
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("Kathy", "TestTwoService - onUnbind - from = " + intent.getStringExtra("from"));
        return false;
    }

    @Override
    public void onDestroy() {
        Log.i("Kathy", "TestTwoService - onDestroy - Thread = " + Thread.currentThread().getName());
        super.onDestroy();
    }

    //getRandomNumber是Service暴露出去供client調(diào)用的公共方法
    public int getRandomNumber() {
        return generator.nextInt();
    }
}

client端要做的事情:
1.創(chuàng)建ServiceConnection類型實(shí)例吆鹤,并重寫onServiceConnected()方法和onServiceDisconnected()方法。
2.當(dāng)執(zhí)行到onServiceConnected回調(diào)時洲守,可通過IBinder實(shí)例得到Service實(shí)例對象疑务,這樣可實(shí)現(xiàn)client與Service的連接。
3.onServiceDisconnected回調(diào)被執(zhí)行時梗醇,表示client與Service斷開連接知允,在此可以寫一些斷開連接后需要做的處理。

創(chuàng)建ActivityA叙谨,代碼如下:

/**
 * Created by Kathy on 17-2-6.
 */
public class ActivityA extends Activity implements Button.OnClickListener {
    private TestTwoService service = null;
    private boolean isBind = false;

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBind = true;
            TestTwoService.MyBinder myBinder = (TestTwoService.MyBinder) binder;
            service = myBinder.getService();
            Log.i("Kathy", "ActivityA - onServiceConnected");
            int num = service.getRandomNumber();
            Log.i("Kathy", "ActivityA - getRandomNumber = " + num);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.i("Kathy", "ActivityA - onServiceDisconnected");
        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        Log.i("Kathy", "ActivityA - onCreate - Thread = " + Thread.currentThread().getName());

        findViewById(R.id.btnBindService).setOnClickListener(this);
        findViewById(R.id.btnUnbindService).setOnClickListener(this);
        findViewById(R.id.btnStartActivityB).setOnClickListener(this);
        findViewById(R.id.btnFinish).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btnBindService) {
            //單擊了“bindService”按鈕
            Intent intent = new Intent(this, TestTwoService.class);
            intent.putExtra("from", "ActivityA");
            Log.i("Kathy", "----------------------------------------------------------------------");
            Log.i("Kathy", "ActivityA 執(zhí)行 bindService");
            bindService(intent, conn, BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.btnUnbindService) {
            //單擊了“unbindService”按鈕
            if (isBind) {
                Log.i("Kathy",
                        "----------------------------------------------------------------------");
                Log.i("Kathy", "ActivityA 執(zhí)行 unbindService");
                unbindService(conn);
            }
        } else if (v.getId() == R.id.btnStartActivityB) {
            //單擊了“start ActivityB”按鈕
            Intent intent = new Intent(this, ActivityB.class);
            Log.i("Kathy",
                    "----------------------------------------------------------------------");
            Log.i("Kathy", "ActivityA 啟動 ActivityB");
            startActivity(intent);
        } else if (v.getId() == R.id.btnFinish) {
            //單擊了“Finish”按鈕
            Log.i("Kathy",
                    "----------------------------------------------------------------------");
            Log.i("Kathy", "ActivityA 執(zhí)行 finish");
            this.finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("Kathy", "ActivityA - onDestroy");
    }
}

創(chuàng)建ActivityB温鸽,代碼如下:

/**
 * Created by Kathy on 17-2-6.
 */
public class ActivityB extends Activity implements Button.OnClickListener {

    private TestTwoService service = null;

    private boolean isBind = false;

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBind = true;
            TestTwoService.MyBinder myBinder = (TestTwoService.MyBinder)binder;
            service = myBinder.getService();
            Log.i("Kathy", "ActivityB - onServiceConnected");
            int num = service.getRandomNumber();
            Log.i("Kathy", "ActivityB - getRandomNumber = " + num);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.i("Kathy", "ActivityB - onServiceDisconnected");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);

        findViewById(R.id.btnBindService).setOnClickListener(this);
        findViewById(R.id.btnUnbindService).setOnClickListener(this);
        findViewById(R.id.btnFinish).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.btnBindService){
            //單擊了“bindService”按鈕
            Intent intent = new Intent(this, TestTwoService.class);
            intent.putExtra("from", "ActivityB");
            Log.i("Kathy", "----------------------------------------------------------------------");
            Log.i("Kathy", "ActivityB 執(zhí)行 bindService");
            bindService(intent, conn, BIND_AUTO_CREATE);
        }else if(v.getId() == R.id.btnUnbindService){
            //單擊了“unbindService”按鈕
            if(isBind){
                Log.i("Kathy", "----------------------------------------------------------------------");
                Log.i("Kathy", "ActivityB 執(zhí)行 unbindService");
                unbindService(conn);
            }
        }else if(v.getId() == R.id.btnFinish){
            //單擊了“Finish”按鈕
            Log.i("Kathy", "----------------------------------------------------------------------");
            Log.i("Kathy", "ActivityB 執(zhí)行 finish");
            this.finish();
        }
    }
    @Override
    public void onDestroy(){
        super.onDestroy();
        Log.i("Kathy", "ActivityB - onDestroy");
    }
}

測試步驟1

step1: 點(diǎn)擊ActivityA的bindService按鈕
step2: 再點(diǎn)擊ActivityA的unbindService按鈕
Log輸出:

02-07 14:09:38.031 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main
02-07 14:09:39.488 1738-1738/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:09:39.488 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 bindService
02-07 14:09:39.496 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main
02-07 14:09:39.497 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main
02-07 14:09:39.500 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected
02-07 14:09:39.500 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -1046987376
02-07 14:09:50.866 1738-1738/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:09:50.866 1738-1738/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 unbindService
02-07 14:09:50.870 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA
02-07 14:09:50.871 1738-1738/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

總結(jié)調(diào)用bindService之后發(fā)生的事情:
1.client執(zhí)行bindService()
2.如果Service不存在,則Service執(zhí)行onCreate(),onBind()
3.client實(shí)例ServiceConnection執(zhí)行onServiceConnected()方法

總結(jié)調(diào)用unbindService之后發(fā)生的事情:
1.client執(zhí)行unbindService()
2.client與Service解除綁定連接狀態(tài)
3.Service檢測是否還有其他client與其連接唉俗,如果沒有Service執(zhí)行onUnbind()和onDestroy()

測試步驟2

step1: 點(diǎn)擊ActivityA的bindService按鈕
step2: 再點(diǎn)擊ActivityA的Finish按鈕
Log 輸出:

02-07 14:49:16.626 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main
02-07 14:49:18.102 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:49:18.102 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 bindService
02-07 14:49:18.105 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main
02-07 14:49:18.110 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main
02-07 14:49:18.112 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected
02-07 14:49:18.112 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -318399886
02-07 14:49:19.540 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:49:19.540 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 finish
02-07 14:49:19.789 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onDestroy
02-07 14:49:19.798 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA
02-07 14:49:19.798 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

總結(jié):如果client銷毀嗤朴,那么client會自動與Service解除綁定配椭。

測試步驟3

step1: 點(diǎn)擊ActivityA的bindService按鈕
step2: 點(diǎn)擊ActivityA的startActivity B按鈕,切換到ActivityB
step3: 點(diǎn)擊ActivityB中的bindService按鈕
step4: 點(diǎn)擊ActivityB中的unbindService按鈕
step5: 點(diǎn)擊ActivityB中的Finish按鈕
step6: 點(diǎn)擊ActivityA中的unbindService按鈕
得到Log:

02-07 14:55:04.390 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onCreate - Thread = main
02-07 14:55:08.191 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:08.191 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 bindService
02-07 14:55:08.197 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onCreate - Thread = main
02-07 14:55:08.198 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onBind - Thread = main
02-07 14:55:08.205 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - onServiceConnected
02-07 14:55:08.205 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA - getRandomNumber = -706215542
02-07 14:55:23.261 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:23.261 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 啟動 ActivityB
02-07 14:55:29.239 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:29.239 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 執(zhí)行 bindService
02-07 14:55:29.241 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - onServiceConnected
02-07 14:55:29.241 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - getRandomNumber = 1827572726
02-07 14:55:33.951 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:33.951 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 執(zhí)行 unbindService
02-07 14:55:36.645 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:36.645 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB 執(zhí)行 finish
02-07 14:55:36.852 12566-12566/com.demo.kathy.demo I/Kathy: ActivityB - onDestroy
02-07 14:55:43.137 12566-12566/com.demo.kathy.demo I/Kathy: ----------------------------------------------------------------------
02-07 14:55:43.137 12566-12566/com.demo.kathy.demo I/Kathy: ActivityA 執(zhí)行 unbindService
02-07 14:55:43.143 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onUnbind - from = ActivityA
02-07 14:55:43.143 12566-12566/com.demo.kathy.demo I/Kathy: TestTwoService - onDestroy - Thread = main

總結(jié)bindService的生命周期:
1.點(diǎn)擊ActivityA的bindService按鈕
第一次調(diào)用bindService會實(shí)例化TestTwoService雹姊,然后執(zhí)行其onBind()方法股缸,得到IBinder類型的實(shí)例,將其作為參數(shù)傳入ActivityA的ServiceConnection的onServiceConnected方法中吱雏,標(biāo)志著ActivityA與TestTwoService建立了綁定敦姻。

2.點(diǎn)擊ActivityB中的bindService按鈕
由于TestTwoService已處于運(yùn)行狀態(tài),所以再次調(diào)用bindService不會重新創(chuàng)建它的實(shí)例歧杏,所以也不會執(zhí)行TestTwoService的onCreate()方法和onBind()方法镰惦。ActivityB與ActivityA共享IBinder實(shí)例。此時有兩個client與TestTwoService綁定犬绒。

3.點(diǎn)擊ActivityB中的unbindService按鈕
ActivityB與TestTwoService解除了綁定旺入,當(dāng)沒有任何client與Service綁定時,才會執(zhí)行Service的onUnbind()方法凯力。此時茵瘾,ActivityA還在綁定連接中,所以不會執(zhí)行Service的解綁方法咐鹤。

4.點(diǎn)擊ActivityA中的unbindService按鈕
ActivityA執(zhí)行unbindService之后拗秘,ActivityA與TestTwoService就解除綁定了,這樣就沒有client與TestTwoService綁定祈惶,這時候Android會銷毀TestTwoService雕旨,在銷毀前會先執(zhí)行TestTwoService的onUnbind()方法,然后才會執(zhí)行其onDestroy()方法捧请,這樣TestService就銷毀了凡涩。

如何保證Service不被殺死?

1. onStartCommand方式中疹蛉,返回START_STICKY

首先我們來看看onStartCommand都可以返回哪些值:

調(diào)用Context.startService方式啟動Service時突照,如果Android面臨內(nèi)存匱乏,可能會銷毀當(dāng)前運(yùn)行的Service氧吐,待內(nèi)存充足時可以重建Service讹蘑。而Service被Android系統(tǒng)強(qiáng)制銷毀并再次重建的行為依賴于Service的onStartCommand()方法的返回值。

  • START_NOT_STICKY
    如果返回START_NOT_STICKY筑舅,表示當(dāng)Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后座慰,不會重新創(chuàng)建該Service。當(dāng)然如果在其被殺掉之后一段時間又調(diào)用了startService翠拣,那么該Service又將被實(shí)例化版仔。那什么情境下返回該值比較恰當(dāng)呢?
    如果我們某個Service執(zhí)行的工作被中斷幾次無關(guān)緊要或者對Android內(nèi)存緊張的情況下需要被殺掉且不會立即重新創(chuàng)建這種行為也可接受,那么我們便可將 onStartCommand的返回值設(shè)置為START_NOT_STICKY蛮粮。
    舉個例子益缎,某個Service需要定時從服務(wù)器獲取最新數(shù)據(jù):通過一個定時器每隔指定的N分鐘讓定時器啟動Service去獲取服務(wù)端的最新數(shù)據(jù)。當(dāng)執(zhí)行到Service的onStartCommand時然想,在該方法內(nèi)再規(guī)劃一個N分鐘后的定時器用于再次啟動該Service并開辟一個新的線程去執(zhí)行網(wǎng)絡(luò)操作莺奔。假設(shè)Service在從服務(wù)器獲取最新數(shù)據(jù)的過程中被Android系統(tǒng)強(qiáng)制殺掉,Service不會再重新創(chuàng)建变泄,這也沒關(guān)系令哟,因?yàn)樵龠^N分鐘定時器就會再次啟動該Service并重新獲取數(shù)據(jù)。

  • START_STICKY
    如果返回START_STICKY妨蛹,表示Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后屏富,Android系統(tǒng)會將該Service依然設(shè)置為started狀態(tài)(即運(yùn)行狀態(tài)),但是不再保存onStartCommand方法傳入的intent對象蛙卤,然后Android系統(tǒng)會嘗試再次重新創(chuàng)建該Service狠半,并執(zhí)行onStartCommand回調(diào)方法,但是onStartCommand回調(diào)方法的Intent參數(shù)為null颤难,也就是onStartCommand方法雖然會執(zhí)行但是獲取不到intent信息典予。如果你的Service可以在任意時刻運(yùn)行或結(jié)束都沒什么問題,而且不需要intent信息乐严,那么就可以在onStartCommand方法中返回START_STICKY,比如一個用來播放背景音樂功能的Service就適合返回該值衣摩。

  • START_REDELIVER_INTENT
    如果返回START_REDELIVER_INTENT昂验,表示Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后,與返回START_STICKY的情況類似艾扮,Android系統(tǒng)會將再次重新創(chuàng)建該Service既琴,并執(zhí)行onStartCommand回調(diào)方法,但是不同的是泡嘴,Android系統(tǒng)會再次將Service在被殺掉之前最后一次傳入onStartCommand方法中的Intent再次保留下來并再次傳入到重新創(chuàng)建后的Service的onStartCommand方法中甫恩,這樣我們就能讀取到intent參數(shù)。只要返回START_REDELIVER_INTENT酌予,那么onStartCommand重的intent一定不是null磺箕。如果我們的Service需要依賴具體的Intent才能運(yùn)行(需要從Intent中讀取相關(guān)數(shù)據(jù)信息等),并且在強(qiáng)制銷毀后有必要重新創(chuàng)建運(yùn)行抛虫,那么這樣的Service就適合返回START_REDELIVER_INTENT松靡。

2.提高Service的優(yōu)先級
在AndroidManifest.xml文件中對于intent-filter可以通過android:priority = "1000"這個屬性設(shè)置最高優(yōu)先級,1000是最高值建椰,如果數(shù)字越小則優(yōu)先級越低雕欺,同時適用于廣播。

3.提升Service進(jìn)程的優(yōu)先級

當(dāng)系統(tǒng)進(jìn)程空間緊張時,會依照優(yōu)先級自動進(jìn)行進(jìn)程的回收屠列。
Android將進(jìn)程分為6個等級啦逆,按照優(yōu)先級由高到低依次為:

  • 前臺進(jìn)程foreground_app
  • 可視進(jìn)程visible_app
  • 次要服務(wù)進(jìn)程secondary_server
  • 后臺進(jìn)程hiddena_app
  • 內(nèi)容供應(yīng)節(jié)點(diǎn)content_provider
  • 空進(jìn)程empty_app
    可以使用startForeground將service放到前臺狀態(tài),這樣低內(nèi)存時笛洛,被殺死的概率會低一些夏志。

4.在onDestroy方法里重啟Service
當(dāng)service走到onDestroy()時,發(fā)送一個自定義廣播撞蜂,當(dāng)收到廣播時盲镶,重新啟動service。

5.系統(tǒng)廣播監(jiān)聽Service狀態(tài)
6.將APK安裝到/system/app蝌诡,變身為系統(tǒng)級應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溉贿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浦旱,更是在濱河造成了極大的恐慌宇色,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颁湖,死亡現(xiàn)場離奇詭異宣蠕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)甥捺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門抢蚀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人镰禾,你說我怎么就攤上這事皿曲。” “怎么了吴侦?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵屋休,是天一觀的道長。 經(jīng)常有香客問我备韧,道長劫樟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任织堂,我火速辦了婚禮叠艳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘易阳。我一直安慰自己虑绵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布闽烙。 她就那樣靜靜地躺著翅睛,像睡著了一般声搁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捕发,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天疏旨,我揣著相機(jī)與錄音,去河邊找鬼扎酷。 笑死檐涝,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的法挨。 我是一名探鬼主播谁榜,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼凡纳!你這毒婦竟也來了窃植?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤荐糜,失蹤者是張志新(化名)和其女友劉穎巷怜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暴氏,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡延塑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了答渔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片关带。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沼撕,靈堂內(nèi)的尸體忽然破棺而出宋雏,到底是詐尸還是另有隱情,我是刑警寧澤端朵,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站燃箭,受9級特大地震影響冲呢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜招狸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一敬拓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧裙戏,春花似錦乘凸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灵嫌。三九已至,卻和暖如春葛作,著一層夾襖步出監(jiān)牢的瞬間寿羞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工赂蠢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绪穆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓虱岂,卻偏偏與公主長得像玖院,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子第岖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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

  • 前言:本文所寫的是博主的個人見解难菌,如有錯誤或者不恰當(dāng)之處,歡迎私信博主绍傲,加以改正扔傅!原文鏈接,demo鏈接 Serv...
    PassersHowe閱讀 1,405評論 0 5
  • 服務(wù)基本上分為兩種形式 啟動 當(dāng)應(yīng)用組件(如 Activity)通過調(diào)用 startService() 啟動服務(wù)時...
    pifoo閱讀 1,256評論 0 8
  • 描述 Service通程瘫總是稱之為“后臺服務(wù)”猎塞,其中“后臺”一詞是相對于前臺而言的,具體是指其本身的運(yùn)行并不依賴于...
    pkqgo閱讀 651評論 1 3
  • 什么是Service 先看一下google官方的介紹: Service是一個可以在后臺執(zhí)行長時間運(yùn)行操作而不提供用...
    Cris_Ma閱讀 745評論 0 0
  • 90天視覺記錄練習(xí)已經(jīng)過去一半啦杠纵,最近忙著參加堅持星球演講訓(xùn)練營荠耽,還在忙著開發(fā)自己的場景思維導(dǎo)圖訓(xùn)練營課程,視覺記...
    世界記憶大師程程閱讀 140評論 0 0