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){
}
});
Related
I have created an app which is relied on my local server which fetch profile image and information about user..Code works fine without any problem but when I change my data in the local server (for example profile picture )the updated profile is not reflecting in the application until activity is restarted but this should not be happened because live data should reflect the change immediately as soon as changes occurred in the database.
below is the code of live data class
private MutableLiveData<Profile> profileMutableLiveData;
public void init(String token){
if (profileMutableLiveData!=null){
return;
}
repository=Repository.getInstance();
profileMutableLiveData=repository.getProfile(token);
}
public LiveData<Profile> getProfile(){
return profileMutableLiveData;
}
here is my Repository code
public class Repository {
private static Repository instance;
public static Repository getInstance(){
if (instance==null){
instance=new Repository();
}
return instance;
}
public MutableLiveData<Profile> getProfile(String token){
MutableLiveData<Profile> data=new MutableLiveData<>();
RetrofitApi retrofitApi=RetrofitInstance.getInstance();
Call<Profile> call=retrofitApi.getProfile(token);
call.enqueue(new Callback<Profile>() {
#Override
public void onResponse(Call<Profile> call, Response<Profile> response) {
Profile profile=response.body();
if (response.isSuccessful()){
data.setValue(profile);
}
}
#Override
public void onFailure(Call<Profile> call, Throwable t) {
}
});
return data;
}
}
Code in main activity to observe changes....
actually I am showing profile image in navigation drawer ... like telegram app
viewModelClass = new ViewModelProvider(this).get(ViewModelClass.class);
viewModelClass.init(token);
viewModelClass.getProfile().observe(this, new Observer<Profile>() {
#Override
public void onChanged(Profile profile) {
Picasso.get().load("http://192.168.43.216:8000" + profile.getProfile_photo()).into(profileImage);
fName = profile.getFirst_name();
lName = profile.getLast_name();
image = profile.getProfile_photo();
nameView.setText("Hello " + profile.getFirst_name());
}
});
}
The code is working fine but I want the data must be updated as soon as changes made in my server...
but data is updated when I restart the activity or opening app again after closing the activity...
May be the problem - is that you begin to observe in your activity one instance of MutableLiveData, and then you replace it with another one.
In your ViewModel:
profileMutableLiveData=repository.getProfile(token);
you override it instead of setting new value with "postValue"
In your Repository:
MutableLiveData<Profile> data=new MutableLiveData<>();
you make another instance of LiveData
You can try to change your return value from a Repository to a "Profile" and set it as a new value of MutableLiveData in your ViewModel with "postValue"
UPDATED
I've read your question more carefully. I think my answer above wouldn't give you what you expect (in case you expect Retrofit should update LiveData instantly like ROOM does)
So my thoughts:
You expect too much using LiveData+Retrofit. Just using them doesn't mean you'll get on-line updates of your data on your server. To achieve that you have to change mechanism of your interaction with your server, not just fix few lines in code you've shown.
There is mechanism LiveData+ROOM that works with local DB (Sqlite) in a way, that you expect from LiveData+Retrofit. But there is no magic there. Room is using mechanic, that built-in in Sqlite for notifying (triggering) when there are some changes in DB tables occur. But Retrofit doesn't implement similar mechanism with Rest Api and actually it's not its responsibility.
To achieve what you want you can look at several possibilities:
To use some Cloud Service API, that contains that built-in mechanism for notifying your device when data changes (Firebase, for example)
To implement some kind of periodic synchronisation of your app data with server. After this synchronisation you'll have all data on device and depending on where you put your data you could observe changes with LiveData+Room or FileObserver.
To simplify your case and refresh your data from the server at activity explicitly after click on Button "Refresh" on your activity. In that case you can implement steps that I wrote at first version of my answer.
I want to store data retrieved from API using volley, but if I made 2 different requests followed by each other , it shows the first request only before updating .
I have to request the second one again to store the new data.
Is there a solution?
SharedPreferences m=PreferenceManager.getDefaultSharedPreferences(context);
String resp=m.getString("Response","");
return resp;
private void share (String x)
{
SharedPreferences
m=PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor=m.edit();
editor.putString("Response",x);
editor.commit();
}
I would like to store user preferences in Firebase real time database instead of typical sharedPreferences.
As an example, my user should specify the itemId in order to access to this part of the database:
items
itemId
members
uid: true
So when the user fill in the itemId, I need to check if this itemId exists in the database and display error asking the user to fill in another itemId.
I envisage to use standard Preference screens and associate a custom PreferenceDataStore at least to handle the itemId.
When reading the documentation, I need to override getString/putString methods:
public class DataStore extends PreferenceDataStore {
#Override
public void putString(String key, #Nullable String value) {
// Save the value somewhere
}
#Override
#Nullable
public String getString(String key, #Nullable String defValue) {
// Retrieve the value
}
}
At the end, I need to manage it asynchronously in order to query my database and get some results.
So I'm wondering if using PreferenceDataStore is the good approach ... My initial idea was to avoid developping settings screens that already exist in Androidx Preference lib.
Thx for your help!
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.
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.