Android – 開機後自動啟動的背景服務

也就是所謂的 On Boot Service. 當使用者重新啟動行動裝置之後, 將會在背景中執行的程序處理, 例如準備接收推播的Listener, 或是其他的背景服務程式, 可以用來偵測事件的觸發, 而發出通知等等.

 

Android O(8) 以前的處理模式


首先, 會需要一個使用權限為 RECEIVE_BOOT_COMPLETED:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

 

再來, 開發一個自訂的 BroadcastReceiver, 負責接收系統傳來的 Broadcast.

MyReceiver.java

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("brad", "MyReceiver: onReceive()");
        Intent it = new Intent(context, MyService.class);
        context.startService(it);
    }
}

 

回到AndroidManifest.xml, 設定其接收的action:

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

 

至此, 就要來開發 MyService.java

public class MyService extends Service {
    private Timer timer;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("brad", "MyService:onCreate()");

        timer = new Timer();
        timer.schedule(new MyTask(), 0, 1000);
    }

    private class MyTask extends TimerTask {
        @Override
        public void run() {
            Log.i("brad", "MyTask:run()");
        }
    }


}

此處建立一個TimerTask, 每隔一秒執行一次.

至此就可以安裝測試, 應該會在行動裝置重新開機之後, 不斷地一秒執行一次.

但是, 當行動裝置為Android 8(O)+,  就完全沒有任何反應. 以下來針對Android 8之後的版本處理.

 

Android O(8)+ 之後的處理


以上的處理程序不變.

回到 MyReceiver.java

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("brad", "MyReceiver: onReceive()");
        Intent it = new Intent(context, MyService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            context.startForegroundService(it); // 在 Huawei 上可以執行了七秒, 官網說五秒
        }else{
            context.startService(it);
        }

    }

}

透過 startForegroundService() 可以啟動 MyService, 但是只有幾秒而已. 但是已經可以滿足去設定像是推播的 Listener.

但是, 還是不能滿足原先的需求, 轉向思考啟動MainActivity, 再來帶出MyService:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("brad", "MyReceiver: onReceive()");
        Intent it = new Intent(context, MyService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//            context.startForegroundService(it); // 在 Huawei 上可以執行了七秒, 官網說五秒

            // 偷吃步 => 跑了一分鐘
            Intent it2 = new Intent(context, MainActivity.class);
            it2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(it2);
        }else{
            context.startService(it);
        }
    }
}

這樣會在開機之後, 閃一下白色區塊, 不到0.5秒就消失. 但是這一次, 竟然可以讓MyService的TimerTask跑一分鐘, 很準的.

還是不能滿足, 於是, 回到 startForegroundService() 啟動  MyService之後, 馬上來啟動一個背景MyService2.

MyService.java 如下: ( 不再處理 Timer/TimerTask)

public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("brad", "MyService:onCreate()");

        Intent it = new Intent(this, MyService2.class);
        startService(it);
    }
}

而啟動的MyService2, 如下:

public class MyService2 extends Service {
    private Timer timer;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("brad", "MyService2:onCreate()");

        timer = new Timer();
        timer.schedule(new MyTask2(), 0, 1000);
    }

    private class MyTask2 extends TimerTask {
        @Override
        public void run() {
            Log.i("brad", "MyTask2:run()");
        }
    }

}

 

別忘了, MyReceiver.java 要改回來:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("brad", "MyReceiver: onReceive()");
        Intent it = new Intent(context, MyService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            context.startForegroundService(it); // 在 Huawei 上可以執行了七秒, 官網說五秒

            // 偷吃步 => 跑了一分鐘
//            Intent it2 = new Intent(context, MainActivity.class);
//            it2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            context.startActivity(it2);

        }else{
            context.startService(it);
        }

    }

}

 

終於成功了. 您是看看吧!

 

 

 

 

 

 

 

本站資源一切隨緣,
不用註冊, 不看廣告
如果對您有所助益,
歡迎功德隨喜, 金額隨意,
請點擊以下...(感謝您)

功德箱/打賞箱

%d bloggers like this: