Why onSharedPreference not called in second application? - android

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.

Related

Remember/Forget device function on android app

I am building an app which connects & then controls a device.
I am wanting to add a remember device function and forget device function so the user can stick to one device or switch.
I am new to android so any help on how to implement this would be great.
You can keep the information in SharedPreferences. If you are connecting to a Bluetooth device then you need to remember the Mac address of the device.
Store and retrieve the info using the following functions.
public static void addDataToSharedPrefsString(String key, String value,Context context) {
SharedPreferences.Editor sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(
context).edit();
sharedPreferences.putString(key, value);
sharedPreferences.commit();
}
public static String getDataFromSharedPrefString(String key,Context context) {
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(context);
String value = preferences.getString
(key, "");
return value;
}
Add to shared pref by
addDataToSharedPrefsString("macAddress", "MAC123q4e",context);
get the shared value by
getDataFromSharedPrefString("macAddress",context);
if you want to delete an existing item in shared pref, set the value null.
addDataToSharedPrefsString("key", null,context);
I hope this is your requirement and this solution would help you.

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.

Reading sharedpreference on mobile when starting wear app

I'm learning data communication in android wear. My understanding is that both mobile and wear apps need to connect to DataItem via Google Services API in order to read data from the one or the other.
I have data saved in sharedpreference in the mobile app. Only when I open my wear app, I want to read the data from sharedpreference in the mobile app to display on the wear.
Would it be like, whenever the mobile app updates this data in sharedpreference, have that activity connected to Google Services API and put a request in DataItem. Then the wear app would be listening to changes by WearableListenerService?
I prefer not to have service running the entire time at least not on the mobile side. What would be an approach to accomplish this?
That would be the approach to take but to save you the hassle implementing it there's already a library that does this.
WearSharedPreferences
for data transfer you can use the library Emmet
https://github.com/florent37/emmet
We can imagine a protocol like this
public interface SmartphoneProtocole{
void getStringPreference(String key);
void getBooleanPreference(String key);
}
public interface WearProtocole{
void onStringPreference(String key, String value);
void onBooleanPreference(String key, boolean value);
}
wear/WearActivity.java
//access "MY_STRING" sharedpreference
SmartphoneProtocole smartphoneProtocol = emmet.createSender(SmartphoneProtocole.class);
emmet.createReceiver(WearProtocole.class, new WearProtocole(){
#Override
void onStringPreference(String key, String value){
//use your received preference value
}
#Override
void onBooleanPreference(String key, boolean value){
}
});
smartphoneProtocol.getStringPreference("MY_STRING"); //request the "MY_STRING" sharedpreference
mobile/WearService.java
final WearProtocole wearProtocol = emmet.createSender(WearProtocole.class);
emmet.createReceiver(SmartphoneProtocol.class, new SmartphoneProtocol(){
//on received from wear
#Override
void getStringPreference(String key){
String value = //read the value from sharedpreferences
wearProtocol.onStringPreference(key,value); //send to wear
}
#Override
void getBooleanPreference(String key){
}
});

Saving data upon closing app and retrieving that data

I know, there are plenty of questions in regards to saving/retrieving data on here. I was doing find looking things up on my own and really thought I could manage to find my answers without having to "ask a question", but I began to wonder something that I haven't seen an answer for on here.
MY SITUATION:
Naturally, I'm making an app. Upon closing the app, I want to save a simple array of numbers (0 or 1) or boolean values as it were. Upon starting the app, I want to search for that array, if it exists, and retrieve it for use within the app.
I began placing my code into the activity in which the array would be used. But, I started wondering if I would have to copy/paste the overridden onStop() function into all of my activities? Or do I do it in the main activity and somehow link the other activities.
Basically, no matter what state/activity the app is currently on when the app is closed, I want to be able to save the array of int/bool and open it back up when the app is started.
Maybe I didn't know how to search for what I wanted, so explaining it felt like the right thing to do.
I don't mind doing more searching, but if someone would point me in the right direction at the very least, I'd be extremely grateful.
EDIT: If there's a better way to do what I want than what I described (i.e. using a different state instead of onStop(), for instance), please feel free to throw out ideas. This is my first time actually having to deal with the activities' lifecycles and I'm a bit confused even after looking through the android development tutorials. I really think they're poorly done in most cases.
When you application needs to save some persistent data you should always do it in onPause() method and rather than onStop(). Because if android OS kills your process then onStop() and onDestroy() methods are never called. Similarly retrieve data in onResume() method.
Looking at the purpose you want to fulfill, SharedPreferences is all you want.
The documentation states:
"SharePreferences provides a general framework that allows you to save
and retrieve persistent key-value pairs of primitive data types. You
can use SharedPreferences to save any primitive data: booleans,
floats, ints, longs, and strings. This data will persist across user
sessions (even if your application is killed)."
Use SharedPreference to store small amount of data or use SQLite to store large amount of data.
See this link
http://developer.android.com/guide/topics/data/data-storage.html
Serialize an object and pass it around which is more dependable than shared preferences (had lots of trouble with consistency with shared preferences):
public class SharedVariables {
public static <S extends Serializable> void writeObject(
final Context context, String key, S serializableObject) {
ObjectOutputStream objectOut = null;
try {
FileOutputStream fileOut = context.getApplicationContext().openFileOutput(key, Activity.MODE_PRIVATE);
objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serializableObject);
fileOut.getFD().sync();
} catch (IOException e) {
Log.e("SharedVariable", e.getMessage(), e);
} finally {
if (objectOut != null) {
try {
objectOut.close();
} catch (IOException e) {
Log.e("SharedVariable", e.getMessage(), e);
}
}
}
}
Then use a class to use:
public class Timestamps implements Serializable {
private float timestampServer;
public float getTimestampServer() {
return timestampServer;
}
public void setTimestampServer(float timestampServer) {
this.timestampServer = timestampServer;
}
}
Then wherever you want to write to the variable use:
SharedVariables.writeObject(getApplicationContext(), "Timestamps", timestampsData);
Best way to achieve that is:
create a class. Call it MySettings, or whatever suits you
in this class, define the array of ints / booleans you are going to share, as static. Create getter & setter method (property) to access that (also as static methods)
add a static load() method to MySettings that reads from SharedPreferences. When you launch the app (in your first activity or better in a subclass of Application) call MySettings.load(). This load method sets the array
add a static save() method. Public also. Now you can save from anywhere in you app. This save() method reads the array and writes in SharedPreferences
Code sample:
public class MySettings {
private static List<Integer> data;
public static void load() {
data = new ArrayList<Integer>();
// use SharedPreferences to retrieve all your data
}
public static void save() {
// save all contents from data
}
public static List<Integer> getData() {
return data;
}
public static void setData(List<Integer> data) {
MySettings.data = data;
}
}

Keeping count of notifications in a broadcast receiver

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.

Categories

Resources