Keeping count of notifications in a broadcast receiver - android

I am trying to keep a count going on the number of unread notifications in a broadcast receiver and have the number of unread notifications display differently as they accumulate but every time the receiver is fired its going to re-initialize everything and clear out the count. How can i keep control of the count, am i going to have to create another class just to keep the variables? that seems like a lot of work for just something so simple

If you're just looking to persist a value between instantiations of your BroadcastReceiver, store the result in a private Preferences object. You can read the stored value in at the beginning of each onReceive(), and the write it back out at the end. Something like:
public static final String PREFS_NAME = "com.examples.myapplication.PREFS";
public static final String KEY_COUNT = "notificationCount";
private int currentCount;
public void onReceive(Context context, Intent intent) {
SharedPreferences values = context.getSharedPreferences(PREFS_NAME, Activity.MODE_PRIVATE);
currentCount = values.getInt(KEY_COUNT, 0); //Sets to zero if not in prefs yet
//Do your magic work here
//Write the value back to storage for later use
SharedPreferences.Editor editor = values.edit();
editor.put(KEY_COUNT,currentCount);
editor.commit();
}
You could also write to the global standard preferences with PreferenceManager.getDefaultSharedPreferences(context) instead, which wouldn't require you to define a name.

Related

Logic behind storing a max number of user favorites to SharedPreferences

I'm wanting to store a number of different user favorites (in this example a max of 5) in sharedpreferences.
The user will be able to add and delete these favorites from within the app.
I'm having trouble getting my head around how to achieve this (I assume some sort of looping is needed).
The gist of what I'm trying to do when a user adds a new favorite:
//init prefs
public static final String PREFS_NAME = "PREFS";
SharedPreferences sharedPreferences = null;
SharedPreferences.Editor sharedPreferencesEditor;
//onCreate
sharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
//method called when user adds new favorite
public void addFavorite(String fav) {
//int i = 0;
//int maxFavs = 5;
//check how many favorites are already stored in shared prefs, if any (is it under maxFavs?)
//if over maxFavs, display error
Toast.makeText(getApplicationContext(),"Favorite added",Toast.LENGTH_SHORT).show();
//else continue
//upon finding available favorite 'space' (less than permitted maxFavs), add to favorites in shared prefs
sharedPreferencesEditor = sharedPreferences.edit();
sharedPreferencesEditor.putString("fav_" + i, fav);
sharedPreferencesEditor.apply();
}
Am I getting the right idea here, or is there a better way to do what I'm intending to do? Hopefully it's clear from the above.
Store favorite count in preferences as an int and read & update it as needed. Also it would be better if you store favorites in preferences as (key : favoritedItemId, value boolean)
Even better: Use a proper local database for situations like this. Preferences is a primitive key value type storage intended for simplier cases like storing a users light mode preference.
Gave up and created a simple database following the example here:
https://inducesmile.com/android/android-sqlite-database-example-tutorial/
Still, if anyone has a solution I'd be interested to see!

preference settings in broadcast receiver

I have a broadcast receiver running independently from my application.
When a specific number calls, i need to trigger a service to run.
I am saving the triggering number in shared preferences within my application.
How do I get this value within my broadcast receiver so that I can check that the number calling matches before I start my service call.
I have tried the following code within my receiver to retrieve it:
variables
private SharedPreferences preferenceSettingsUnique;
private SharedPreferences.Editor preferenceEditorUnique;
private static final int PREFERENCE_MODE_PRIVATE = 0;
private static final String MY_UNIQUE_SETTINGS = "MY_UNIQUE_SETTINGS";
In the function I have
preferenceSettingsUnique = getSharedPreferences(MY_UNIQUE_SETTINGS,PREFERENCE_MODE_PRIVATE);
tracker_trigger = preferenceSettingsUnique.getString("tracker_trigger",null);
The value returns as null.
If anyone knows a good way to do this please.
edit showing saving procedure
preferenceSettingsUnique = getSharedPreferences(MY_UNIQUE_SETTINGS,PREFERENCE_MODE_PRIVATE);
preferenceEditorUnique = preferenceSettingsUnique.edit();
final EditText trackertrigger_Field = (EditText) findViewById(R.id.Editsmstrigger);
preferenceEditorUnique.putString("tracking_trigger",trackertrigger_Field.getText().toString());
boolean Success = preferenceEditorUnique.commit();
if(Success){
//ALERT MESSAGE
Toast.makeText(getBaseContext(),"Successfully Saved Settings.", Toast.LENGTH_LONG).show();
super.onBackPressed();
}
You are saving data in preferences with key tracking_trigger but when retrieving data from the preferences, you are trying to get data corresponding to the key tracker_triggerwhich doesn't exists. That's why always returns the default value of null. Just make both the keys same.

Android: Unbale to save boolean in SharedPreferences

Hey guys I am unable to save a boolean value using SharedPreferences. The value is ALWAYS true for some reasons. Here is how I save the value:
public static void setSharedPreference(Context ctx, String keyValue, boolean value){
SharedPreferences sp = ctx.getSharedPreferences(Constants._preferencesName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(keyValue,value);
editor.commit();
}
And this is how I get it back:
public static boolean getBooleanPreference(Context ctx, String keyValue){
boolean prefValue;
SharedPreferences sp = ctx.getSharedPreferences(Constants._preferencesName, ctx.MODE_PRIVATE);
prefValue = sp.getBoolean(keyValue, false);
return prefValue;
}
What is wrong?!
Your code is syntactically correct, but I suspect you are passing different Context while saving than you are passing while reading from prefs. This will result in accessing different shared preferences storage. This is especially easy to step on if you are doing your writes and reads in different activities and decide to pass this as context. Unless there's a reason for doing so then you most likely want to reach your preferences from anywhere in your app then use always application context instead (getApplicationContext()).
Everything is correct in your code.
The ONLY possibility of a mistake is when you are calling these methods. Please use getApplicationContext() while putting and retrieving data.
And please do a "Clear data" for the app and start with a clean SharedPreference.

Best Practices for SharedPreferences

A set of questions about SharedPreferences that I was looking for:
What, Why, When?
How does it work inside?
The Best Practice to use it?
Only some of those question were answered here. That's why I made some investigations, and tests.
As I've answered on my own question I've decided to share answer with other people.
I've wrote a little article that can also be found here.
Best Practice: SharedPreferences
Android provides many ways of storing application data. One of those ways leads us to the SharedPreferences object which is used to store private primitive data in key-value pairs.
All logic are based only on three simple classes:
SharedPreferences
SharedPreferences.Editor
SharedPreferences.OnSharedPreferenceChangeListener
SharedPreferences
SharedPreferences is main of them. It's responsible for getting (parsing) stored data, provides interface for getting Editor object and interfaces for adding and removing OnSharedPreferenceChangeListener
To create SharedPreferences you will need Context object (can be an application Context)
getSharedPreferences method parses Preference file and creates Map object for it
You can create it in few modes provided by Context, it's strongly recommended to use MODE_PRIVATE because creating world-readable/writable files is very dangerous, and likely to cause security holes in applications
// parse Preference file
SharedPreferences preferences = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// get values from Map
preferences.getBoolean("key", defaultValue)
preferences.get..("key", defaultValue)
// you can get all Map but be careful you must not modify the collection returned by this
// method, or alter any of its contents.
Map<String, ?> all = preferences.getAll();
// get Editor object
SharedPreferences.Editor editor = preferences.edit();
//add on Change Listener
preferences.registerOnSharedPreferenceChangeListener(mListener);
//remove on Change Listener
preferences.unregisterOnSharedPreferenceChangeListener(mListener);
// listener example
SharedPreferences.OnSharedPreferenceChangeListener mOnSharedPreferenceChangeListener
= new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
};
Editor
SharedPreferences.Editor is an Interface used for modifying values in a SharedPreferences object. All changes you make in an editor are batched, and not copied back to the original SharedPreferences until you call commit() or apply()
Use simple interface to put values in Editor
Save values synchronous with commit() or asynchronous with apply which is faster. In fact of using different threads using commit() is safer. Thats why I prefer to use commit().
Remove single value with remove() or clear all values with clear()
// get Editor object
SharedPreferences.Editor editor = preferences.edit();
// put values in editor
editor.putBoolean("key", value);
editor.put..("key", value);
// remove single value by key
editor.remove("key");
// remove all values
editor.clear();
// commit your putted values to the SharedPreferences object synchronously
// returns true if success
boolean result = editor.commit();
// do the same as commit() but asynchronously (faster but not safely)
// returns nothing
editor.apply();
Performance & Tips
SharedPreferences is a Singleton object so you can easily get as many references as you want, it opens file only when you call getSharedPreferences first time, or create only one reference for it.
// There are 1000 String values in preferences
SharedPreferences first = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 4 milliseconds
SharedPreferences second = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds
SharedPreferences third = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);
// call time = 0 milliseconds
As SharedPreferences is a Singleton object you can change any of It's instances and not be scared that their data will be different
first.edit().putInt("key",15).commit();
int firstValue = first.getInt("key",0)); // firstValue is 15
int secondValue = second.getInt("key",0)); // secondValue is also 15
When you call get method first time it parses value by key and adds this value to the map. So for second call it just gets it from map, without parsing.
first.getString("key", null)
// call time = 147 milliseconds
first.getString("key", null)
// call time = 0 milliseconds
second.getString("key", null)
// call time = 0 milliseconds
third.getString("key", null)
// call time = 0 milliseconds
Remember the larger the Preference object is the longer get, commit, apply, remove and clear operations will be. So it's highly recommended to separate your data in different small objects.
Your Preferences will not be removed after Application update. So there are cases when you need to create some migration scheme. For example you have Application that parse local JSON in start of application, to do this only after first start you decided to save boolean flag wasLocalDataLoaded. After some time you updated that JSON and released new application version. Users will update their applications but they will not load new JSON because they already done it in first application version.
public class MigrationManager {
private final static String KEY_PREFERENCES_VERSION = "key_preferences_version";
private final static int PREFERENCES_VERSION = 2;
public static void migrate(Context context) {
SharedPreferences preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
checkPreferences(preferences);
}
private static void checkPreferences(SharedPreferences thePreferences) {
final double oldVersion = thePreferences.getInt(KEY_PREFERENCES_VERSION, 1);
if (oldVersion < PREFERENCES_VERSION) {
final SharedPreferences.Editor edit = thePreferences.edit();
edit.clear();
edit.putInt(KEY_PREFERENCES_VERSION, currentVersion);
edit.commit();
}
}
}
SharedPreferences are stored in an xml file in the app data folder
// yours preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PREFS_NAME.xml
// default preferences
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml
Android guide.
Sample Code
public class PreferencesManager {
private static final String PREF_NAME = "com.example.app.PREF_NAME";
private static final String KEY_VALUE = "com.example.app.KEY_VALUE";
private static PreferencesManager sInstance;
private final SharedPreferences mPref;
private PreferencesManager(Context context) {
mPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
}
public static synchronized void initializeInstance(Context context) {
if (sInstance == null) {
sInstance = new PreferencesManager(context);
}
}
public static synchronized PreferencesManager getInstance() {
if (sInstance == null) {
throw new IllegalStateException(PreferencesManager.class.getSimpleName() +
" is not initialized, call initializeInstance(..) method first.");
}
return sInstance;
}
public void setValue(long value) {
mPref.edit()
.putLong(KEY_VALUE, value)
.commit();
}
public long getValue() {
return mPref.getLong(KEY_VALUE, 0);
}
public void remove(String key) {
mPref.edit()
.remove(key)
.commit();
}
public boolean clear() {
return mPref.edit()
.clear()
.commit();
}
}
Yakiv has mentioned everything about preferences so neatly and nicely. I just want to add one more point. While editing data in shared preferences we usually do
mPref.edit()
which creates a new object of SharedPreferences.Editor type every time which can result in unnecessary objects in memory. So you can maintain a reference to editor object too and save memory and object creation time and corresponding garbage collection time.

Why onSharedPreference not called in second application?

I have read all the documentation on SharedPreferences, I have one app that has the global configurations, from which all apps will want to read at will and when changes occur. I can read the SharedPreference, but how do I register for its ChangeListener?
//App1
sharedPreferences = getSharedPreferences("my.test.Config_preferences", Context.MODE_WORLD_READABLE)
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
Log.i("TAG", "!!! App1 OnPreferenceChanged()"); //WORKING!
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
//App2
otherAppsContext = createPackageContext("my.test.Config", 0);
sharedPreferences = otherAppsContext.getSharedPreferences("my.test.Config_preferences", Context.MODE_WORLD_READABLE);
String s = sharedPreferences.getString("Name", "0"); //OK value
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {
Log.i("TAG", "### App2 OnPreferenceChanged()");
//NOT WORKING!
}
};
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
This is not a good implementation.
First, as soon as the user uninstalls my.test.Config_preferences, all your apps lose their preferences.
Second, every application on the device can read these preferences -- not just yours -- which is bad for security and privacy.
Please give each application its own SharedPreferences. Or, if having one central set of preferences is necessary (e.g., app-and-plugins model), expose the preference data through something you can secure via permissions, such as a remote service using AIDL or a content provider.
Final answer:
Replace
getSharedPreferences("my.test.Config_preferences", Context.MODE_WORLD_READABLE)
with
getSharedPreferences("my.test.Config_preferences", Context.MODE_MULTI_PROCESS)
After I study the source code,
I found base/core/java/android/app/SharedPreferencesImpl.java
can answer your question.
notifyListener uses Memory to notify each other,
so your two applications can communicate with each other.

Categories

Resources