2

So I have indeed searched thoroughly for an answer to my question; normally I can find answers pretty easily to pretty much anything.

Anyway, basically I have an alarm manager set up which eventually sets a broadcast receiver. Inside the receiver, it decides which intent has been received, removes a shared preference, and then sets a notification that starts the activity. The problem is that on my phones with 4.0 the shared preference item is not successfully deleted, but on any previous phones I've tried (2.2, 2.3) it works perfectly.

I did end up finding the documentation of Android 3.1 and the FLAG_INCLUDE_STOPPED_PACKAGES implementation. I tried throwing that onto the intent, just in case, but it still wasn't working. Either way, it's not the launching of the activity that is the problem, but the simple deletion of a shared preference.

I hope that's clear enough! I'll put in some of the code below.

This is where the intent is started:

Calendar cal = Calendar.getInstance();
int seconds = 5 * 60; // 1 * 24 * 60 * 60;
cal.add(Calendar.SECOND, seconds);

Intent intent = new Intent(SetAlertActivity.this, ReminderReceiver.class);
intent.putExtra("id", "FAlert");
//intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), FRAUD_ALERT_CODE, intent, 0);

AlarmManager alertManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alertManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);

settingsEditor = alertSettings.edit();
settingsEditor.putLong("AlertTime1", cal.getTimeInMillis());
settingsEditor.commit();

And then the broadcast receiver onReceive():

    nContext = context;
    alertSettings = nContext.getSharedPreferences(MainActivity.PREFERENCE_FILENAME, 0);
    if (intent.getStringExtra("id").equals("FAlert"))
    {

        settingsEditor = alertSettings.edit();
        settingsEditor.remove("AlertTime1");
        settingsEditor.commit();

        String ns = Context.NOTIFICATION_SERVICE;
        int icon = R.drawable.ar_icon;
        CharSequence tickerText = nContext.getString(R.string.notification_ticker);
        CharSequence contentTitle = nContext.getString(R.string.notification_title);
        CharSequence contentText = nContext.getString(R.string.notification_text);
        long when = System.currentTimeMillis();

        NotificationManager mNotificationManager = (NotificationManager) nContext.getSystemService(ns);
        Notification notification = new Notification(icon, tickerText, when);

        Intent notificationIntent = new Intent(nContext, SetAlertActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(nContext, 135, notificationIntent, 0);

        notification.defaults |= Notification.DEFAULT_SOUND;
        notification.defaults |= Notification.DEFAULT_LIGHTS;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        notification.setLatestEventInfo(nContext, contentTitle, contentText, contentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, notification);
    }

So, as I mentioned before, on my devices on 4.0 (I don't have any 3.X devices) the

settingsEditor = alertSettings.edit();
settingsEditor.remove("AlertTime1");
settingsEditor.commit();

part isn't working. The activity will open correctly, but the "AlertTime1" is still there. On the 2.2 and 2.3 devices, the "AlertTime1" is successfully deleted.

sigh :D

Thanks for any help!!

Oh, and in case it's needed, here is my manifest for the receiver:

<receiver
    android:name="ReminderReceiver"
    android:process=":remote" >
</receiver>

This is where the difference shows:

    alertSettings = getSharedPreferences(AlertRenewActivity.PREFERENCE_FILENAME, 0);
    settingsEditor = alertSettings.edit();
    if (alertSettings.contains("AlertTime1"))
    {
        alertTime = alertSettings.getLong("AlertTime1", 0);
        timeLeft = (int) ((alertTime - System.currentTimeMillis()) / (1000L));
        daysLeft = timeLeft / (60 * 60 * 24);
        daysLeftView.setText(Integer.toString(daysLeft));
        setAlert.setEnabled(false);
        setAlert.setTextColor(R.color.dark_text);
    }
    else
    {
        daysLeftView.setText(R.string.no_alert_set);
    }

On my older phones, it correctly resets to saying "No Alert Set" but on the 4.0 phones it still shows "0" days left (which is what it says since I'm only setting the alert to 5 minutes or so for testing). Basically, the user can't set a new alert because it hasn't reset correctly, and again, only on the 4.0 phones I'm trying :P

leenephi
  • 900
  • 5
  • 13
  • As you can see I haven't asked many questions before ;) I hope this is a worthy first one! – leenephi May 05 '12 at 19:37
  • Have you stepped through your code to see if you're making inside your `if` block? – Jason Robinson May 05 '12 at 19:49
  • Yeah, the notifications work perfectly, and I can run the activity from the notification that is created; the only thing that doesn't work on my 4.0 phones is the shared preference "AlertTime1" getting deleted. – leenephi May 05 '12 at 19:54
  • Can you show where you are setting `alertSettings` in the first block of code? – Jason Robinson May 05 '12 at 19:59
  • Make sure you have an activity, and that you launch the activity manually before trying to do anything with the broadcasts. http://commonsware.com/blog/2011/07/13/boot-completed-regression-confirmed.html – CommonsWare May 05 '12 at 20:05
  • alertSettings = getSharedPreferences(PREFERENCE_FILENAME, 0); which alertSettings is called privately in the beginning of the class. – leenephi May 05 '12 at 20:13
  • Try printing the value of `AlertTime1` before and after you remove it, let me know what is printed. – Jason Robinson May 05 '12 at 20:15
  • And yes, the user sets this intent from inside the application. – leenephi May 05 '12 at 20:17
  • I'll do that as soon as I get back home. Thanks! – leenephi May 05 '12 at 20:21
  • Ok I did this: Log.i("alertrenew", "" + alertSettings.getLong("FraudAlertTime", 123)); settingsEditor = alertSettings.edit(); settingsEditor.remove("FraudAlertTime"); settingsEditor.commit(); Log.i("alertrenew", "" + alertSettings.getLong("FraudAlertTime", 123)); and it showed: 1336253282195 123 (123 was the default I had set to return, so it seems to be working..?) Is that what you were asking for? – leenephi May 05 '12 at 21:31
  • Did you read the blog Mark posted? It's most likely your problem since you said it works fine pre-Honeycomb – Jason Robinson May 06 '12 at 03:54
  • Sure did. And according to that it's not the issue.. In order for this "alert" to get set in the first place the user opens the app, clicks a button, and from there the alarm manager begins with the code I have above. From there, I have it set to go off a few minutes later. Everything in the code works fine in the ICS phones. The notifications run, they open the app, the only thing is the shared preferences doesn't commit the deletion in the ICS phones. It's so frustrating haha :P – leenephi May 06 '12 at 04:10
  • I guess what I can try is just having a check in the activity itself that says "if the alarm time is less than 0, delete the alarm time." But that's not as fun as solving this mystery ;) – leenephi May 06 '12 at 04:12

5 Answers5

1

Use Context.MODE_MULTI_PROCESS as the 2nd parameter to getSharedPreferences(). The problem is that you have the broadcast receiver running in a separate process from your activities, and as of Android 3.0 the default behaviour of multi-process access to shared preferences has changed. This should fix the problem for you on 4.x devices.

However, there is a bug in Android 2.3 which causes simultaneous access to shared preferences from multiple processes not to work reliably in some cases. We came across this and were very frustrated by it because it is difficult to reproduce and explain (probably some kind of timing issue).

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Anyone who haven't tried this solution. Please try this one first With the implementation of this answer: https://stackoverflow.com/a/18557877/7099939 – M Shaban Ali Dec 21 '22 at 13:58
0

What I ended up doing was just having a check in the activity itself that says "if the alarm time is less than 0, delete the alarm time." It was a work around; I didn't receive any other answer that worked unfortunately.

leenephi
  • 900
  • 5
  • 13
0

you should delete android:process=":remote" attribute in your receiver in the manifest. SharedPreferences does not work with new processes and :remote declares "do whatever the process id is ".

OzgurGundogan
  • 73
  • 1
  • 6
0

I know this is an old question but maybe my answer will be helpful for others who facing this problem this days. I just found a solution and it worked for me.

make a service and implement the work you want on it, and then just call the service from your broadcast receiver, which means the only work of your receiver is to call the service which will handle the work you want to do.

-1

The simply answer is this: don't bother doing so much in a receiver. Instead, kick of an intent call to another Activity in the same package hierarchy and you'll be able to do it just as easily.

  • I'll try this. I read something about it but it seemed to be talking more about separate threads in receivers. It just seems weird that it works fine on earlier versions of Android. – leenephi May 06 '12 at 01:26