2013-01-17 83 views
2

我試圖創建一個提醒應用程序,彈出狀態欄中的提醒。據我所知,Android NotificationManager是用於安排通知的標準工具,但是爲了重新安排通知,需要BootService,因爲安排的事件在啓動時不能存活。Android AlarmManager隨機調度通知?

我已經將一個應用程序拼湊在一起,在應用程序的啓動時間安排一個提醒,並在狀態欄彈出一個通知。如果你點擊通知,它會啓動MainActivity,未來,它將有選擇添加更多的提醒,刪除它們或任何。

我遇到的問題是,提醒第一次正常工作,但似乎是重新安排自己,並出於某種原因在隨機時間再次彈出。我應該啓動另一項活動,而不是安裝BootAlarmService的活動?

更新: 所以我想我發現了logcat的一些線索。顯然該服務正在崩潰並正在重新啓動,正在重新設置通知。任何想法,爲什麼這是?

UPDATE II:代碼改爲工作模型

ActivityManager I No longer want com.example.alarm_boot_test (pid 1428): hidden #16 
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.BootAlarmService in 5000ms 
ActivityManager W Scheduling restart of crashed service com.example.alarm_boot_test/.NotificationAlarmService in 15000ms 
ActivityManager I Start proc com.example.alarm_boot_test for service com.example.alarm_boot_test/.BootAlarmService: pid=2321 uid=10069 gids={} 
     dalvikvm D Debugger has detached; object registry had 1 entries 
     szipinf D Initializing inflate state 
BootAlarmService D oncreate() 
BootAlarmService D alarm set for Thu Jan 17 08:03:00 CST 2013 

MainActivity.java

package com.example.alarm_boot_test; 

import android.app.Activity; 
import android.os.Bundle; 

public class MainActivity extends Activity 
{ 

    @Override 
    protected void onCreate (Bundle savedInstanceState) 
    { 
     super.onCreate (savedInstanceState); 
     setContentView (R.layout.activity_main); 
    } 


} 

BootAlarmService.java

package com.example.alarm_boot_test; 

import java.util.Calendar; 

import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.util.Log; 

public class BootAlarmService extends Service 
{ 
    private final String TAG = this.getClass().getName(); 

    @Override 
    public void onCreate() 
    { 
     Log.d (TAG, "oncreate()"); 
     super.onCreate(); 
    } 


    @Override 
    public int onStartCommand (Intent intent, int flags, int startId) 
    { 
     Log.d (TAG, "alarm_test: BootAlarmService.onStartCommand() Received start id " + startId + ": " + intent); 

     // if intent == null, service has been killed/restarted by system 
     if (intent != null) 
     createNotificationOnBoot(); 
     else 
     Toast.makeText (getBaseContext(), "Intent was null in BootAlarmService.", Toast.LENGTH_LONG).show(); 


     return START_STICKY; 
    } 


    private void createNotificationOnBoot() 
    { 
     Intent inotify = new Intent(this , NotificationAlarmService.class); 
     inotify.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); 
     AlarmManager amgr = (AlarmManager)getSystemService(ALARM_SERVICE); 
     PendingIntent pendingIntent = PendingIntent.getService(this, 0, inotify, 0); 

     // go off two mins from now 
     Calendar calendar = Calendar.getInstance(); 
     calendar.set(Calendar.SECOND, 0); 
     calendar.set(Calendar.MINUTE, calendar.get (Calendar.MINUTE) + 2); 

     amgr.set (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); 


     Log.d (TAG, "alarm set for " + calendar.getTime().toString()); 
    } 


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


} 

BootReceiver.java

package com.example.alarm_boot_test; 

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 

public class BootReceiver extends BroadcastReceiver 
{ 

    @Override 
    public void onReceive (final Context context, final Intent bootintent) 
    { 
     Intent i = new Intent(); 
     i.setAction ("com.example.alarm_boot_test.BootAlarmService"); 
     context.startService (i); 
    } 

} 

NotificationAlarmService.java

package com.example.alarm_boot_test; 

import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.util.Log; 

public class NotificationAlarmService extends Service 
{ 
    private final String TAG = this.getClass().getName(); 


    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 
    } 


    @Override 
    public int onStartCommand (Intent intent, int flags, int startId) 
    { 
     Log.d (TAG, "alarm_test: NotificationAlarmService.onStartCommand()"); 
     if (intent != null) 
      createNotification(); 
     else 
      Toast.makeText (getBaseContext(), "Intent was null in NotificationAlarmService.", Toast.LENGTH_LONG).show(); 

     return super.onStartCommand (intent, flags, startId); 
    } 



    private void createNotification() 
    { 
     NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
     Notification notification = new Notification(android.R.drawable.stat_sys_warning, "Note from AlarmService", System.currentTimeMillis()); 
     Intent i = new Intent(this, ViewReminder.class); 
     PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0); 

     notification.setLatestEventInfo(this, "New Notification", "You have been notified by AlarmService", pendingIntent); 
     notificationManager.notify(10001, notification); 

    } 




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

* activity_main.xml中*

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity" > 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:text="Service started! Reboot!" /> 

</RelativeLayout> 

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.alarm_boot_test" 
    android:versionCode="1" 
    android:versionName="1.0" > 

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

    <uses-sdk 
     android:minSdkVersion="9" 
     android:targetSdkVersion="9" /> 

    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <service android:name="com.example.alarm_boot_test.BootAlarmService" > 
      <intent-filter> 
       <action android:name="com.example.alarm_boot_test.BootAlarmService" > 
       </action> 
      </intent-filter> 
     </service> 

     <receiver android:name="com.example.alarm_boot_test.BootReceiver" > 
      <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED" > 
       </action> 
      </intent-filter> 
     </receiver> 

     <service android:name="com.example.alarm_boot_test.NotificationAlarmService" > 
     </service> 

     <activity 
      android:name="com.example.alarm_boot_test.MainActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

回答

1

爲了幫助別人,我想我需要在BootStartCommand()方法和NotificationAlarmService.java中的onStartCommand()方法中檢查傳入的Intent是否爲NULL。只有幾天才進行測試,但是如果系統殺死/重新啓動服務,它看起來像Intent是NULL。僅僅通過測試就可以讓我在引導時啓動服務(當傳遞的Intent不爲空時)創建通知。

+0

這很好,你分享了這個,但我有一個不同的問題,我想我的應用程序在一天內隨機通知我幾次,什麼是正確的方法來做到這一點? – Recomer