Android的AlarmManager随机安排的通知? [英] Android AlarmManager Randomly Scheduling Notifications?

查看:232
本文介绍了Android的AlarmManager随机安排的通知?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建弹出在状态栏中提醒的提醒应用程序。据我了解,在Android NotificationManager是使用但需要以重新安排通知的BootService安排通知如期事件不会在引导生存的标准工具。

我拼凑低于该调度单提醒在启动时的应用程序,并弹出后在状态栏中的通知。如果您单击该通知,它将启动MainActivity其中,在未来,将有选择添加更多的提醒,删除它们,或什么的。

时遇到的问题是,提醒工作正常首次但是它似乎被重新调度本身和在随机时间由于某种原因重新弹出。我应该启动另一个活动,而不是将安装BootAlarmService的人?

更新:
所以,我想我发现了一些线索与logcat中。显然,服务崩溃,并正在重新启动是重置的通知。任何想法这是为什么?

更新二: code改为工作模型

  ActivityManager我不再想com.example.alarm_boot_test(PID 1428):隐藏#16
在5000毫秒坠毁服务com.example.alarm_boot_test / .BootAlarmService的ActivityManagerW¯¯调度重启
在15000ms坠毁服务com.example.alarm_boot_test / .NotificationAlarmService的ActivityManagerW¯¯调度重启
ActivityManager我开始PROC com.example.alarm_boot_test服务com.example.alarm_boot_test / .BootAlarmService:PID = 2321 UID = 10069导报= {}
       dalvikvmÐ调试器分离;对象注册了1项
        szipinfÐ初始化状态膨胀
BootAlarmServiceð的OnCreate()
BootAlarmServiceð报警周四一月17集CST 8时03分00秒2013

MainActivity.java

 包com.example.alarm_boot_test;进口android.app.Activity;
进口android.os.Bundle;公共类MainActivity扩展活动
{    @覆盖
    保护无效的onCreate(捆绑savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
    }
}

BootAlarmService.java

 包com.example.alarm_boot_test;进口的java.util.Calendar;进口android.app.AlarmManager;
进口android.app.PendingIntent;
进口android.app.Service;
进口android.content.Intent;
进口android.os.IBinder;
进口android.util.Log;公共类BootAlarmService延伸服务
{
    私人最终字符串标记= this.getClass().getName();    @覆盖
    公共无效的onCreate()
    {
        Log.d(TAG的OnCreate());
        super.onCreate();
    }
   @覆盖
   公众诠释onStartCommand(意向意图,诠释旗帜,INT startId)
   {
       Log.d(TAG,alarm_test:BootAlarmService.onStartCommand()开始收到的ID为+ startId +:+意向);       //如果意图== NULL,服务已被杀害/由系统重新启动
       如果(意向!= NULL)
        createNotificationOnBoot();
       其他
        Toast.makeText(getBaseContext(),。意图是BootAlarmService空,Toast.LENGTH_LONG).show();
       返回START_STICKY;
    }
    私人无效createNotificationOnBoot()
    {
        意向书的inotify =新意图(这一点,NotificationAlarmService.class);
        inotify.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        AlarmManager AMGR =(AlarmManager)getSystemService(ALARM_SERVICE);
        的PendingIntent的PendingIntent = PendingIntent.getService(在此,0,inotify的,0);        // 2分钟从现在熄灭
        台历挂历= 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,+ calendar.getTime()的ToString()报警组);
    }
    @覆盖
    公众的IBinder onBind(意向意图)
    {
        返回null;
    }
}

BootReceiver.java

 包com.example.alarm_boot_test;进口android.content.BroadcastReceiver;
进口android.content.Context;
进口android.content.Intent;公共类BootReceiver扩展广播接收器
{    @覆盖
    公共无效的onReceive(最终上下文的背景下,最终的意图bootintent)
    {
        意图I =新意图();
        i.setAction(com.example.alarm_boot_test.BootAlarmService);
        context.startService(ⅰ);
    }}

NotificationAlarmService.java

 包com.example.alarm_boot_test;进口android.app.Notification;
进口android.app.NotificationManager;
进口android.app.PendingIntent;
进口android.app.Service;
进口android.content.Intent;
进口android.os.IBinder;
进口android.util.Log;公共类NotificationAlarmService延伸服务
{
    私人最终字符串标记= this.getClass()的getName()。
    @覆盖
    公共无效的onCreate()
    {
        super.onCreate();
    }
    @覆盖
    公众诠释onStartCommand(意向意图,诠释旗帜,INT startId)
    {
       Log.d(TAGalarm_test:NotificationAlarmService.onStartCommand());
       如果(意向!= NULL)
          createNotification();
       其他
          Toast.makeText(getBaseContext(),。意图是NotificationAlarmService空,Toast.LENGTH_LONG).show();       返回super.onStartCommand(意向,旗帜,startId);
     }    私人无效createNotification()
    {
      NotificationManager notificationManager =(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
      通知通知=新的通知(android.R.drawable.stat_sys_warning,注意从AlarmService,System.currentTimeMillis的());
      意图I =新意图(这一点,ViewReminder.class);
      的PendingIntent的PendingIntent = PendingIntent.getActivity(在此,0,I,0);      notification.setLatestEventInfo(这一点,新通知,你已经被AlarmService通知的PendingIntent);
      notificationManager.notify(10001,通知);   }
    @覆盖
   公众的IBinder onBind(意向意图)
   {
       返回null;
   }
}

* activity_main.xml中*

 <的RelativeLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    工具:上下文=MainActivity。>    <的TextView
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_centerHorizo​​ntal =真
        机器人:layout_centerVertical =真
        机器人:文字=服务开始重新启动! />< / RelativeLayout的>

AndroidManifest.xml中

 <?XML版本=1.0编码=UTF-8&GT?;
<清单的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    包=com.example.alarm_boot_test
    安卓版code =1
    机器人:=的versionName1.0>    <使用许可权的android:NAME =android.permission.RECEIVE_BOOT_COMPLETED/>    <用途-SDK
        安卓的minSdkVersion =9
        机器人:targetSdkVersion =9/>    <应用
        机器人:allowBackup =真
        机器人:图标=@绘制/ ic_launcher
        机器人:标签=@字符串/ APP_NAME
        机器人:主题=@风格/ AppTheme>
        <服务机器人:名字=com.example.alarm_boot_test.BootAlarmService>
            &所述;意图滤光器>
                <作用机器人:名字=com.example.alarm_boot_test.BootAlarmService>
                < /作用>
            &所述; /意图滤光器>
        < /服务>        <接收机器人:名字=com.example.alarm_boot_test.BootReceiver>
            &所述;意图滤光器>
                <作用机器人:名字=android.intent.action.BOOT_COMPLETED>
                < /作用>
            &所述; /意图滤光器>
        < /接收器>        <服务机器人:名字=com.example.alarm_boot_test.NotificationAlarmService>
        < /服务>        <活动
            机器人:名字=com.example.alarm_boot_test.MainActivity
            机器人:标签=@字符串/ APP_NAME>
            &所述;意图滤光器>
                <作用机器人:名字=android.intent.action.MAIN/>                <类机器人:名字=android.intent.category.LAUNCHER/>
            &所述; /意图滤光器>
        < /活性GT;
    < /用途>< /清单>


解决方案

在情况下,它可以帮助其他人,我想我需要检查NULL传递的意图在onStartCommand()方法,无论是在BootAlarmService.java以及NotificationAlarmService的.java。只有在测试这几天,但它看起来像意图是NULL,如果系统杀死/重新启动该服务。只是这个测试使我创造只有当服务在系统启动时启动的通知(当传递意图不是为null)。

I'm trying to create a reminder application that pops up a reminder in the status bar. As I understand, the Android NotificationManager is the standard tool to use to schedule notifications however a BootService is needed in order to re-schedule notifications as scheduled events do not survive across boots.

I've pieced together an application below which schedules a single reminder at boot time, and pops up a notification in the status bar. If you click the notification, it launches MainActivity which, in the future, will have options to add more reminders, delete them, or whatever.

The problem I'm having is that the reminder works correctly the first time however it seems to be re-scheduling itself and popping up again at random times for some reason. Should I be launching another activity rather than the one which installs the BootAlarmService?

UPDATE: So I think I found some clues with logcat. Apparently the Service is crashing and being restarted which is resetting the Notification. Any ideas why this is?

UPDATE II : code changed to working model

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>

解决方案

In case it helps someone else, I think I needed to check the passed Intent for NULL in the onStartCommand() method both in BootAlarmService.java as well as NotificationAlarmService.java. Only been testing it a couple days but it looks like the Intent is NULL if the system kills/restarts the service. Simply testing for this allowed me to create the notification only when the service is started at Boot-time (when the passed Intent is NOT null).

这篇关于Android的AlarmManager随机安排的通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆