I need that when calling the onBackPressed method, the activity is not destroyed but pauses and stops.
My idea is that it works like when the Home button of the mobile is pressed, which calls onPause and onStop because that way, the activity is not destroyed and when the activity is reopened, onResume is called so that the variables remain the value that when the activity was closed.
Is there any way to do this? If not, is there a way to keep the state of the variables once the activity is closed? I have tried to use SharedPreference but I cannot use them because my variables are of different types than those offered.
If you want to customize the behaviour of your buttons, you have to use in your activity ...
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
return true; //To assess you have handled the event.
}
//If you want the normal behaviour to go on after your code.
return super.onKeyDown(keyCode, event);
}
Here is some more information about handling key event.
Although it seems what you want to do is just retain the state of your activity. The best way is to store your data before quitting and call it back when you recreate your activity.
If you want to store temporary data (I mean not save it between 2 boots), one way to do it would be to use sharedPreferences.
//Before your activity closes
private val PREFS_NAME = "kotlincodes"
private val SAVE_VALUE = "valueToSave"
val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
val editor: SharedPreferences.Editor = sharedPref.edit()
editor.putInt(SAVE_VALUE, value)
editor.commit()
//When you reopen your activity
private val PREFS_NAME = "kotlincodes"
val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
sharedPref.getString(SAVE_VALUE, null)
Another way to do it since you cannot use sharedPreferences (because you don't use primitive types), is to use a global singleton.
Here is a Java implementation ...
public class StorageClass{
private Object data1 = null;
private StorageClass instance;
private StorageClass(){};
public static final StorageClass getInstance(){
if(instance == null){
synchronized(StorageClass.class){
if(instance==null) instance = new StorageClass();
}
}
return instance;
}
public void setData1(Object newData) { data1 = newData; }
public Object getData1() { return data1; }
}
Then just use ...
StorageClass.getInstance().setData1(someValue);
... and ...
StorageClass.getInstance().getData1(someValue);
In Kotlin ...
object Singleton{
var data1
}
Which you use with ...
Singleton.data1 = someValue //Before closing.
someValue = Singleton.data1 //When restarting the activity.
Related
I have three button in my activity when I click any of two both will get disable but when I went back to my activity they won't restore the previous state.I have tried to achieve this using shared preference but Couldn't hold button state .Can anyone tell me about the mistake that I'm doing in shared preference.
Here I'm sharing my code with you.
on create method
spStateButton= getApplicationContext().getSharedPreferences("Button_State", 0);
spEditor = spStateButton.edit();
In Activity
public void setButtonState(boolean enabled) {
spEditor.putBoolean("btn_state", enabled);
spEditor.commit();
}
public boolean getButtonState(){
return spStateButton.getBoolean("btn_state", true);
}
button place in my activity
holder.btn_Fwd.setEnabled(getButtonState());
setButtonState(false);
holder.btn_Rec.setEnabled(getButtonState());
setButtonState(false);
You used method setButtonState(boolean enabled) for saving value to shared preference and you always call that method with parameter as false. So in shared preference the key "btn_state" having value always false.
So if you want to enable button for next time activity starts, call something like
setButtonState(true);
You can also use Singleton class to save a status value across app. Create class as below
public class SingleTon {
private static final SingleTon instance = new SingleTon();
private Boolean buttonState = true //initially visible
private SingleTon(){}
public static Boolean getButtonState(){
return buttonState;
}
public void setButtonState(Boolean buttonState){
return instance;
}
public SingleTon getInstance(){
return instance;
}
}
I have two activities named One_Activity and two_activity.
After allowing the user to make a selection I want to allow the app to decide which activity to display - even if we exit from the program and return.
For instance we should always launch two_activity as the default if we selected it.
How can I implement this?
To extend on JoelFernandes suggestion, which is a correct solution, your launch activity will need to check SharedPreferences as follows
public class MainActivity extends Activity {
public static final int MODE_LAUNCH_A = 0;
public static final int MODE_LAUNCH_B = 1;
public static final String PREF_LAUNCH_MODE = "PREF_LAUNCH_MODE";
#Override
protected void onResume() {
super.onResume();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Intent target;
switch(prefs.getInteger(PREF_LAUNCH_MODE, 0)) {
case MODE_LAUNCH_A:
target = new Intent(this, AlphaActivity,class);
break;
case MODE_LAUNCH_B:
target = new Intent(this, BravoActivity,class);
break;
}
startActivity(target);
}
}
In the Activity where you select the Activity to use as the Main Activity you need to save the preference like follows:
private void saveSelection(int selection) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().setInteger(MainActivity.PREF_LAUNCH_MODE, selection).commit; //(or .apply() instead of commit)
}
// call the above method like
saveSelection(MainActivity.MODE_LAUNCH_A);
In the manifest you should also set NoHistory on MainActivity to stop it making a mess when you press the back button.
You can set a flag and save it in SharedPreferences. When you reopen the app, access the flag and depending on its value, you can show the desired activity as your main activity.
Please read carefully because it is a little bit complicated!
I have a service that call many functions every 5 second. Now I want to call one specific fucntion in those functions just 1 time only. So I make this to check if that function has called before.
private void checkFirstLaunchApp() {
final String HAS_RUN_BEFORE = "hasRunBefore";
final String HAS_RUN = "hasRun";
SharedPreferences runCheck = getSharedPreferences(HAS_RUN_BEFORE, 0);
Boolean hasRun = runCheck.getBoolean(HAS_RUN, false);
if (!hasRun) {
SharedPreferences settings = getSharedPreferences(HAS_RUN_BEFORE, 0);
SharedPreferences.Editor edit = settings.edit();
edit.putBoolean(HAS_RUN, true); //set to has run
edit.apply(); //apply
//do that function
functionIWant();
}
} else {
//do nothing
}
}
But the problem is if I close my app and reopen it,that function will not be called anymore. What I want is when I reopen my app, that function will be called 1 time again.Please show me how can I do that?
you have to reset HAS_RUN to false inside onStart() of your launcher activity.
Alternate
Extend Application class and create global variable:
public class MyApplication extends Application{
public boolean hasRun;
public void onCreate (){
hasRun=false;
}
}
Get instance of MyApplication
MyApplication app=(MyApplication)getApplication();
if(!app.hasRun){
app.hasRun=true;
// do your stuff
}
Handle it in the onResume method
Use global variable instead of SharedPreferences
A field variable is fine, sharedpreferences is not suitable for this case.
private boolean mIsCalled;
...
private void functionIWant() {
if (mIsCalled) return;
mIsCalled = ture;
// your function body
}
Set SharedPreference to false in onStop() method :
SharedPreferences settings = getSharedPreferences(HAS_RUN_BEFORE, 0);
SharedPreferences.Editor edit = settings.edit();
edit.putBoolean(HAS_RUN, true); //set to has run
edit.apply(); //apply
Call your method in onResume() method :
checkFirstLaunchApp()
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
I am working on an application, wherein after say 5 times the app is opened by a user, at 6th attempt the app should ask for feedback from user. I tried using Activity OnStart,OnResume, but its not working out since even after leaving and re-entering activity these methods are called. Also as per android functionality, I cannot quit app so that I can find it out from the first activity called. How do I find how many times the app was launched?
I hope this is not confusing.
Edit
Alternatively is there a way, wherein I can always resume my app from the first activity( or welcome page for eg.), once user presses home to quit the app.
This is actually quite simple. Using SharedPreference or the Database.
during OnCreate add 1 to the numberofTimes counter and commit.
OnCreate (Bundle bundle){
mPref = getPreferences();
int c = mPref.getInt("numRun",0);
c++;
mPref.edit().putInt("numRun",c).commit();
//do other stuff...
}
OnCreate is called regardless of you start the app or you resume the app, but isFinishing() returns true if and only iff the user (or you) called finish() on the app (and it was not being destroyed by the manager)
This way you only increment when you are doing fresh start.
the isFinishing() Method inside of a OnPause method to check to see if the activity is being finish() or just being paused.
#Override
protected void OnPause(){
if(!isFinishing()){
c = mPref.getInt("numRun",0);
c--;
mPref.edit().putInt("numRun",c).commit();
}
//Other pause stuff.
}
This covers all your scenarios:
1. user starts app/activity (+1)-> finishes app, exit with finish()
2. user starts app (+1) -> pause (-1) -> returns (+1)-> finish
3. user starts app (+1) -> pause (-1) -> android kills process (0) -> user returns to app (+1) -> user finish.
every scenario you only increment the "times run" counter once per "run" of the activity
Just:
declare:
private SharedPreferences prefs;
private SharedPreferences.Editor editor;
private int totalCount;
initialize in onCreate():
prefs = getPreferences(Context.MODE_PRIVATE);
editor = prefs.edit();
print or count wherever you want (any where in onCreate() or any specific click as you specified):
totalCount = prefs.getInt("counter", 0);
totalCount++;
editor.putInt("counter", totalCount);
editor.commit();
now print totalCount where you want to count e.g.:
System.out.println("Total Application counter Reach to :"+totalCount);
if you have a starting activity for app launch then you can implement it in following ways
1. Database:- through database you can save your application launch count and retrieve it on create of activity.
Static Variable:- static variable also retain values during application start and end
Application Preference:-you can store value in application preference and use it
problem with 2 and 3 approach is that if you switch off and on again your phone you will loose data. but if you still want to use 2 or 3 approach then 2 approach is very simple and
sample code for 3rd approach here
well you have to extends Application class and create a subclass from that
public class MyApp extends Application{
int visitCount;
onCreate(){
visitCount=0;
}
and you can mention it in your menifest file like
<application name="MyApp">
.....
</application>
and in onCreate of your activity you can get it by
MyApp myApp=(MyApp)getApplicationContext();
Edit1:
subclass your activity and override method
public class myActivity extends Activity{
#Override
onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
counterFlag=true;
}
}
it is get called when user press home button
and again override onResume() and check whether your counter flag is enabled or not
and create all your activity by subclassing your MyActivity
also if any other activity has exit point on click of back button then you can override
#Override
public void back_pressed(){
}
and do your task accordingly
I think this would be the best option in order to cover all scenarios:
private static boolean valueOfLaunchCountModified = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
if(!valueOfCountModified){
preferences = getPreferences(MODE_PRIVATE);
launchCount= preferences.getInt("launchCount", 0);
if(preferences.edit().putInt("launchCount", ++launchCount).commit()){
valueOfCountModified = true;
if(launchCount == 5){
//Do whatever you want
}
}
}
}
If we remember the definition of a static variable ("...They are associated with the class, rather than with any object. Every instance of the class shares a class variable...") we will discover that is perfect for us.
When onPause method or an orientation change is executed the value of "valueOfLaunchCountModified" doesn't change; however, if the app process is destroyed, the value of "valueOfLaunchCountModified" changes to false.
If you only want to count "true" invocations then extend Application and place counter logic into Application#onCreate. This could be a simple preference
I prefer to use onResume to track launch count since it’s getting called in every scenario (refer to Android Activity Lifecycle) when the activity is shown.
onResume could be called quite frequently depending on usage pattern, so instead of tracking launch count, it would be better to track launch session (as in only 1 launch count would be tracked per hour).
#Synchronized fun appSessionCount(sharedPref: SharedPreferences): Boolean {
val now = LocalDateTime.now(ZoneOffset.UTC)
val firstSeconds = sharedPref.getLong(KEY_FIRST_LAUNCH_DATE, 0)
if (firstSeconds == 0L) {
sharedPref.edit {
putLong(KEY_FIRST_LAUNCH_DATE, now.atZone(ZoneOffset.UTC).toEpochSecond())
}
}
val seconds = sharedPref.getLong(KEY_LAST_SESSION_DATE, 0)
val lastDate = if (seconds > 0) LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneOffset.UTC) else null
var count = sharedPref.getLong(KEY_SESSION_COUNT, 0)
// first time or 1 hour ago
if (lastDate == null || Duration.between(lastDate, now).toHours() >= 1) {
sharedPref.edit {
putLong(KEY_SESSION_COUNT, count + 1)
putLong(KEY_LAST_SESSION_DATE, now.atZone(ZoneOffset.UTC).toEpochSecond())
}
return true
}
return false
}
I run the code at onResume of my main activity.
class MainActivity : AppCompatActivity() {
lateinit var sharedPref: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
sharedPref = getSharedPreferences("LuaApp", Context.MODE_PRIVATE)
}
override fun onResume() {
super.onResume()
appSessionCount(sharedPref)
}
}
https://code.luasoftware.com/tutorials/android/android-track-app-launch-count/