我正在创建一个用于显示预定通知的安卓库。例如,在下周下午4点发出通知。
我需要有一个尚未显示的预定通知的注册,所以如果我愿意,我可以取消它们。因此,每当我安排新通知时,我都会将其保存到 SharedPreferences 中。然后我开始一个 BroadcastReceiver ,当时间到来时将会超时。此时,接收方在SharedPreferences中注销通知。
当应用程序未运行时,该工作正常。 但是当应用程序运行时,接收方所做的更改不会在正在运行的应用程序中受到影响,因此我从未注册过该通知已被显示。
以下是我的示例活动代码:
public class MainActivity extends AppCompatActivity {
NotificationJSONStorage storage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
storage = new NotificationJSONStorage(context,
"notifications");
// show notification in the next 10 seconds
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
sendNotification(getApplicationContext(), calendar.getTimeInMillis(), ...);
}
public int sendNotification(Context context, long dateTriggerMilliseconds, ...) {
// create a unique notification id
int id = UUID.randomUUID().hashCode();
// Create an explicit intent for an Activity in your app
Intent intent = new Intent(context, DelayedNotificationReceiver.class);
// pass data to the receiver
intent.putExtra("notification_id", id);
...
// Set the Activity to start in a new, empty task
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, dateTriggerMilliseconds, pendingIntent);
// adds the notification id to shared preferences
try {
storage.addScheduledNotification(id);
} catch (JSONException e) {
e.printStackTrace();
}
return id;
}
}
这是我的BroadcastReceiver代码:
public class DelayedNotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// receive custom data from intent
int id = intent.getIntExtra("notification_id", -1);
...
try {
Intent launchIntent = new Intent(context, Class.forName("my.launcher.class"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, id, launchIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
...;
// show the notification
NotificationManagerCompat.from(context)
.notify(id, builder.build());
// removes the notification id from shared preferences
NotificationJSONStorage storage = new NotificationJSONStorage(context,
"notifications");
storage.removeScheduledNotification(id);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
这是一个用于保存和读取SharedPreferences的通知数据的类:
public class NotificationJSONStorage {
private final String SCHEDULED_NOTIFICATIONS_KEY = "scheduled_notifications";
private Context context;
private JSONObject jsonRoot;
private String preferencesNamespace;
public NotificationJSONStorage(Context context, String preferencesNamespace) {
this.context = context;
this.preferencesNamespace = preferencesNamespace;
}
public void addScheduledNotification(int id) throws JSONException {
JSONObject root = getJsonRoot();
// do stuff with json root
...
// persist it
save(SCHEDULED_NOTIFICATIONS_KEY);
}
public boolean removeScheduledNotification(int id) throws JSONException {
JSONObject root = getJsonRoot();
// do stuff with json root
...
// persist it
save(SCHEDULED_NOTIFICATIONS_KEY);
return result;
}
public JSONObject load(String key) throws JSONException {
SharedPreferences preferences = context.getSharedPreferences(preferencesNamespace,
Context.MODE_PRIVATE);
String raw = preferences.getString(key, null);
JSONObject root = null;
if (raw != null && !raw.isEmpty()) {
root = new JSONObject(raw);
} else {
root = new JSONObject();
}
return root;
}
public void save(String key) {
String out = getJsonRoot().toString();
// write to shared preferences
SharedPreferences preferences = context.getSharedPreferences(preferencesNamespace,
Context.MODE_PRIVATE);
preferences.edit()
.putString(key, out)
.apply();
}
public JSONObject getJsonRoot() {
if (jsonRoot == null) {
try {
jsonRoot = load(SCHEDULED_NOTIFICATIONS_KEY);
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonRoot;
}
}
这是主要活动的Android清单:
<?xml version="1.0" encoding="utf-8"?>
<application
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=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
这是通知模块的Android清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.l33tbit.androidnotifications">
<uses-permission android:name="android.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<application>
<receiver android:name=".DelayedNotificationReceiver"/>
</application>
有什么想法吗?
答案 0 :(得分:0)
我终于解决了这个问题。问题是当接收者改变状态时,NotificationJSONStorage类中的 jsonRoot 引用没有得到更新,因为它只被加载了一次。
我所做的是向SharedPreferences添加一个侦听器,强制在发生任何更改时重新加载json数据。
public class NotificationJSONStorage implements SharedPreferences.OnSharedPreferenceChangeListener {
private final String SCHEDULED_NOTIFICATIONS_KEY = "scheduled_notifications";
private Context context;
private JSONObject jsonRoot;
private String preferencesNamespace;
private boolean rootDirty = true;
public NotificationJSONStorage(Context context, String preferencesNamespace) {
this.context = context;
this.preferencesNamespace = preferencesNamespace;
context.getSharedPreferences(preferencesNamespace, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
}
public void onDestroy() {
context.getSharedPreferences(preferencesNamespace, Context.MODE_PRIVATE)
.unregisterOnSharedPreferenceChangeListener(this);
}
public void addScheduledNotification(int id) throws JSONException {
JSONObject root = getJsonRoot();
// do stuff with json root
...
// persist it
save(SCHEDULED_NOTIFICATIONS_KEY);
}
public boolean removeScheduledNotification(int id) throws JSONException {
JSONObject root = getJsonRoot();
// do stuff with json root
...
// persist it
save(SCHEDULED_NOTIFICATIONS_KEY);
return result;
}
public JSONObject load(String key) throws JSONException {
SharedPreferences preferences = context.getSharedPreferences(preferencesNamespace,
Context.MODE_PRIVATE);
String raw = preferences.getString(key, null);
JSONObject root = null;
if (raw != null && !raw.isEmpty()) {
root = new JSONObject(raw);
} else {
root = new JSONObject();
}
return root;
}
public void save(String key) {
String out = getJsonRoot().toString();
// write to shared preferences
SharedPreferences preferences = context.getSharedPreferences(preferencesNamespace,
Context.MODE_PRIVATE);
preferences.edit()
.putString(key, out)
.apply();
}
public JSONObject getJsonRoot() {
// also check if the data is dirty so it should be reloaded
if (jsonRoot == null || rootDirty) {
try {
jsonRoot = load(SCHEDULED_NOTIFICATIONS_KEY);
rootDirty = false;
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonRoot;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(SCHEDULED_NOTIFICATIONS_KEY)) {
rootDirty = true;
}
}
}