应用程序关闭时广播接收器

时间:2014-10-20 20:18:07

标签: android android-activity android-broadcast android-alarms

我想制作一个即使应用程序关闭也能运行的闹钟, 当应用程序未关闭时,一切正常 但是当触发时间并关闭应用程序时,应用程序崩溃的时刻就会消失。 我尝试了一些解决方案,但他们没有帮助。

这是我的代码:

public class MainActivity extends Activity {

//used for register alarm manager
PendingIntent pendingIntent;
//used to store running alarmmanager instance
AlarmManager alarmManager;
//Callback function for Alarmmanager event
BroadcastReceiver mReceiver;

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

    //Register AlarmManager Broadcast receive.
    RegisterAlarmBroadcast();

    tp = (TimePicker)findViewById(R.id.timePicker1);
    tp.setIs24HourView(true);

    Calendar cal=Calendar.getInstance(); 
    tp.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY));
    tp.setCurrentMinute(cal.get(Calendar.MINUTE) );

}

public void onClickSetAlarm(View v)
{
    //Get the current time and set alarm after 10 seconds from current time
    // so here we get   
    Calendar time = Calendar.getInstance();
    time.set(Calendar.HOUR_OF_DAY, tp.getCurrentHour());
    time.set(Calendar.MINUTE, tp.getCurrentMinute());
    time.set(Calendar.SECOND, 0);

    alarmManager.set( AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent);
    tp.setEnabled(false);
//  alarmManager.set( AlarmManager.RTC_WAKEUP, 
//          System.currentTimeMillis()  + Integer.parseInt(time.getText().toString() ) * 1000 , pendingIntent );
}

private void RegisterAlarmBroadcast()
{
    //  Log.i("Alarm Example:RegisterAlarmBroadcast()", "Going to register Intent.RegisterAlramBroadcast");

    //This is the call back function(BroadcastReceiver) which will be call when your 
    //alarm time will reached.
    mReceiver = new BroadcastReceiver()
    {
        private static final String TAG = "Alarm Example Receiver";
        @Override
        public void onReceive(Context context, Intent intent)
        {
            //Log.i(TAG,"BroadcastReceiver::OnReceive() >>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            Toast.makeText(context, "Congrats!. Your Alarm time has been reached", Toast.LENGTH_LONG).show();
            tp.setEnabled(true);

             // define sound URI, the sound to be played when there's a notification
            Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

            // intent triggered, you can add other intent for other actions

            PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 0, new Intent("MY_ALARM_NOTIFICATION").setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);

            // this is it, we'll build the notification!
            // in the addAction method, if you don't want any icon, just set the first param to 0
            Notification mNotification = new Notification.Builder(MainActivity.this)

                .setContentTitle("New Post!")
                .setContentText("Here's an awesome update for you!")
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentIntent(pIntent)
                .setSound(soundUri)

              //  .addAction(R.drawable.ninja, "View", pIntent)
                .addAction(0, "Remind", pIntent)
                .build();

            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

            // If you want to hide the notification after it was selected, do the code below
            // myNotification.flags |= Notification.FLAG_AUTO_CANCEL;

            notificationManager.notify(0, mNotification);
        }
    };

    // register the alarm broadcast here
    registerReceiver(mReceiver, new IntentFilter("MY_ALARM_NOTIFICATION") );
    pendingIntent = PendingIntent.getBroadcast( this, 123456789, new Intent("MY_ALARM_NOTIFICATION").setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),0 );
    alarmManager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
   }
}
private void UnregisterAlarmBroadcast()
{
    alarmManager.cancel(pendingIntent); 
    getBaseContext().unregisterReceiver(mReceiver);
}
 @Override
protected void onDestroy() {
    unregisterReceiver(mReceiver);
    super.onDestroy();
  } 
}

任何形式的帮助都将受到赞赏。

这是我的manifest.xml:

<receiver android:name=".MainActivity" >

         <intent-filter>
            <action android:name="MY_ALARM_NOTIFICATION" />
        </intent-filter>

    </receiver>

2 个答案:

答案 0 :(得分:2)

如果没有看到堆栈跟踪我会猜测AlarmManager正在尝试发送警报,但由于您的应用已被杀死且您注册的Receiver也已被杀死,因此在NullPointerException中的某个地方AlarmManager。根据设计,当您知道Activity被导航离开时(例如onStop()),您必须取消注册/删除警报。如果您希望在应用程序不可见和/或关闭后使用闹钟,那么

  1. 您需要在AndroidManifest.xml中注册接收者。在应用程序导航完毕后,应用程序中以编程方式注册的接收器不应该存在 - 并且如果用户退出应用程序,将随应用程序一起销毁。

  2. 您可能还想在接收器中注册BOOT_COMPLETED。当设备重新启动时,所有警报都丢失,因此每当设备重新启动时,您都需要重新设置警报(检查SharedPreferences标志以查看是否应该设置一个警报)。

答案 1 :(得分:2)

您已在清单中将Activity定义为<receiver>。那不行。

你在这里遇到了几个问题。

  1. 您的BroadcastReceiver必须在包含<receiver>标记的清单中声明。这意味着您用作BroadcastReceiver的班级必须是公开的。
  2. 在您的代码中,您已将BroadcastReceiver声明为匿名类。一般情况下,这可以使用,但如果需要从应用程序外部的组件调用BroadcastReceiver,则无法运行。 AlarmMnager在您的应用之外运行(实际上它甚至会在您的应用未运行时触发警报),因此您的BroadcastReceiver必须定义为扩展BroadcastReceiver的公共类。
  3. 您正在呼叫PendingIntent.getActivity()。如果您想开始BroadcastReceiver,则需要拨打PendingIntent.getBroadcast()
  4. 在您的onReceive()方法中,在应用未运行时触发警报的情况下,您正在使用null的成员变量。由于即使您的应用未运行,AlarmManager也可以触发警报,因此在调用onReceive()时,您不能指望设置任何成员变量
  5. 我建议您查看一些如何执行此操作的示例。有很多可用的。

相关问题