2014-01-23 32 views
1

我想在我的Android应用中实现“每日提醒”功能,应该在设定的时间每天触发一次。我尝试的第一个实现是为大多数人工作的,但是一些用户子集(包括至少一个在三星的Android 4.3上运行的人)报告说,警报以比它应该更频繁的方式触发,例如,每10分钟一次,每次他们打开应用程序,一般都很烦人。Android的每日闹铃发射太频繁或只有一次

这里的报警的启用:

Intent myIntent = new Intent(ctx, AlarmReceiver.class); 
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, myIntent,0); 

AlarmManager alarmManager = (AlarmManager)ctx.getSystemService(Service.ALARM_SERVICE); 
alarmManager.cancel(pendingIntent); 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, sched, 
       AlarmManager.INTERVAL_DAY, 
       pendingIntent); 

再有就是这个AlarmReceiver类:

public class AlarmReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     // TODO Auto-generated method stub 

      Intent service1 = new Intent(context, AlarmService.class); 
      context.startService(service1); 
    } 

} 

这是登记在AndroidManifest接收器:<receiver android:name=".AlarmReceiver"/>

最后还有的AlarmService ,它看起来像这样:

public class AlarmService extends Service { 

    @Override 
    public IBinder onBind(Intent arg0) { 
     // TODO Auto-generated method stub 
     return null; 
    } 


    @Override 
    public void onCreate() 
    { 
     // TODO Auto-generated method stub 
     super.onCreate(); 
    } 

    @SuppressWarnings("static-access") 
    @Override 
    public void onStart(Intent intent, int startId) 
    { 
     super.onStart(intent, startId); 

     Log.v("pm", "about to notify"); 

     Intent intent1 = new Intent(this.getApplicationContext(), MainActivity.class); 
     intent1.setAction(Intent.ACTION_MAIN); 
     intent1.addCategory(Intent.CATEGORY_LAUNCHER); 
     //intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP); 

     PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(),0, intent1,PendingIntent.FLAG_UPDATE_CURRENT); 

     Notification notification = new Notification.Builder(this.getApplicationContext()) 
             .setContentTitle("My App") 
             .setContentText("Don't forget that thing!") 
             .setSmallIcon(R.drawable.ic_launcher) 
             .setWhen(System.currentTimeMillis()) 
             .setContentIntent(pendingNotificationIntent) 
             .getNotification();      

     notification.flags |= Notification.FLAG_AUTO_CANCEL; 
     notification.defaults |= Notification.DEFAULT_SOUND; 
     notification.defaults |= Notification.DEFAULT_VIBRATE; 

     NotificationManager nManager = 
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
     nManager.notify(0, notification); 
    } 

    @Override 
    public void onDestroy() 
    { 
     // TODO Auto-generated method stub 
     super.onDestroy(); 
    } 
} 

但是,正如我所说,人们报告说这每十分钟就会发射一次!所以我尝试将AlarmService更改为一个较不被弃用的实现,但在这个过程中,现在人们说它只会触发一次,然后再也不会!

我换成onStart这个:

@Override 
public int onStartCommand(Intent intent, int flags, int startId) 
{ 
     Log.v("pm", "about to notify"); 

    if (intent != null) { 
     Intent intent1 = new Intent(this.getApplicationContext(), MainActivity.class); 
     intent1.setAction(Intent.ACTION_MAIN); 
     intent1.addCategory(Intent.CATEGORY_LAUNCHER); 
     //intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP); 

     PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(),0, intent1,PendingIntent.FLAG_UPDATE_CURRENT); 

     Notification notification = new Notification.Builder(this.getApplicationContext()) 
             .setContentTitle("My App") 
             .setContentText("Don't forget that thing!") 
             .setSmallIcon(R.drawable.ic_launcher) 
             .setWhen(System.currentTimeMillis()) 
             .setContentIntent(pendingNotificationIntent) 
             .getNotification();      

     notification.flags |= Notification.FLAG_AUTO_CANCEL; 
     notification.defaults |= Notification.DEFAULT_SOUND; 
     notification.defaults |= Notification.DEFAULT_VIBRATE; 

     NotificationManager nManager = 
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
     nManager.notify(0, notification); 
    } else { 
     Log.v("pm", "Null Intent"); 
    } 

    return START_STICKY; 
} 

既然不能复制我的设备原来的问题,这是一个有点难以测试!我的两个理论是:

  1. 的问题在于AlarmReceiver,喜欢它应该不会是启动一个全新的服务,但做一些与现有的服务
  2. 我不应该去在排除空intent值我onStartCommand功能

我只是有点紧张,尝试2号以防万一它导致人们的设备再次惹恼他们!

+0

称为如果你能等待,这几天我米工作在一个双定时器(1个闹钟是每月和1个镜头,另一个是每天在固定的时间和重复)。问题是,我目前正在关闭工作,并在几个小时之前不会回家......但我有一个接近工作的解决方案(只是它不能在重新启动后继续工作 - 仍在工作)。 –

+1

我越来越想知道为什么我的AlarmReceiver创建服务,而不是直接显示通知... – andygeers

回答

6

这里的报警器是如何启用

注意,这将是不准确的在Android 4.4或以上版本,即使您正在使用setRepeating(),一旦你提高你的android:targetSdkVersion到19或更高。

再有就是这个AlarmReceiver类

这不会是一个_WAKEUP风格报警可靠。设备在startService()呼叫和您的服务实际上有机会做某事之间入睡是非常有可能的。如果您要使用代理到服务模式,请为use WakefulBroadcastReceivermy WakefulIntentService代表_WAKEUP-样式警报。

但在这个过程中,现在人们都说它每天只发一次!

既然这是你想要的,我会认为这是一件好事。

我取代在onStart这个:

我不知道为什么你使用的是Service代替IntentService。无论如何,请在onStartCommand()方法的底部拨打stopSelf(),这样服务就会消失。这项服务完成后没有理由继续运行。另外,用START_NOT_STICKY代替START_STICKY

而且,如果这是你想要的服务做的工作,你可以放弃完全的服务和移动你的胆量onStartCommand()进入BroadcastReceiveronReceive()

当工作花费太长的时间来冒险捆绑主应用程序线程(例如,> 1ms)时,会使用委托工作从接收方到服务的模式...但您的服务需要后台线程,你的缺乏。由于我期望您的代码在执行时间内小于1毫秒,因此您可以在onReceive()中执行此操作并简化您的应用程序,您将不再需要单独的Service或我之前提到的任何Wakeful*

的问题在于AlarmReceiver,喜欢它应该不会首发了全新的服务,但这样做与现有的服务

东西如果只运行每天一次,也最好不要是“现有服务”。您不需要有一个正在运行的进程,捆绑系统RAM,只需等待时钟打勾即可。

我不应该打扰我onStartCommand功能不包括空意图值

你会得到一个nullIntent如果:

  • 服务完成onStartCommand()为之前,您的进程被终止拨打startService()

  • 您的服务已成功运行之前onStartCommand()并返回START_STICKY

我越来越想知道为什么我AlarmReceiver创建一个服务,而不仅仅是直接显示该通知。

同意。如果您计划进行更多的工作,涉及磁盘或网络I/O,则然后使用IntentService(后台线程,服务自动停止)。否则,我只是把它放在onReceive()中,并称它为好。

+0

非常感谢。我在阅读完你的回答后意识到,我完全错误地输入了新的问题 - 它每天都没有发射一次(这就是我想要的,就像你说的那样),它只是一次发射完全停止。它不会再发生。但即便如此,我认为放弃这项服务并将通知转移到AlarmReceiver中仍然可以解决问题。 – andygeers

+0

@andygeers:另外请注意,在某些设备上,特别是某些SONY Xperia机型,可以禁用'_WAKEUP'报警(“STAMINA模式”)并将其转换为非'_WAKEUP'报警。请参阅http://commonsware.com/blog/2013/03/08/warning-xperia-z-stamina-alarmmanager.html和http://commonsware.com/blog/2013/03/11/more-xperia-alarmmanager .html – CommonsWare

+0

将通知直接放在alaemreceiver中似乎很好地诀窍 – andygeers

0

我只是想为所有遇到AlarmManager和Android 4问题的人添加。4+,这是真正的重要您添加stopSelf();,像@CommonsWave已经说了,到内服务您的onStartCommand()的底部,这是从广播接收器