How to count time in two different activities? - java

I don't know if this is even possible but I have several activities, two at the moment, and I have time limit of 20 minutes for player to finish the game. The problem is, he starts at one activity, then goes to another and so on. How to keep the timer going even in another activity, and keep it visible in a textView?
EDIT for minhaz:
public void getTime(long value, String PREFERENCE_NAME){
SharedPreferences myPrefs = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putLong("time", value);
prefsEditor.commit();
}

Just create a global timer class.
class Timer {
private static long startTime = -1;
public static void reset() {Timer.startTime = -1;}
public static void initialize() {Timer.startTime = System.currentTimeMillis();}
public static long getTimeMillis() {return System.currentTimeMillis() - startTime;}
private Timer() {}
}
Then, by importing this class (wherever you've put it), you can access the current time.

As stated by Lukas, extending Application would be nice.
You could also use a preference that store the time at which the timer was started...
But working working with timer start time sounds the best way, I think.

Start timer from one activity and when user switch to next one pass the value inside an Intent
Intent intent=new Intent(Current.class, NextActivity.class);
intent.putExtra("time", timer_value);
And on the another activity get the value as
time_value=intent.getLongExtra("time")
In this way user will get some buffer time, when their is delay in between activities, as starting activity call is Asynchronous. You can call finsh() or do something else based on your requirement from the time.
Extending Application class is also a good solution, if you want to limit time from starting the app. But thats not exactly the total play time.
Update:
For storing data, you can use persistence storage based on your requirement. Right now, shared preference look like a good candidate.
Store Data
SharedPreferences myPrefs = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putLong("time", value);
prefsEditor.commit();
Retrieve data
SharedPreferences sharedPref = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return sharedPref.getLong("time", 0);

Related

Is this an efficient way to get/set multiple SharedPreferences in a singleton helper?

My Android app stores 15-20 settings pairs with SharedPreferences, and I've been using a helper class so I don't have to create a new method in every class that needs to retrieve them.
Some retrievals are starting to take >100ms, and I'm not sure my current method is efficient for performance since it passes in the Context and creates a new SharedPreferences object each time. This happens numerous times throughout the app's AsyncTasks.
Here's what I've been doing:
public class SharedPrefHelper {
static void setDefaults(String key, String value, Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(key, value);
editor.apply();
}
static void setDefaultsInt(String key, int value, Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(key, value);
editor.apply();
}
//... continued with other variable types and getDefault variants
//.......
}
Would below be a more efficient way of handling this?
public class SharedPrefHelper {
private static SharedPreferences preferences;
static void init(#NonNull final App app) {
preferences = PreferenceManager.getDefaultSharedPreferences(app);
}
//App is the Application class, init is called in onCreate()
static void setDefaults(String key, String value) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(key, value);
editor.apply();
}
//... continued with other variable types and getDefault variants
//.......
}
Or are there other variable keywords that would do better (final, etc)?
+100ms is a long time for such a simple action and so little key-value pairs.
I think the problem is not here.
However, to answer your question, yes, the proposed alternative is certainly better than the original one. Indeed, there is no point in calling getDefaultSharedPreferences(context) multiple times, as that method points to a default file, which is set application-wide.
So just store it as instance/static field (but avoid static as much as possible).
preferences.edit()
returns a new, fresh, Editor (EditorImpl, it maintains a Map of the changed key-value pairs and then persist everything on apply) every call, so you're totally fine.

Variables don't get changed after going back

I have a boolean variable public static boolean isInDarkTheme but when I try to change the value in my settings activity it only gets changed tempolarily.
I did it so:
if (on) {
//Do something when Switch button is on/checked
MainActivity.isInDarkTheme = true;
} else {
//Do something when Switch is off/unchecked
MainActivity.isInDarkTheme = false;
}
Log.d("DarkTheme", "SETTINGS " + MainActivity.isInDarkTheme);
in my settings the variable is changed but when I go back to my main with the
arrow I created with this:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
picture with this button
it is still the same in the main
but! when I use my software key to get back to the MainActivity it get saved
picture with software back key
Any idea what I can do that it get saved with the other button?
your variable will not be saved and will be collected by garbage collector once the activity is destroyed.
you have to use something like SharedPreferences.
to save the variable
SharedPreferences sharedPrefrences = getSharedPreferences("pref_name", MODE_PRIVATE);
sharedPrefrences.edit().putBoolean("isDarkTheme", true).apply();
to load
SharedPreferences sharedPrefrences = getSharedPreferences("pref_name", MODE_PRIVATE);
// key , default value
boolean isDark= sharedPrefrences.getBoolean("isDarkThem", false);
read about SharedPreferences here
The most likely reason is that both activities are loaded by different class loaders with the effect that the MainActivity you "see" in your Settings activity is a different one than the one you "see" in your other activity. You can find that out by logging the classloader "attached" to the MainActivity by calling MainActivity.class.getClassLoader()

SharedPreferences, Singleton Class - What should you use for calling, editing, saving and recalling two integer values

My app will carry two scores the entire time, calling them, adding to them, saving them, and later calling them back again for other functions and editing. What is the best method for this? These will be the only numbers needed throughout the app.
All I am looking for is the most efficient option I should implement. And if possible a simple example of making, editing, saving and recalling. Thank you.
I suggest using SharePreferences because you are only need to store very small data.
Hint:
synchronized void saveScores(final Context contex, final String scoreOneKey, final String scoreTwoKey, final Integer scoreOne, final Integer scoreTwo){
final SharedPreferences sharedPreferences = context.getSharedPreferences("user.score.key", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS)
final SharedPreferences.Editor preferencesEditor = sharedPreferences.edit();
preferencesEditor.putInt(scoreOneKey, scoreOne);
preferencesEditor.putInt(scoreTwoKey, scoreTwo);
preferencesEditor.commit();
}
Things to Note here are:
You are method must synchronized as multiple threads can access the game score.
Notice the sharedPreference access controls (MODE_PRIVATE | MODE_MUTI_PROCESS) that tells the OS that this sharedPreference is not accessible by other apps but at same time it is possible to access it from multiple process of your app ( if you can even encrypt the scores before saving them.)
UpdatedYou can use SharedPreferences To save Scores When you will call getFirstScore() first Time it will return 0 as the variable is not yet created and then you can call setFirstScore() to save it.
public class ScoreDatabase{
private Context context;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
public ScoreDatabase(Context context){
this.context=context;
pref = context.getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE);
editor = pref.edit();
}
public int getFirstScore() {
return pref.getInt("FIRST_SCORE", 0);
}
public int getSecondScore() {
return pref.getInt("SECOND_SCORE", 0);
}
public void setFirstScore(int score) {
editor.putInt("FIRST_SCORE", score);
editor.commit();
}
public void setSecondScore(int score) {
editor.putInt("SECOND_SCORE", score);
editor.commit();
}
}
Now make instance of this class and use anywhere you want just pass getApplicationContext() in the constructor
//In your MainActivity class
ScoreDatabase scoreDatabase=new ScoreDatabase(getApplicationContext());
//call set function when you want to set score
scoreDatabase.setFirstScore(10);
scoreDatabase.setSecondScore(20);
//Call get function when you want to get score
int firstScore=scoreDatabase.getFirstScore();
int secondScore=scoreDatabase.getSecondScore();

Unable to fetch SharedPreferences

I'm trying to get familiar with using SharedPreferences, by building a simple test app where I store and retrieve user preferences by using a class that extends 'PreferenceActivity'.
The problem is that every time I shut down the app and start it again I'm unable to load the SharedPreferences values that I earlier selected.
In the MainActivity's onCreate method I am first calling a method 'loadPreferences', then creating an ImageView and a button.
I assigned onclick listener to the button that creates and starts a new intent.
...onClick(View v){
Intent intent = new Intent(MainActivity.this, MyPrefsActivity.class);
startActivity(intent);
}
In MyPrefsActivity class I have a ListPreference that has a 'Preference.OnPreferenceChangeListener'.
... {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
imageNumber = Integer.parseInt(newValue.toString());
return true;
}
};
Upon return from MyPrefsActivity to MainActivity in the 'onResume':
protected void onResume() {
super.onResume();
savePreferences();
loadPreferences();
}
private void savePreferences(){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("imageNumber", MyPrefsActivity.imageNumber);
editor.apply();
}
private void loadPreferences (){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int imageNumb = prefs.getInt("imageNumber", 0);
switch (imageNumb){
case 0:
imageView.setImageResource(R.mipmap.image1);
break;
case 1:
imageView.setImageResource(R.mipmap.image2);
break;
case 2:
imageView.setImageResource(R.mipmap.image3);
break;
default:
imageView.setImageResource(R.mipmap.image4);
}
}
When 'loadPreferences' is called for the first time upon startup, 'imageNumb' allways has a value 0, instaed of the value that I assigned to on previous run in method 'savePreferences'.
I noticed that after startup when I enter 'MyPreferencesAction' for the first time and open the ListPreferences, the checkbox that I selected on the last run is already selected for me. It seems like my selection is saved but when I try to load SharedPreferences am I messing up something???
You have to save your preferences in onPause event. Right now you are saving it in onResume when values you want are no longer there.
#Override
protected void onPause(){
super.onPause();
savePreferences();
}
#Override
protected void onResume() {
super.onResume();
loadPreferences();
}
There is another issue with your code. You are saving preferences in MainActivity, but you are changing them in MyPrefsActivity. That will not work. You have to save changes to the preferences in MyPrefsActivity, use above load/save pattern in there too. If you don't have any preference changes happening in MainActivity, you can safely omit calling savePreferences from it.
Depending on MyPrefsActivity declaration calling MyPrefsActivity.imageNumber from MainActivity may not be safe, you will have to change that code too. Like I said, most likely you don't need it at all in MainActivity (if you saving are only preferences values that are set in MyPrefsActivity) and that should be part of MyPrefsActivity.
Also Preference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value.
I realized there was a lot of needless complexity in my code. So I got completely rid of the method savePreferences(). Instead i simplified the PreferenceChangeListeners method onPreferenceChange(...):
This seems to me to be the most simplest way to update SharedPreferences when using PreferenceActivity.
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.getEditor().
putInt("imageNumber", Integer.parseInt(newValue.toString())).apply();
return true;
}
Now I save the SharedPreferences manually, only when 'onPreferenceChange' is called. Not on 'onResume', 'onStop', 'onRestart' or on 'onPause'.
Please inform me if this is a bad way to change SharedPreferences.
Quoting Dalija Prasnikar: "reference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value."
If you understood you correctly Dalija, there is a 'onPreferenceChange(...)' like method that does the job but does not have a boolean return value but void? I was not able to find any examples, could you please show or point to an examle?

Access common functions static?

I have a question which might be more general, but I came across it during android dev:
How can I best share own common used methods?
Eg retrieving a shared preference by key is always the same code. But if I have to use it in different Fragments or Activities, I always have to copy the same code:
private void setSharedPrefs(String key, String value) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
editor.putString(key, value).commit();
}
It it a good habit to make this a public static in a GlobalUtils class or so?
How would you handle these kind of functions?
You could definitely make a static class such as GlobalUtils or even a dedicated class for SharedPreferences. You just have to pass in a Context to the method so that you could get the SharedPreferences object. You can take this as far as you need it to go; I've made these classes countless times. I even have a thread-safe SharedPreferences wrapper :-)
EDIT: Just looked at my code again and half of my SharedPreference wrappers are static and the rest are lazily instantiated. That being said I think you should do whichever you feel comfortable with as long as the rest of your code doesn't necessitate it going one way or the other.
Yes you could make it public static:
public static void setSharedPrefs(Context context, String key, String value) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
editor.putString(key, value).commit();
}
Be careful in some situations where you may hold onto the context after an activity has died, that is bad.
A more likely scenario your describing could be to create a class like this:
public class MyPrefs {
SharedPreferences settings;
SharedPreferences.Editor editor;
public MyPrefs(Context context){
settings = PreferenceManager.getDefaultSharedPreferences(context);
editor = settings.edit();
}
public void saveName(String name){
editor.putString("name", name).commit();
}
}
You would lazy init this class in your class that extends Application and have a getter in there to retrieve it, with something like:
MyPrefs prefs = ((MyAppication) getContext().getApplicationContext()).getMyPrefs();
and use it like so:
prefs.saveName("blundell");
EDIT
Example of Lazy initialisation:
private MyPrefs prefs;
public MyPrefs getMyPrefs(){
if(prefs == null){
prefs = new MyPrefs(this);
}
return prefs;
}
N.B This is lazy initialization within a class that extends Application therefore this refers to your application context and will live for the duration of your Application. If you where using an Activity context you would not want to use lazy initialisation. (So use the application context!)
I usually write common code inside a static method in a different class. So that i can call the static method anywhere in the project without every time creating new class objects.

Categories