35

我尝试了各种方法来实现这一点,但我的服务最终被杀死了。

我想使用 AlarmManager 每隔一小时触发一次课程。即使设备处于睡眠状态,它也应该发送闪烁的 LED 警报、振动或声音。无论如何,它应该永远运行。

我注意到 Whatsapp 一直在运行,即使我杀死了所有正在运行的应用程序并清除内存,让设备进入睡眠状态,但 Whatsapp 仍然会收到消息并提醒我。他们是怎么做到的?我想对我的应用程序做同样的事情。

4

5 回答 5

30

注意:现在此答案仅对 ANDROID 7 及以下版本有效。由于 Android 8 谷歌改变了后台任务的处理方式

自从我发布这个问题以来,我已经将此解决方案的两种不同方法实施到多个应用程序中。


方法 1

此摘录来自我使用推送通知的应用程序,该应用程序需要设备的即时唤醒呼叫。我在这里做的是

  1. 使用 WAKE_LOCK 权限和
  2. 使用 Wakelocker 抽象类
  3. 根据需要在 Activity 中使用它:

显现:

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

唤醒锁类:

public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;

public static void acquire(Context context) {
    if (wakeLock != null) wakeLock.release();

    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
            PowerManager.ACQUIRE_CAUSES_WAKEUP |
            PowerManager.ON_AFTER_RELEASE, "WakeLock");
    wakeLock.acquire();
}

public static void release() {
    if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}

活动类示例:

private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());
        // do something
        WakeLocker.release();
}

方法 2

最好让 Android 控制唤醒,并且可以定期唤醒您的代码。只需使用 AlarmManager 定期调用服务类。这是我的 LifeLog24 应用程序中的一些代码:

主要活动

Intent ll24 = new Intent(context, AlarmReceiverLifeLog.class);
    PendingIntent recurringLl24 = PendingIntent.getBroadcast(context, 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarms.setRepeating(AlarmManager.RTC_WAKEUP, first_log.getTime(), AlarmManager.INTERVAL_HOUR, recurringLl24); // Log repetition

报警等级

public class AlarmReceiverLifeLog extends BroadcastReceiver {

    private static final String TAG = "LL24";
    static Context context;

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

        Log.v(TAG, "Alarm for LifeLog...");

        Intent ll24Service = new Intent(context, LifeLogService.class);
        context.startService(ll24Service);
    }
    }

LifeLogService.class 是我做事的地方。在这种情况下,Alarm 每小时都会唤醒一次,并触发 BroadcastReceiver,后者反过来运行服务。还有更多,以确保服务不会运行两次等等,但你明白它是如何完成的。AlarmManager 实际上是最好的方法,因为您不必担心电池使用等问题,并且 Android 会定期唤醒您的服务。

于 2015-02-05T17:37:07.880 回答
11

这很简单。
步骤:
1.创建一个服务类。
2.创建一个BroadcastReceiver类3.在服务的onDestroy方法中
调用BroadReceiver 4.在BroadReceiver类的onReceive方法中再次启动服务。

这是代码

清单文件: `

<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=".LauncherActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name=".utilities.NotificationService"
        android:enabled="true">

    </service>

    <receiver
        android:name=".utilities.RestartService"
        android:enabled="true"
        android:exported="true"
        android:label="RestartServiceWhenStopped"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="RestartService" />
        </intent-filter>
    </receiver>
</application>

`

服务等级

public class NotificationService extends Service {
    public NotificationService() {
    }

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

   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
       super.onStartCommand(intent, flags, startId);
       return START_STICKY;
   }

   @Override
   public void onDestroy() {
       super.onDestroy();
       Intent restartService = new Intent("RestartService");
       sendBroadcast(restartService);
  }
}

广播接收器类

public class RestartService extends BroadcastReceiver {

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

         context.startService(new Intent(context,NotificationService.class));
     }
 }
于 2017-05-01T13:28:51.977 回答
2

按照这些简单的步骤,让 servce 在 android 设备中永远保持活力。1. 使用报警管理器调用服务。2. 在 onStart 方法中返回 START_STICKY。3. 在销毁时调用警报管理器并使用 startService 方法重新启动服务。4.(可选)在 onTaskRemoved 方法中重复第 3 点。

于 2017-09-17T12:11:08.233 回答
1

请求部分唤醒锁。

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

 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();

onStartCommand 重新运行 START_STICKY :

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId); 
        return START_STICKY;
    }
于 2013-10-13T12:20:00.823 回答
-1

您可以使用函数 startForeground(int, Notification)参见此处此处

启动的服务可以使用 startForeground(int, Notification) API 将服务置于前台状态,系统认为它是用户主动意识到的,因此在内存不足时不适合杀死。(理论上,在当前前台应用程序的极端内存压力下,服务仍然可能被杀死,但实际上这不应该是一个问题。)

于 2014-09-16T11:49:48.480 回答