So I have constructed a class SaveAndLoad that looks like this:
public class SaveAndLoad {
public Preferences pref;
public final String path = "Highscore";
public SaveAndLoad() {
pref = Gdx.app.getPreferences("Gametitle");
}
public void saveInt(int value) {
pref.putInteger(path, value);
pref.flush();
}
public int getInt() {
return pref.getInteger(path);
}
}
When I try to save my highscore I call saveInt(highscore) and when you turn the game on again I call getInt.
constructor(){
SaveAndLoad sdRemote = new SaveAndLoad ();
try {
highscore = sdRemote.getInt();
} catch (NullPointerException e) {
highscore = 0;
}
}
The problem is that when I start the game again after a earlier game, the highscore don't load, it returns zero...
I've done the manifest permission:
Thanks
///Daniel
Ps. In the last answer I say it works on some devices, but I found out later that was not the case.
Make sure you retrieve data like this:
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
int silent = settings.getInt("score", 0);
And save it like this:
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInt("score", playerScore);
// Commit the edits!
editor.commit(); //<----------
Edit:
Ah you are using GDX. In that case make sure you are initializing this class after GDX has initialized. Check if Gdx.app.getPreferences("Game"); is returning null.
Edit2:
Ok, so we have confirmed it's a problem with Gdx on certain devices (that sucks).
If you REALLY need to make this work on both Desktop and Android devices there is another way. If you just want your game to work on Android you just should't use Gdx at all for saving the data.
I suggest you use something called a GDX Android interface. This way you can handle saving data on Android devices yourself using native Android calls that I used in this answer. This isn't really easy though but there is a tutorial here:
https://code.google.com/p/libgdx-users/wiki/IntegratingAndroidNativeUiElements3TierProjectSetup
you can store and retrive data from this.
following code of class and methods.
public class SaveAndLoad {
public SharedPreferences pref;
public final String path = "Highscore";
public SaveAndLoad() {
pref = Gdx.app.getSharedPreferences("Gametitle",MODE_PRIVATE);
}
public void saveInt(int value) {
Editor edit = pref.edit();
edit.putInt(path, value);
edit.commit();
}
public int getInt() {
return pref.getInt(path,0);
}
}
for Save HighScore.
int highscore = 0;
SaveAndLoad sdRemote = new SaveAndLoad ();
try {
highscore = sdRemote.getInt();
} catch (NullPointerException e) {
e.printStackTrace();
}
for get HighScore.
int highscore = 255;
SaveAndLoad sdRemote = new SaveAndLoad ();
try {
sdRemote.saveInt(highscore);
} catch (NullPointerException e) {
e.printStackTrace();
}
this code working properly for me. and use this i'm sure its useful for you.
From the sounds of it you are doing everything correctly, which leaves the option of us testing the device in question. If you could run the following application listener on the device and see if MyValue is increasing each time you run the application on the device.
public class PrefTest implements ApplicationListener {
#Override public void create() {
final Preferences pref = Gdx.app.getPreferences("TestApp");
int value = pref.getInteger("MyValue", 0);
Gdx.app.log("MyValue", Integer.toString(value));
value++;
pref.putInteger("MyValue", value);
pref.flush();
}
#Override public void render() {}
#Override public void dispose() {}
#Override public void resize(final int width, final int height) {}
#Override public void pause() {}
#Override public void resume() {}
}
You should see value increase in the LogCat each time you launch the application. Example, install app and run, back out and launch from the icon, repeat the back out and launch. If this works, then we know the issue is something to do with your code. If this doesn't work, then we know the issue is something with LibGDX or the phone itself.
Related
This question already has answers here:
Determine if Android app is being used for the first time
(15 answers)
Closed 6 years ago.
I am new to android development and and I want to setup some of application's attributes based on Application first run after installation. Is there any way to find that the application is running for the first time and then to setup its first run attributes?
The following is an example of using SharedPreferences to achieve a 'first run' check.
public class MyActivity extends Activity {
SharedPreferences prefs = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Perhaps set content view here
prefs = getSharedPreferences("com.mycompany.myAppName", MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
if (prefs.getBoolean("firstrun", true)) {
// Do first run stuff here then set 'firstrun' as false
// using the following line to edit/commit prefs
prefs.edit().putBoolean("firstrun", false).commit();
}
}
}
When the code runs prefs.getBoolean(...) if there isn't a boolean saved in SharedPreferences with the key "firstrun" then that indicates the app has never been run (because nothing has ever saved a boolean with that key or the user has cleared the app data in order to force a 'first run' scenario). If this isn't the first run then the line prefs.edit().putBoolean("firstrun", false).commit(); will have been executed and therefore prefs.getBoolean("firstrun", true) will actually return false as it overrides the default true provided as the second parameter.
The accepted answer doesn't differentiate between a first run and subsequent upgrades. Just setting a boolean in shared preferences will only tell you if it is the first run after the app is first installed. Later if you want to upgrade your app and make some changes on the first run of that upgrade, you won't be able to use that boolean any more because shared preferences are saved across upgrades.
This method uses shared preferences to save the version code rather than a boolean.
import com.yourpackage.BuildConfig;
...
private void checkFirstRun() {
final String PREFS_NAME = "MyPrefsFile";
final String PREF_VERSION_CODE_KEY = "version_code";
final int DOESNT_EXIST = -1;
// Get current version code
int currentVersionCode = BuildConfig.VERSION_CODE;
// Get saved version code
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
int savedVersionCode = prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST);
// Check for first run or upgrade
if (currentVersionCode == savedVersionCode) {
// This is just a normal run
return;
} else if (savedVersionCode == DOESNT_EXIST) {
// TODO This is a new install (or the user cleared the shared preferences)
} else if (currentVersionCode > savedVersionCode) {
// TODO This is an upgrade
}
// Update the shared preferences with the current version code
prefs.edit().putInt(PREF_VERSION_CODE_KEY, currentVersionCode).apply();
}
You would probably call this method from onCreate in your main activity so that it is checked every time your app starts.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkFirstRun();
}
private void checkFirstRun() {
// ...
}
}
If you needed to, you could adjust the code to do specific things depending on what version the user previously had installed.
Idea came from this answer. These also helpful:
How can you get the Manifest Version number from the App's (Layout) XML variables?
User versionName value of AndroidManifest.xml in code
If you are having trouble getting the version code, see the following Q&A:
How to get the build/version number of your Android application?
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.UUID;
import android.content.Context;
public class Util {
// ===========================================================
//
// ===========================================================
private static final String INSTALLATION = "INSTALLATION";
public synchronized static boolean isFirstLaunch(Context context) {
String sID = null;
boolean launchFlag = false;
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists()) {
launchFlag = true;
writeInstallationFile(installation);
}
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return launchFlag;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");// read only mode
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
> Usage (in class extending android.app.Activity)
Util.isFirstLaunch(this);
There is no way to know that through the Android API. You have to store some flag by yourself and make it persist either in a SharedPreferenceEditor or using a database.
If you want to base some licence related stuff on this flag, I suggest you use an obfuscated preference editor provided by the LVL library. It's simple and clean.
Regards,
Stephane
I'm not sure it's good way to check it. What about case when user uses button "clear data" from settings? SharedPreferences will be cleared and you catch "first run" again. And it's a problem. I guess it's better idea to use InstallReferrerReceiver.
Just check for some preference with default value indicating that it's a first run. So if you get default value, do your initialization and set this preference to different value to indicate that the app is initialized already.
The following is an example of using SharedPreferences to achieve a 'forWhat' check.
preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferencesEditor = preferences.edit();
public static boolean isFirstRun(String forWhat) {
if (preferences.getBoolean(forWhat, true)) {
preferencesEditor.putBoolean(forWhat, false).commit();
return true;
} else {
return false;
}
}
There's no reliable way to detect first run, as the shared preferences way is not always safe, the user can delete the shared preferences data from the settings!
a better way is to use the answers here Is there a unique Android device ID? to get the device's unique ID and store it somewhere in your server, so whenever the user launches the app you request the server and check if it's there in your database or it is new.
This might help you
public class FirstActivity extends Activity {
SharedPreferences sharedPreferences = null;
Editor editor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
sharedPreferences = getSharedPreferences("com.myAppName", MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
if (sharedPreferences.getBoolean("firstRun", true)) {
//You can perform anything over here. This will call only first time
editor = sharedPreferences.edit();
editor.putBoolean("firstRun", false)
editor.commit();
}
}
}
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Hi After doing lots of Search , I could not find the answer of a question, that seems somewhat simple.
I have multiple apps installed on device. Is there any way of finding the last launching date of all apps?
You could put the time and date in an SharedPref when the app opens.
Then, the next time you open the app the app reads the SharedPref and displays it.
Something like this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar c = Calendar.getInstance();
SharedPreferences sp = this.getPreferences(Context.MODE_PRIVATE);
String lastLaunch = sp.getString("launch", "First launch!");
SharedPreferences.Editor editor = sp.edit();
editor.putString("launch", c.getTime().toString());
editor.commit();
}
The String lastLaunch is the last time it launched! If it's the first time the string is: "First launch!"
I hope that i have helped you a little bit :)
Based on your requirements from the comments above, I'm providing a method to share the launch times between a bunch of our apps using SharedPreferences.
Firstly, we need to allow our apps to share local storage so they can access preference data. For this, we use the sharedUserId property in the app manifest. This can be your own unique string and each of the apps that share the space must have this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="example.com.myapp"
android:sharedUserId="string.user.id.here">
...
</manifest>
Secondly, we use the Application class to determine when the app comes to the foreground and when it does, write the timestamp in Context.CONTEXT_IGNORE_SECURITY mode to share between our apps:
public class MyApp extends Application implements ActivityLifecycleCallbacks {
private boolean appInBg;
private int TIMEOUT = 5000;
private Handler mHandler = new Handler();
#Override
public void onActivityResumed() {
if (appInBg) {
writeToPref();
} else {
mHandler.cancelCallbacksAndMessages(null);
}
}
#Override
public void onActivityPaused() {
mHanlder.postDelayed(new Runnable() {
#Override
public void run() {
appInBg = true;
}
}, TIMEOUT);
}
...
private void writeToPref() {
SharedPreferences prefs = myContext.getSharedPreferences("run_prefs", Context.CONTEXT_IGNORE_SECURITY);
prefs.edit().putInt("last_run", System.currentTimeMillis()).apply();
}
}
Here, we allow a buffer time of 5 seconds to switch between screens. This should be adequate in most cases.
Finally, we can read the written SharedPreference value as follows:
Context context = createPackageContext("example.com.myapp", 0);
SharedPreferences pref = context.getSharedPreferences("run_prefs", Context.CONTEXT_IGNORE_SECURITY);
int lastLaunch = pref.getString("last_run", System.currentTimeMillis());
// Similarly, for other apps.
Hope this solves your issue.
I have taken CSIPSIMPLE code and repackaged to com.mycompany.appname
The problem is, whenever app is crashed, All values are deleted from Shared preferences.
Why?
My Application is
public class BeemApplication extends Application {
static BeemApplication application = null;
public static SharedPreferences mPref;
public static Editor mEditor;
public BeemApplication() {
}
public static BeemApplication getInstance() {
if(application != null) {
return application;
} else {
return new BeemApplication();
}
}
#Override
public void onCreate() {
super.onCreate();
application = this;
mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEditor = mPref.edit();
}
#Override
public void onTerminate() {
super.onTerminate();
}
}
In Activity I will get them like ,
BeemApplication.mEditor.putString(ctx.getString(R.string.pref_online_number), number).commit();
BeemApplication.mPref.getString(ctx.getString(R.string.pref_online_number), number).commit();
This is common issue that many have faced including myself.
Have a look at this post Android - Shared Preferences are lost sometimes which shares your findings.
I would recommend not storing persistent data across shared preferences and rather use something like a database table to store settings.
In my android application i want to make a feedback dialog that will show the second time the application is started.
How can i do this ?
Can i do it by variables in a PreferenceActivity. If the a variable in the preference activity is edit by feks ++; will this be the result of the variable next time the app is started ?
Edit:
I dont get any of the suggested answers to work, can i create a text file on the ext or internal store the first time the app is started and check if the file exists ?
Use SharedPreferences:
public class MainActivity extends Activity {
private SharedPreferences mSharedPrefs;
private static final String PREF_LAUNCH_COUNTER = "launch_counter";
private int mLaunchCount = 0;
#Override
public void onCreate(Bundle savedState) {
mSharedPrefs = getPreferences(Context.MODE_PRIVATE);
if (savedState != null) {
mLaunchCount = savedState.getInt(PREF_LAUNCH_COUNTER, 1);
} else {
mLaunchCount = mSharedPrefs.getInt(PREF_LAUNCH_COUNTER, 1);
if(mLaunchCount > 1) {
//code to handle when the app was launched after the first time.
} else {
//code for when the app was launched for the first time..
}
mSharedPrefs.edit().putInt(PREF_LAUNCH_COUNTER, mLaunchCount++);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(PREF_LAUNCH_COUNTER, mLaunchCount);
}
}
No, variables do not persist through activity restarts, because the entire object is garbage collected and recreated.
You can use SharedPreferences to store data that must be persisted between application launches.
It's kinda of a barbarian solution, but it did not have Eclipse or and Android phone close to me.
You can do something like that I think :
protected boolean isSecondLaunchTime() {
SharedPreferences settings = getPreferences(MODE_PRIVATE);
int time = settings.getInt("launchTimes", 1);
if(time==1 || time>2) return false;
settings.edit().putString("launchTimes", ++time);
settings.edit().commit();
if(time==2) return true;
else return false;
}
Good luck !
I have a problem with SharedPrefences and initializations.
My application has a login where you insert an user, and for that user, you have a specific preferences... so, I need to save preferences according to the user to load it later.
I though that SharedPrefences would be the solution, and it really is I think, but I have a problem to initialize they: I have an Activity class called Options. It has static functions that returns the value of the options... but I have a problem, I call that functions before I have create that activity (intent), so I think that the functions are returning the last value that the last user has selected on the options...
How can I load the options before that calls?
I though to use first of all an Intent sending extra data with the user and in onCreate() of the Options, initialize they, but if I make an intent, then the Options will appear (xml will load).
Any help pls?
Try something like this.... adding methods for each variable you want to save.
public class PreferenceManager {
private static PreferenceManager self;
private SharedPreferences preferences = null;
private SharedPreferences.Editor editor = null;
private boolean isInitialised = false;
private static final String MY_PREFERENCE = "mypreferencekey";
private String myPreference = null;
public void initialise(Context context) {
if (!isInitialised) {
preferences = context.getSharedPreferences("MyPreferencePlace", Context.MODE_PRIVATE);
editor = preferences.edit();
loadPreferences();
isInitialised = true;
}
}
public static PreferenceManager getInstance() {
if (self == null) {
self = new PreferenceManager();
}
return self;
}
private PreferenceManager() {
}
public void setPreference(String newPreferenceValue) {
this.myPreference = newPreferenceValue;
savePreferences();
}
public String getPreference(){
return myPreference;
}
private void savePreferences() {
editor.putString(MY_PREFERENCE, myPreference);
editor.commit();
}
private void loadPreferences() {
myPreference = preferences.getString(MY_PREFERENCE, null);
}
}
All the SharedPreferences need is a context and it can be initialized. As your application always opens an Activity to start with, you always have a context to work with.
I would advise you to wrap the SharedPreferences in a Singleton class and just pass a context as parameter at the getInstance method. You should be able to access your shared preferences at all Activities this way.
I work on the dependency injector for android, and content of shared preferences is already injectable into annotated fields ( see: https://github.com/ko5tik/andject , PreferenceInjector). Patches and improvements are welcome. Saving of preferences comes soon