我的应用程序应在指定的时间发送通知。 我编写了一个使用AlarmManager的服务,该服务是一个接收器,如果您关闭该应用程序,它将重新启动它。服务重新启动(从日志中可以看到),但是在应用程序关闭时,AlarmManager不起作用(接收者没有收到来自它的意图)。我还尝试在服务代码中注册接收器-仍然无法正常工作( AlarmService-前台服务。 AlarmSetter-设置警报的类。 AlarmReceiver-接收方发送通知(已记录:接收到意图)
清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="net.ozero.drugsreminder"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
>
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.AddPrescActivity"
android:label="@string/label_add_presc_activity"
android:parentActivityName=".activities.MainActivity"
android:theme="@style/ActionBarTheme"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activities.AddDrugActivity"
android:label="@string/label_add_drug_activity"
android:parentActivityName=".activities.AddPrescActivity"
android:theme="@style/ActionBarTheme"
android:windowSoftInputMode="stateVisible">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".activities.AlarmActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".services.AlarmService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="net.ozero.drugsreminder.services.AlarmService.MarkEvent" />
<action android:name="net.ozero.drugsreminder.services.AlarmService.SetLater" />
</intent-filter>
</service>
<receiver
android:name=".services.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="net.ozero.drugsreminder.services.AlarmReceiver" />
</intent-filter>
</receiver>
<receiver
android:name=".services.RestartAlarmServiceReceiver"
android:enabled="true"
android:exported="true">
</receiver>
<receiver
android:name=".services.BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
</application>
</manifest>
AlarmService:
package net.ozero.drugsreminder.services;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import net.ozero.drugsreminder.alarm.AlarmSetter;
import net.ozero.drugsreminder.database.DBHelper;
import net.ozero.drugsreminder.datastructure.Event;
import net.ozero.drugsreminder.formatters.AlarmMessageBuilder;
import java.util.List;
import static net.ozero.drugsreminder.App.*;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
/**TODO alarm repeating (bug) */
public class AlarmService extends Service {
public AlarmService() {
}
public DBHelper mDBHelper;
public AlarmReceiver mAlarmReceiver;
public AlarmManager mAlarmManager;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AlarmService:", "on start");
// mAlarmReceiver = new AlarmReceiver();
mDBHelper = new DBHelper(this);
//set event is done
if (isMarkAction(intent)) {
markEvent(intent);
}
//set event to alarm later
if (isSetLaterAction(intent)) {
setEventLater(intent);
}
setAlarms();
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.i("AlarmService:", "on removed");
sendBroadcast(new Intent(this, RestartAlarmServiceReceiver.class));
Log.i(getClass().getName(), "OnTaskRemoves: broadcast sent");
super.onTaskRemoved(rootIntent);
}
private boolean isMarkAction(Intent intent) {
return (
intent != null
&& intent.getAction() != null
&& intent.getAction().equals(ACTION_MARK_EVENT)
);
}
private boolean isSetLaterAction(Intent intent) {
return (
intent != null
&& intent.getAction() != null
&& intent.getAction().equals(ACTION_SET_LATER)
);
}
private void setEventLater(Intent intent) {
int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
mDBHelper.setEventLater(id, ALARM_INTERVAL);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.cancel(id);
Log.i("AlarmService:", "event time set later : " + id);
}
private void markEvent(Intent intent) {
int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
mDBHelper.markEvent(id);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.cancel(id);
Log.i("AlarmService:", "event is marked, id : " + id);
}
private void setAlarms() {
mDBHelper = new DBHelper(this);
List<Event> events = mDBHelper.getActualEvents();
Log.i("AlarmService:setAlarms:", "actual (not marked) events size:" + String.valueOf(events.size()));
AlarmSetter alarmSetter = new AlarmSetter(this);
AlarmMessageBuilder alarmMessageBuilder = new AlarmMessageBuilder(mDBHelper);
for (Event event : events) {
long timeMillis = event.getReceptionDateTime().getTime();
String message = alarmMessageBuilder.getMessage(event);
int id = event.getId();
alarmSetter.setAlarm(timeMillis, message, id);
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(getClass().getName(), "onDestroy");
}
}
AlarmSetter:
package net.ozero.drugsreminder.alarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import net.ozero.drugsreminder.services.AlarmReceiver;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;
public class AlarmSetter {
//one minute timeout
public static final long DEFAULT_ALARM_TIMEOUT = 60*1000L;
private Context mContext;
private AlarmManager mAlarmManager;
public AlarmSetter(Context applicationContext) {
mContext = applicationContext;
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Log.i("AlarmSetter:", "alarm manager:" + mAlarmManager);
}
//main method
public void setAlarm(long timeMillis, String message, int id) {
//creating intent for alarm message
Intent intent = new Intent("net.ozero.drugsreminder.services.AlarmReceiver");
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.putExtra(EXTRA_ALARM_MESSAGE, message);
intent.putExtra(EXTRA_ALARM_ID, id);
//creating pending intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext.getApplicationContext(), id, intent, 0);
//setting alarm
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
} else {
mAlarmManager.set(
AlarmManager.RTC_WAKEUP,
timeMillis,
pendingIntent
);
}
Log.i("AlarmSetter:" , "alarm set");
}
}
AlarmReceiver:
package net.ozero.drugsreminder.services;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import net.ozero.drugsreminder.alarm.NotificationSetter;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("AlarmReceiver:", "notification received");
String message = intent.getStringExtra(EXTRA_ALARM_MESSAGE);
int id = intent.getIntExtra(EXTRA_ALARM_ID, 1);
NotificationSetter notificationSetter = new NotificationSetter(context);
notificationSetter.setNotification(message, id);
}
}
答案 0 :(得分:0)
您必须将您的服务作为真正的前台服务来运行,这样即使您的应用已完成,他也将幸免于难。
这是来自http://www.vogella.com/tutorials/AndroidServices/article.html的一个简单示例:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);