Android:警报服务无法正常工作

时间:2016-01-31 20:07:49

标签: android

我正在尝试创建一个简单的警报应用程序,警报应在几天后发生。

我创建了一项服务,根据首选项中保存的数据注册警报管理器。一切都运行正常,只是当应用程序没有运行时它不会触发警报。

AlarmService.java

   @Override
    protected void onHandleIntent(Intent intent) {

        Toast.makeText(this,"Service started",Toast.LENGTH_LONG);
        //set separate pending intent values for all days
        setIntents();
        // register the alarm manager here
        alarmManager = (AlarmManager)(getSystemService(Context.ALARM_SERVICE));
        execute();
    }

    private void execute() {

        prefs=getSharedPreferences("user_data_pref",Context.MODE_PRIVATE);
        prefEditor=prefs.edit();

        int hour=prefs.getInt("ALARM_HOUR",0);
        int minute=prefs.getInt("ALARM_MINUTE",0);

        if(prefs.getString("ALARM_STATUS","NOT_SET").equals("SET"))
            isAlarmOn=true;
        if(prefs.getString("NOTIFICATION_STATUS","NOT_SET").equals("SET"))
            isNotificationOn=true;

        if (prefs.getBoolean("MON_SET",false)) {
            setAlarmFor(Calendar.MONDAY,hour,minute,mondayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("TUE_SET",false)) {
            setAlarmFor(Calendar.TUESDAY,hour,minute,tuesdayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("WED_SET",false)) {
            setAlarmFor(Calendar.WEDNESDAY,hour,minute,wednesdayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("THU_SET",false)) {
            setAlarmFor(Calendar.THURSDAY,hour,minute,thursdayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("FRI_SET",false)) {
            setAlarmFor(Calendar.FRIDAY,hour,minute,fridayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("SAT_SET",false)) {
            setAlarmFor(Calendar.SATURDAY,hour,minute,saturdayIntent,isAlarmOn,isNotificationOn);
        }
        if (prefs.getBoolean("SUN_SET",false)) {
            setAlarmFor(Calendar.SUNDAY,hour,minute,sundayIntent,isAlarmOn,isNotificationOn);
        }
}
    private void setAlarmFor(int weekday, int hour, int minute, PendingIntent pendingIntent, boolean isAlarmOn, boolean isNotificationOn){
        if(isAlarmOn){
            prefEditor.putString("ALARM_STATUS","SET");
            prefEditor.commit();
        }
        if(isNotificationOn){
            prefEditor.putString("NOTIFICATION_STATUS","SET");
            prefEditor.commit();
        }

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_WEEK,weekday);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND,0);

        /* Repeating on every week interval */
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                7*24*60*60*1000, pendingIntent);
    }
    private void setIntents(){
        Intent intent = new Intent(this,AlarmReceiver.class);
        mondayIntent=PendingIntent.getBroadcast(this, Calendar.MONDAY, intent, 0);
        tuesdayIntent=PendingIntent.getBroadcast(this, Calendar.TUESDAY, intent, 0);
        wednesdayIntent=PendingIntent.getBroadcast(this, Calendar.WEDNESDAY, intent, 0);
        thursdayIntent=PendingIntent.getBroadcast(this, Calendar.THURSDAY, intent, 0);
        fridayIntent=PendingIntent.getBroadcast(this, Calendar.FRIDAY, intent, 0);
        saturdayIntent=PendingIntent.getBroadcast(this, Calendar.SATURDAY, intent, 0);
        sundayIntent=PendingIntent.getBroadcast(this, Calendar.SUNDAY, intent, 0);
    }

它应该触发显示警报的AlarmReceiver类。

AlarmReceiver.java

    @Override
public void onReceive(Context context, Intent intent) {
    prefs=context.getSharedPreferences("user_data_pref",Context.MODE_PRIVATE);
    //Get Status of currently set alarm and notification
    alarmStatus=prefs.getString("ALARM_STATUS","NOT_SET");
    notificationStatus=prefs.getString("NOTIFICATION_STATUS","NOT_SET");
    //Send notification if the notification is set
    if(notificationStatus.equals("SET")){
        Toast.makeText(context, "NOTIFICATION START SUCCESSFUL", Toast.LENGTH_SHORT).show();
        playNotificationSound(context,getNotificationSound());
        NotificationCompat.Builder mBuilder =   new NotificationCompat.Builder(context)
                .setContentTitle("") // title for notification
                .setContentText("") // message for notification
                .setAutoCancel(true); // clear notification after click
        Intent intent_1 = new Intent(context, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(context, 11, intent_1, Intent.FLAG_ACTIVITY_NEW_TASK);
        mBuilder.setContentIntent(pi);
        NotificationManager mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(0, mBuilder.build());
        displayNotification(context);
    }
    //Fire Alarm if the Alarm is set
    if(alarmStatus.equals("SET")){
        Toast.makeText(context, "ALARM START SUCCESSFUL", Toast.LENGTH_SHORT).show();
        /** Creating Alarm */
        Intent i = new Intent(context,FitterfoxAlarmActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    }
}

的AndroidManifest.xml

<receiver android:name=".OnBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <receiver android:name=".AlarmReceiver"></receiver>

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

2 个答案:

答案 0 :(得分:0)

尝试这套代码,您的服务永远不会阻止它为我工作。 &#34; alarmManager.setRepeating&#34;许多棒棒糖和棉花糖设备一旦启动就无法工作,然后失去对服务的控制,这将有助于你。

if (android.os.Build.VERSION.SDK_INT >= 23) {
    piLR = PendingIntent.getBroadcast(context, 0, intentLR,
            PendingIntent.FLAG_UPDATE_CURRENT);
    amLR.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            interval, piLR);
} else if (android.os.Build.VERSION.SDK_INT >= 19
        && android.os.Build.VERSION.SDK_INT < 23) {
    piLR = PendingIntent.getBroadcast(context, 0, intentLR,
            PendingIntent.FLAG_UPDATE_CURRENT);
    amLR.setInexactRepeating(AlarmManager.RTC_WAKEUP,
            System.currentTimeMillis(), interval, piLR);
} else {
    amLR.setRepeating(AlarmManager.RTC_WAKEUP,
            System.currentTimeMillis(), interval, piLR);
}

答案 1 :(得分:0)

从KitKat开始,对AlarmManager进行了更改,以提高设备的电池寿命。警报触发的时间不太准确。如果您希望闹钟在预定时间的几分钟内触发,则需要更改使用AlarmManager的方式。

对于KitKat(API 19)及更高版本的构建,setRepeating()中指定的时间不准确,如documentation中所述。文档还注意到:

  

如果您的应用程序需要精确的交付时间,则必须使用   一次性精确报警,每次重新安排。

您指示在应用未运行时警报不会触发。由于警报的周期为一周,因此计划时间与警报触发的实际时间之间可能存在较大差异。 documentation表示:

  

您的闹钟的第一次触发不会在请求的时间之前,但是   在此之后几乎整整一段时间内可能不会发生。

我怀疑使用您当前的代码,您最终会看到警报响起,但可能需要在预期时间后等待很长时间。

您修改后的代码可能需要使用setWindow()

Marshmallow介绍了Doze模式,它进一步改变了警报调度。正如@Andy在他的回答中指出的那样,为了在Marshmallow和更高版本的设备上得到你想要的优点,你需要使用setExactAndAllowWhileIdle()

另外两件需要修复的事情。您的PendingIntents可能应该使用标记PendingIntent.FLAG_UPDATE_CURRENT。在您的收件人中,标记Intent.FLAG_ACTIVITY_NEW_TASK属于intent_1,而非pi

相关问题