Determine number of uses of an app - Android - java

Is there a way to know how many time a user used the app?
basicly i want to do some stuff after 3 uses, 5 uses etc... How can i hold this kind of information after it closed?

You could save that in the preferences. The following code opens the preferences, gets the number of times stored in it, and increments it.
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
int times = preferences.getInt("openKey", 0);
preferences.edit().putInt("openKey", times+1).commit();
You can call this code in your activity's onCreate method.

You can use the SharedPreferences object to store and get any arbitrary information about your application.
Use the Context.getSharedPreferences method to get and instance of this object.
To edit use the edit method to get the editor. don't forget to call commit when you are done.
Important note: if the user uninstalls the application the preferences go away to (just something to keep in mind....)

How about saving the it somewhere? Like in a Database, a SharedPreference or an XML-File?

Related

What is the best way to share data throughout all activites?

So all of my activities will need the current location of the device, as well as a set of data retrieved through a Http request. I was wondering what is the best way to find this information once, and share it across all my activities?
To pass (or persist) data between application's activities, you can either use:
SharedPreferences:
Shared Preferences allows activities and applications to keep preferences, in the form of key-value pairs similar to a Map that will persist even when the user closes the application.
Android stores Shared Preferences settings as XML file in shared_prefs folder under DATA/data/{application package} directory. The DATA folder can be obtained by calling Environment.getDataDirectory().
Link to SharedPreferences example tutorial.
Intent.putExtra(...)
Whenever you need data from an activity to be in another activity, you can pass data between then while starting the activities. Intents in android offer this convenient way to pass data between activities using Extras.
Link to Intent pass data through extras tutorial.
You can use shared preferences to save data for Android. And get preferences when you want it.
Find your scenario:
If you are going to use a very small amount of data like name, phone
no, or some value, which you want to store even if the app is closed, then use shared preference.
If you are going to use a list of object (List<Object>) and is a
large amount of data, which you want to store even if the app is closed, then use ROOM/SQLite for it.
If you are going to use a list of object(List<Object>) and is a
small amount of data, which you want to store only when the app is
active, then use the static object.
I Think, you should use shared preference for location and static variable which is being retrieved from the network.
If you want to use the current location of the device, use fusedLocationProviderClient once you get it, store it in shared preference. Whenever you the location is provided by fusedLocationProviderClient update the shared preference data.
If the data retrieved from the network is an object and changes every time you open the app and is a small amount of data, then use the static variable, or else use ROOM/SQLite

Android: static variables and moving complex data

If I have a class that contains a static variable, say x:
class MyClass {
static boolean x = false;
// Other methods
}
Now let us say that, hypothetically, I set x = true; from my first activity. Is there any point through the rest of my app's life cycle (including various activities and threads) where this value will simple be 'reset' back to false due to how the 'Google JVM' or the android environment works? I have heard that static variables have a 'lifetime', that dies when the program dies. Do Activities count as separate 'programs'? What about services? Or even Widgets?
I am asking this because it is often difficult to share complex data structures that rely on other complex processing (like syncing data from an online database) in android due to how 'separated' activities are, and static variables are often a very quick and dirty solution to the problem. Other things I have tried include serialisation, but that doesn't really seem like a practical solution either (constantly serialising and decoding objects when the user navigates from one activity to the next seems like it would be very resource intensive).
If I am an evil person for doing this, please tell me what I am doing wrong, or even better, give me some links or examples of better ways to solve this problem.
Yes. There are times where that will reset. Primarily if the user leaves the app and starts fiddling around with other apps or if the user lets the phone go to sleep for a long period of time. The Android process could kill the actual app. Then the "state" of the app will be restored when the user comes back, however static variables will be at their defaults because the actual process was rebuilt.
Generally passing small objects between Activities and Services is done by overriding the Parcelable interface. This will allow you to save and restore objects using setOnInstanceState methods of both Activities, Views, and some adapters. They will likewise, have a restore method in which you can rebuild the object. Parcelable is preferable over Serializable.
Larger data may require a shared file or database depending on the data that you want to have synced. There is a 1 MB size limit for parcelables being passed between Activities. One common tactic is to save the information to a file and send a URI to the location of where the information can be retrieved.
Answering your question - yes, there is a situation when you set x = true and value will be 'reset' back to false. Well, not exactly reset but consider this scenario: you have an activity and a service. Service is using separate process (you can define that in AndroidManifest when you declare your service). Then those two processes (main app and service) won't share memory and setting x to true in your activity won't affect the value of MyClass.x in your service. In all other cases changing value in one place will be visible everywhere else. Hope it helps!
No, a static variable will not be changed unless you change it or the app ends, it is safe (but generally unclean) to use it. Closing the activity the variable lives in won't hurt it.
You suggest you just need to keep track of a value as you move around activities. In that case you can add the value in your Intents as what is called an 'extra'. If you need to also pass back the value after, android also has the startActivityForResult feature
Intent extras example:
x below could be any type of value including any object which implements Parcelable
Intent intent = new Intent(...);
intent.putExtra("myKey", x);
startActivity(intent);
in receiving class:
x = getIntent().getBooleanExtra("myKey");
Edit:
Given your additional comment - "lists of objects that contain yet more lists of objects" you may get a Parcel too large exception when trying to use extras, but this is an indication you have a bigger architectural problem and that there may be a better approach
Use Gson.
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.
You have two options. Convert to string , then put data in an intent then pass to activity. Or Convert to string with gson, save to a preference, then in the other activity, check if the preference is alive and read from it.
If you wish to be bold, you can persist to database preferably using Realm for Android or ObjectBox is a new mobile object database optimized for performance. With ObjectBox, we are bringing technology from NoSQL server databases to mobile.

Android - Is it bad practice to have multiple Shared Preferences?

I have an app making use of SharedPreferences. One just stores app version to check against update for a changelog, the other contains some layout info that clear() gets called on as the user chooses. I finally managed to get a PreferenceFragment working and noticed a trend, so I thought I might ask this now before i go preference crazy (though I think I have enough).
I've done my best to search and see no specific mention of a problem, only that it's possible to have multiples.
I'm a little concerned about PreferenceManager.getDefaultSharedPreferences() grabbing the wrong pref, but I might simply be misunderstanding the usage.
The only relevant code i could think of from my activity:
SharedPreferences storedVer = getSharedPreferences(VER_NUM, 0);
SharedPreferences savedLayout = getSharedPreferences(LAYOUT_SAVE, 0);
It is not bad practice at all. I think it is the opposite. I think different behaviours should use different sharedPreference files.
.getDefaultSharedPreferences() uses the default com.company.packagename.xml file. And the others create their own files.
The followings advantages of using multiple sharedPreference's come up in my mind.
When you use BackupManager, you can provide which sharedPreference files to backup and restore.
When the user logout, you can delete sharedPreference file with that users private values in it. You may not want to delete some other.
From my experience with the SharedPreferences I have noticed the following:
1) Always use try to make your SharedPreference name and Attributes name unique all over the device.
2) Do not use the name of your SharedPreference like "myPreference", "preference", "appPreference"...etc. Use your PackageName as a unique identifier for the SharedPreference name.
Example:
SharedPreferences preferences = getSharedPreferences(Context.getPackageName(), Context.MODE_PRIVATE);
3) Use also a unique Keys for your attributes by concatenating the attribute name with the package name.
Example:
Editor editor = sharedpreferences.edit();
boolean isAdminKey = Context.getPackageName()+"admin";
editor.putString(isAdminKey , "value");
editor.commit();
4) No problem with editing multiple Keys values with one commit().
5) Use MODE_PRIVATE when you create your preferences to prevent other applications from reading your SharedPreferences. See step 2 for example
6) Do not rely on the SharedPreferences 100% because it will be cleared if the user pressed Clear Data button from the App info screen. Otherwise, create file in the ExternalDirectory() or send your info to a server.
Late to the party but I would say do not use multiple preferences. Stick with getDefaultSharedPreferences. I have seen many fail to keep track of the names of the saved preferences. In general it makes the code more complicated in just the wrong way (the compiler can't help you manage your names). Moreover shared preferences are for a handful of small values - use the Filesystem for big things and a database for a lot of data.
I have seen the named shared preferences be used a lot and I believe this is an unfortunate trend spread by copyPaste().
Finally, your preference activities write to the default shared preferences - I have recently answered a question where this was the issue - would be completely avoided if default preferences were used. See: Android SharedPreferences not changing
You might consider wrapping the default shared preferences methods to make them even less verbose as I've done here

SharedPreferences being reset after force close

I have been able to successfully implement Shared Preferences into my application but I have ran into a problem with the data being reset/deleted if I kill the application through a task manager.
I am using a static method for saving, that way I only need the method once and can call it everywhere within my app.
protected static synchronized void save(Context cntx){
SharedPreferences preferences2 = cntx.getSharedPreferences("BluRealms", 0);
SharedPreferences.Editor editor = preferences2.edit();
editor.putBoolean("level", Stats.level);
editor.commit();
}
As soon as I kill my app all of my data gets set back to the default settings in my SharedPreferences save method.
I also did some searching and found a few posts that say adding android:persistent="true" into the of the manifest file would fix the problem, yet the data is still reset even with this.
Edit: Well I think I found a bit of information on my problem. This Issue highlights a problem with Samsung Galaxy S phones not saving SharedPreferences properly, which is the device I am testing on. http://code.google.com/p/android/issues/detail?id=14359 - especially comment 6
Any more information on this would be great!
Ok I was able to solve this by removing the "protected static" from my save method.
Instead of calling a global save method, I simply placed the save method in each class that would need to save and then only call the save method in the onPause() and onDestroy() methods.
I noticed that if I called save() too many times within a class that also seemed to erase my SharedPreferences when I closed the app.
TIP:
Do not use static methods for getting or setting shared preferences
In my case remove the tag android: allowBackup = "true" from my manifest and this solves my problem

Storing State in Android

I have this listview that gets populated with the data that is downloaded from the internet.
Hence in the onCreate() method, I will run the async task to download the information and put it into the listview.
I placed a boolean value to whether if the list is downloaded or not during the saveInstanceState() method, this will work if the user gets out of the app from the home button and returns. However, when the user exits the program through the back button, the saveInstanceState() method is not run.
I do not want to download the list again, how can I check whether if it's downloaded before?
Check this out: Implementing the lifecycle callbacks
http://developer.android.com/guide/topics/fundamentals/activities.html
Use the callbacks to get noticed what happens to your activity and react if nesseceray.
You can use the Shared Preferences to store key-value data:
http://developer.android.com/guide/topics/data/data-storage.html
If you want to persist data beyond the LifeCycle of the application, you'll need to store it outside the Bundle.
Your options are:
Shared Preferences
Internal Storage (on Device)
External Storage (memory card)
Local Database
Network (which would probably defeat your question)
I'd suggest a private Internal Storage file for saving your data.
You can override Activity.onBackPressed() and save your state there as well.
Also, you can do
void onPause() {
if(isFinishing()) {
// save your state. maybe you'd be better off with using preferences (or other things suggested by people here), so you don't need to worry about the instance state.
}
}

Categories

Resources