AlarmManager不会触发或设置服务。相同的代码在不同的设备和不同的项目上的工作方式不同

时间:2018-03-01 11:28:05

标签: android android-pendingintent android-alarms

我很抱歉提出一个常见问题,
但我做了很多研究,仍然无法找到解决方案。

我也进行了一项Android测试,我将服务设置为即将触发,但下面的代码在我的两部手机上完全不同

其中一个7.0版的android版本永远不会工作,即使服务从未被触发过。 如果我将触发时间设置为System.currentTimeMillis(),则5.0版本的另一个版本成功运行,但它在当前时间之后的任何时间都不起作用(例如System.currentTimeMillis() + 2000)。如果通知发送成功,那么它会在很短的时间内消失。

这是我的安卓测试方法。

@Test
public void setAlarm(){
    Context context = InstrumentationRegistry.getTargetContext();

    Intent intent = new Intent(context, MedicationNotificationService.class);
    PendingIntent sender = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() , sender);
}

然后是我的详细服务代码。
MedicationNotification只是一个包含触发时间的POJO。
该服务发送通知并设置下一个警报。

public class MedicationNotificationService extends Service {
    private static final String TAG = "MedicationNfService";
    public MedicationNotificationService() {}

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MedicationNotification notification = (MedicationNotification) intent.getSerializableExtra(NOTIFICATION);
        Log.d(TAG, "Service started. notification: " + notification);
        NotificationUtils.showNotification(this, getString(R.string.itsTimeToMedicate),
                notification.getMedication().getName(), notification.getId());

        if (notification.getMedication().getEndDate().after(new Date()))  //set next notification if not expired
        {
            AlarmManagerUtils.arrangeMedicationNotification(this, notification);
            Log.d(TAG, "Medication does not expire, set the next alarm.");
        }
        else
            Log.d(TAG, "Medication expired, delete it.");
        return START_STICKY;
    }
}

我还确保我没有拼错这些服务'名。

<service
    android:name=".android.MedicationNotificationService">
</service>

最后,这是AlarmManager代码。它和我在测试方法中的做法一样。 PendingIndent的ID取决于MedicationNotification的id。 并设置确切的时间。

public class AlarmManagerUtils {

    public static void arrangeMedicationNotification(Context context, MedicationNotification notification){
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        if (alarmManager != null)
        {
            Intent alarmIntent = new Intent(context, MedicationNotificationService.class);
            alarmIntent.putExtra(NOTIFICATION, notification);
            PendingIntent pendingIntent = PendingIntent.getService(context, 50000 + notification.getId(),
                    alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, notification.getNotifyTime().getTimeInMillis(), pendingIntent);
        }
    }
}

感谢您的耐心等待,告诉我您是否需要更多信息,我真的花了几个小时来解决这个问题。这真的很奇怪,它曾经用于我的另一个项目。感谢。

1 个答案:

答案 0 :(得分:0)

用于在代码

下设置闹钟
if (SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP,  c.getTimeInMillis(), pendingIntent);
    }
    else if (Build.VERSION_CODES.KITKAT <= SDK_INT  && SDK_INT < Build.VERSION_CODES.M) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP,  c.getTimeInMillis(), pendingIntent);
    }
    else if (SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,  c.getTimeInMillis(), pendingIntent);
    }

在通知notify方法

后添加以下行
  PowerManager pm = (PowerManager) context
            .getSystemService(Context.POWER_SERVICE);

    boolean isScreenOn ;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        isScreenOn  = pm.isInteractive();
    }else {
        isScreenOn=pm.isScreenOn();
    }

    if (!isScreenOn) {

        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
                | PowerManager.ACQUIRE_CAUSES_WAKEUP
                | PowerManager.ON_AFTER_RELEASE, "MyLock");

        wl.acquire(10000);
        PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "MyCpuLock");

        wl_cpu.acquire(10000);
    }

并在清单

上添加此权限
 <uses-permission android:name="android.permission.WAKE_LOCK" />