Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 当主活动正在运行时,SharedReferences未保存在BroadcastReceiver中_Android_Android Service_Sharedpreferences_Android Notifications - Fatal编程技术网

Android 当主活动正在运行时,SharedReferences未保存在BroadcastReceiver中

Android 当主活动正在运行时,SharedReferences未保存在BroadcastReceiver中,android,android-service,sharedpreferences,android-notifications,Android,Android Service,Sharedpreferences,Android Notifications,我正在制作一个android库,用于显示预定通知。例如,在下周下午4点发出通知 我需要有一个尚未显示的预定通知的登记簿,以便我可以在需要时取消它们。因此,每当我安排新通知时,我都会将其保存到SharedReferences中。然后,我启动一个广播接收器,该接收器将在时间到达时被删除。此时,接收方在SharedReferences中注销通知 当应用程序未运行时,该操作正常但当应用程序运行时,接收者所做的更改不会在运行中的应用程序中受到影响,因此我从未注册通知已显示。 以下是我的示例活动代码: pu

我正在制作一个android库,用于显示预定通知。例如,在下周下午4点发出通知

我需要有一个尚未显示的预定通知的登记簿,以便我可以在需要时取消它们。因此,每当我安排新通知时,我都会将其保存到SharedReferences中。然后,我启动一个广播接收器,该接收器将在时间到达时被删除。此时,接收方在SharedReferences中注销通知

当应用程序未运行时,该操作正常但当应用程序运行时,接收者所做的更改不会在运行中的应用程序中受到影响,因此我从未注册通知已显示。

以下是我的示例活动代码:

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;
}
}

这是我的广播接收机代码:

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();
    }
}
}

这是一个设计用于从SharedReference保存和读取通知数据的类:

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"?>


这是通知模块的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>


有什么想法吗?

我终于解决了这个问题。问题是NotificationJSONStorage类中的jsonRoot引用在接收方更改状态时没有得到更新,因为它只加载了一次

我所做的是在SharedReferences中添加一个监听器,在发生任何更改时强制重新加载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;
    }
}

}

“我从未注册过已显示通知”。我在示例中没有看到任何侦听共享引用或通知的代码?未能看到更改的代码在哪里?广播接收器和应用程序是否处于同一过程中?清单不包含任何类似的内容,例如:“android:process=:remote”?如果代码使用OnSharedPreferenceChangeListener,是否将其声明为成员变量以防止弱引用破坏缺陷?失败的代码引用DelayedNotificationReceiver类的onReceive方法中SharedReferences的应用。没有必要发布json结构的代码,因为我确信这很有效。我编辑了包含清单的帖子。。我认为接收器和应用程序是相同的过程。我没有在听SharedReferences的更改。。我应该吗?为什么?包括将“计划的通知”写入SharedReferences的代码,但没有显示读取“计划的通知”的代码。我需要查看从SharedReferences读取的代码来模拟失败。是的,我想简化代码以便更好地理解。。我编辑了这篇文章,添加了一个与SharedReferences交互的类,用于阅读和写作
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;
    }
}