簡體   English   中英

Android 在啟動時啟動服務,如何在設備重啟后重啟服務類?

[英]Android Starting Service at Boot Time , How to restart service class after device Reboot?

我需要在啟動時啟動服務。 我搜索了很多。 他們正在談論廣播接收器。 由於我是 android 開發的新手,我沒有對 Android 上的服務有一個清晰的了解。 請提供一些源代碼。

您的接收器:

public class MyReceiver extends BroadcastReceiver {   

    @Override
    public void onReceive(Context context, Intent intent) {

     Intent myIntent = new Intent(context, YourService.class);
     context.startService(myIntent);

    }
}

您的 AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.broadcast.receiver.example"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">

        <activity android:name=".BR_Example"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
        <receiver android:name=".MyReceiver" android:enabled="true" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

    </application>

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

</manifest>

可以注冊您自己的應用程序服務,以便在設備啟動時自動啟動。 例如,當您希望從 http 服務器接收推送事件並希望在新事件發生時立即通知用戶時,您就需要這樣做。 用戶不必在服務啟動之前手動啟動活動...

這很簡單。 首先為您的應用授予 RECEIVE_BOOT_COMPLETED 權限。 接下來你需要注冊一個 BroadcastReveiver。 我們稱之為 BootCompletedIntentReceiver。

您的 Manifest.xml 現在應如下所示:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jjoe64"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application> <receiver android:name=".BootCompletedIntentReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <service android:name=".BackgroundService"/> </application> </manifest>

作為最后一步,您必須實現接收器。 這個接收器只是啟動你的后台服務。

 package com.jjoe64; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import com.jjoe64.BackgroundService; public class BootCompletedIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { Intent pushIntent = new Intent(context, BackgroundService.class); context.startService(pushIntent); } } }

來自http://www.jjoe64.com/2011/06/autostart-service-on-device-boot.html

此處發布的大多數解決方案都缺少一個重要的部分:在沒有喚醒鎖的情況下執行此操作會冒着服務在完成處理之前被殺死的風險。 在另一個線程中看到了這個解決方案,也在這里回答。

由於WakefulBroadcastReceiver在 api 26 中已棄用,因此建議API 級別低於 26

您需要獲得喚醒鎖。 幸運的是, Support 庫為我們提供了一個類來執行此操作:

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

然后,在您的服務中,確保釋放喚醒鎖:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

不要忘記添加 WAKE_LOCK 權限並在清單中注冊您的接收器:

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

...

<service android:name=".SimpleWakefulReceiver">
    <intent-filter>
        <action android:name="com.example.SimpleWakefulReceiver"/>
    </intent-filter>
</service>

您應該注冊 BOOT_COMPLETE 以及 REBOOT

<receiver android:name=".Services.BootComplete">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
        </intent-filter>
    </receiver> 

還要在清單中注冊您創建的服務,並將使用權限注冊為

<application ...>
   <service android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.example.MyBroadcastReciver"/>
        </intent-filter>
   </service>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

然后在braod cast Reciever call你的服務

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent myIntent = new Intent(context, MyService.class);
        context.startService(myIntent);
    }
}

Android O或更高版本中重啟服務,即 OS >28 使用此代碼KOTLIN VERSION 1) 在清單中添加權限

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

2) 創建一個Class並用BroadcastReceiver擴展它

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat



class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, arg1: Intent?) {
        Log.d("BootCompletedReceiver", "starting service...")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, Intent(context, YourServiceClass::class.java))
        } else {
            context.startService(Intent(context, YourServiceClass::class.java))
        }
    }
}

3)在應用程序標簽下像這樣在清單文件中聲明

<receiver android:name=".utils.BootCompletedReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

首先在 manifest.xml 文件中注冊一個接收器:

    <receiver android:name="com.mileagelog.service.Broadcast_PowerUp" >
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

然后為這個接收器編寫一個廣播,如:

public class Broadcast_PowerUp extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
        Toast.makeText(context, "Service_PowerUp Started",
                Toast.LENGTH_LONG).show();


    } else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {



        Toast.makeText(context, "Service_PowerUp Stoped", Toast.LENGTH_LONG)
        .show();
    }
  }
}

請檢查JobScheduler是否有 26 以上的 api

WakeLock是最好的選擇,但它在 api 級別 26 中已棄用,如果您認為 api 級別高於 26,請檢查此鏈接
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html#startWakefulService(android.content.Context,%20android.content.Intent)

它說

從 Android O 開始,背景檢查限制使此類不再普遍有用。 (從接收到廣播開始服務通常是不安全的,因為此時您無法保證您的應用程序在前台,因此被允許這樣做。)相反,開發人員應該使用android。 app.job.JobScheduler來安排作業,這不需要應用程序在執行此操作時持有喚醒鎖(系統將負責為作業持有喚醒鎖)。

所以正如它所說的cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

如果是做某事而不是開始並保持它,您可以接收廣播 ACTION_BOOT_COMPLETED

如果不是關於前台請檢查無障礙服務是否可以做

另一種選擇是從廣播接收器啟動活動並在 onCreate() 內啟動服務后完成它,因為較新的 android 版本不允許從接收器啟動服務

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM