2014-10-10 70 views
1

在我的應用中,用戶加入了一個計劃,然後第二天中午有一個報警通知。這裏是我的代碼:AlarmManager報警在手機重置後不會觸發

首先,我設置了一個警報AlarmManager像這樣:

//set alarm to the next day 12:00 noon of the join date 
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
try { 
    alarm_date = format.parse(join_date); 
} catch (ParseException e) { 
    e.printStackTrace(); 
} 

GregorianCalendar calender = new GregorianCalendar(); 
calender.setTime(alarm_date); 
calender.add(Calendar.DATE, 1); 
calender.add(Calendar.HOUR_OF_DAY, 12); 
//calender.add(Calendar.HOUR_OF_DAY, 14); //temp testing data 
//calender.add(Calendar.MINUTE, 43); 

AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); 
Intent i = new Intent(ctx, AlarmReceiver.class); 
am.set(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), PendingIntent.getBroadcast(ctx, 1, i, PendingIntent.FLAG_UPDATE_CURRENT)); 

然後,在預定的時間,它會觸發接收器,像這樣:

public class AlarmReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     Intent service = new Intent(context, AlarmService.class); 
     context.startService(service); 
    } 
} 

最後,它會調用服務來顯示通知,或者在應用程序處於後臺時將其置於前端。下面是該代碼:

public class AlarmService extends Service { 
    private Context ctx; 
    private MyApp gs; 
    private SharedPreferences prefs; 
    NotificationManager notificationManager; 
    Notification myNotification; 
    private String joinPlanID; 
    private String joinPlanDate; 
    private int period; 

    public AlarmService() { 
    } 

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

    public void checkPlanPeriod(String planID) { 
     if (joinPlanID.equals("1")) 
      period = 15; 
     else if (joinPlanID.equals("2")) 
      period = 30; 
     else if (joinPlanID.equals("3")) 
      period = 45; 
    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     ctx = getApplicationContext(); 
     gs = (MyApp) getApplication(); 
     prefs = PreferenceManager.getDefaultSharedPreferences(ctx); 

     if (prefs.getString("joinPlanID", null) != null) { 
      Date alarmDate = null; 
      joinPlanID = prefs.getString("joinPlanID", null); 
      joinPlanDate = prefs.getString("joinPlanDate", null); 
      checkPlanPeriod(joinPlanID); 

      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
      try { 
       alarmDate = format.parse(joinPlanDate); 
      } catch (ParseException e) { 
       e.printStackTrace(); 
      } 

      GregorianCalendar planCalendar = new GregorianCalendar(); 
      planCalendar.setTime(alarmDate); 
      planCalendar.add(Calendar.DATE, period); 

      Calendar now = Calendar.getInstance(); 
      now.add(Calendar.DATE, 1); 

      Calendar tomorrowAlarm = Calendar.getInstance(); 
      tomorrowAlarm.set(Calendar.YEAR, now.get(Calendar.YEAR)); 
      tomorrowAlarm.set(Calendar.MONTH, now.get(Calendar.MONTH)); 
      tomorrowAlarm.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH)); 
      tomorrowAlarm.set(Calendar.HOUR_OF_DAY, 12); 
      tomorrowAlarm.set(Calendar.MINUTE, 0); 
      tomorrowAlarm.set(Calendar.SECOND, 0); 
      tomorrowAlarm.set(Calendar.MILLISECOND, 0); 

      if (planCalendar.compareTo(tomorrowAlarm) != -1) { 
       //set the next day alarm 
       AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); 
       Intent i = new Intent(ctx, AlarmReceiver.class); 
       am.set(AlarmManager.RTC_WAKEUP, tomorrowAlarm.getTimeInMillis(), PendingIntent.getBroadcast(ctx, 1, i, PendingIntent.FLAG_UPDATE_CURRENT)); 
      } 
     } 

     if (gs.getIsAppStart()) { 
      Intent dialogIntent = new Intent(this, Main.class); 
      dialogIntent.putExtra("is_remind", true); 
      dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      this.startActivity(dialogIntent); 
     } else { 
      NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx) 
      .setSmallIcon(R.drawable.ic_launcher) 
      .setContentTitle(getResources().getString(R.string.notify_title)) 
      .setContentText(getResources().getString(R.string.notify_msg)); 

      Intent toLaunch = new Intent(getApplicationContext(), Main.class); 
      toLaunch.putExtra("is_remind", true); 
      toLaunch.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 
      PendingIntent intentBack = PendingIntent.getActivity(ctx, 0, toLaunch,PendingIntent.FLAG_UPDATE_CURRENT); 

      mBuilder.setContentIntent(intentBack); 
      NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); 

      // Send Notification 
      Notification primaryNotification = mBuilder.build(); 
      mNotificationManager.notify(10001, primaryNotification); 
     } 

    } 
} 

的問題是,如果重置我的設備既不觸發報警,也沒有我的接收方收到任何東西。我如何解決它?

+0

重置手段?重啓 ? – Kedarnath 2014-10-10 09:36:25

+0

是的,該程序只適用於我沒有關閉應用程序/重新啓動。 – user782104 2014-10-10 09:37:45

+0

您是否已經在清單中註冊了BroadCastReceiver和Service?權限設置? – Opiatefuchs 2014-10-10 09:38:28

回答

6

添加一個BootReceiver

public class BootReceiver extends BroadcastReceiver { 

    private static final String BOOT_COMPLETED = 
      "android.intent.action.BOOT_COMPLETED"; 
    private static final String QUICKBOOT_POWERON = 
      "android.intent.action.QUICKBOOT_POWERON"; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     String action = intent.getAction(); 
     if (action.equals(BOOT_COMPLETED) || 
       action.equals(QUICKBOOT_POWERON)) { 
      Intent service = new Intent(context, BootService.class); 
      context.startService(service); 
     } 
    } 

} 

添加一個BootService

public class BootService extends IntentService { 

    public BootService() { 
     super("BootService"); 
    } 

    private void setAlarm() { 
     // Set your alarm here as you do in "1. First I set an alarm in alarm manager" 
    } 

    private void setAlarmsFromDatabase() { 
     // Set your alarms from database here 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     setAlarm(); 
     setAlarmsFromDatabase(); // A nice a approach is to store alarms on a database, you may not need it 
     Intent service = new Intent(this, BootService.class); 
     stopService(service); 
    } 

} 

然後在你的AndroidManifest.xml添加

<receiver android:name=".BootReceiver" 
      android:enabled="true"> 
    <intent-filter> 
     <action android:name="android.intent.action.BOOT_COMPLETED"/> 
     <action android:name="android.intent.action.QUICKBOOT_POWERON" /> 
    </intent-filter> 
</receiver> 
<service android:name=".BootService" 
     android:enabled="true"/> 

,並添加此權限

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

現在,您可以重新啓動設備,並報警將每次將設備設置爲啓動

+0

感謝您添加QUICKBOOT_POWERON – user782104 2014-10-13 01:36:20

2

電話重新啓動後,所有設置的鬧鐘都會被清除。警報意圖工作,你需要創建一個掛起的意圖,並將其設置在警報管理器。您可以使用數據庫存儲警報詳細信息,並在電話啓動時重新創建警報。 (應用程序應該聽取android.intent.action.BOOT_COMPLETED)

+0

如果我再次重新啓動如果報警還沒有觸發會怎樣,它會替換舊的還是重複?謝謝 – user782104 2014-10-10 09:50:15

+1

所有警報在重新啓動時被清除。因此,在重新啓動時創建相同的警報將是解決方案。 – 2014-10-10 10:03:33

0

由於您啓動的服務有設備醒來運行鬧鐘運行onReceive方法的可能性,然後在開始之前回到睡眠狀態該服務通常在從BroadCastReceiver開始服務時,您應該改爲使用處理喚​​醒鎖的WakefulBroadcastReceiver,嘗試一下,看看是否有幫助,即使它不能幫助您應該使用它