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

问题描述 投票:0回答:1

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

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

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

这是我的android测试方法。

@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);
        }
    }
}

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

android android-pendingintent android-alarms
1个回答
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" />
© www.soinside.com 2019 - 2024. All rights reserved.