Save the data and using it after restarting the app Android - java

I'm creating a simple app where the user can change the seekbar value. make the default value as 0 and setMax as 5. Every time the app is closed and started back, seekbar value is set to 0. How can I use and set the previous seekbar value which was set before closing the app.
Here's my Activity class >
public class MainActivity extends Activity {
SeekBar s;
TextView v;
public int n;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
s=(SeekBar)findViewById(R.id.seekBar1);
v=(TextView)findViewById(R.id.textView1);
next=(Button)findViewById(R.id.button1);
s.setProgress(n);
v.setText(n+" ");
s.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
n = progress;
v.setText(n+" ");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
v.setText(n+" ");
}
});
}
}
I Tried using onSaveInstanceState and onRestoreInstanceState but failed to restore back to the previous state.
Please Help
Thanks in Advance.

First of all, onSaveInstance and onRestoreInstance method are triggered only, when a destruction because of orientation change happens, hence you can not use this mechanism with that purpose, in order to store previous values after explicitly destroying the activity, you can use one of the persistance mechanisms that android provides. SharedPreferences or SQLiteDB saving them before destroying the activity, and restoring when the activity is started.
To get the latest value if any you have to add this code in onCreate method:
private SharedPreferences prefs;
private int progress;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
progress = prefs.getInt("myProgress", 0);
}
//And to store it all the time before the activity is destroyed you have to add this code in onPause:
protected void onPause() {
super.onPause();
Editor editPrefs = prefs.edit();
editPrefs.putInt("myProgress", newProgressValue);
editPrefs.commit();
}
Hope this helps.
Regards!

You might want to look at Storage Options in the Developers guide.
Specifically, Shared Preferences seems like a good place to start.

you can try to use SQL database, the database will be availble even after the app is closed and reopened

Related

onResume() getting called on pressing back arrow. Please see details

I have a method in onResume() which fetches user's data and should get called when user launch the app. This is working fine.
The problem is that for example after opening 'Settings' when I tap/click on the back arrow, the method in onResume() gets called again and user data starts getting fetched again.
What I want is, I want that method to get called only when user launches the app and not every time the user transition back from settings to main activity.
Here's the onResume() in MainActivity.java:
#Override
protected void onResume() {
super.onResume();
fetchUserData();
}
Here's how I transition to Settings.java:
Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(settingsIntent);
Please let me how can I restrict the fetchUserData() to get called only when user launches the app and not again when user transition back to main activity from any other activity by tapping/clicking on back arrow.
Sorry, if question seems to be badly formatted. I'm still a beginner here.
if you want the method to be called only once when the activity opens move it inside OnCreate() method.OnResume() can be called several times.You can see the documentation of acttivity lifecycle here
You could adapt the following code, by setting a flag/indicator so that only wanted returns are processed (eg set resume_state to RESUMESTATE_NOTHING except when starting an intent after which you want to fetchUserData:-
public class AisleListByCursorActivity extends AppCompatActivity {
public final static int RESUMESTATE_NOTHING = 0;
public final static int RESUMESTATE_AISLEADD = 1;
public final static int RESUMESTATE_AISLESTOCK = 2;
public final static int RESUMESTATE_AISLEDELETE =3;
public final static int RESUMESTATE_AISLEUPDATE = 4;
public int resume_state = RESUMESTATE_NOTHING;
public ShopsCursorAdapter currentsca;
public AislesCursorAdapter currentaca;
public ShopListSpinnerAdapter currentslspa;
public long currentshopid;
private final static String THIS_ACTIVITY = "AisleListByCursorActivity";
private final ShopperDBHelper shopperdb = new ShopperDBHelper(this,null, null, 1);
private ListView aisleslistview;
private Cursor csr;
private int shopid = 0;
protected void onResume() {
super.onResume();
switch (resume_state) {
case RESUMESTATE_AISLEADD:case RESUMESTATE_AISLEUPDATE: {
Cursor csr = shopperdb.getAislesPerShopAsCursor(currentshopid);
currentaca.swapCursor(csr);
resume_state = RESUMESTATE_NOTHING;
break;
}
default: {
resume_state = RESUMESTATE_NOTHING;
}
}
}
........
public void aalbcadd(View view) {
resume_state = RESUMESTATE_AISLEADD;
Intent intent = new Intent(this,AisleAddActivity.class);
intent.putExtra("Caller",THIS_ACTIVITY);
intent.putExtra("SHOPID", currentshopid);
startActivity(intent);
}
Create method in OnStart() or onCreate() rather than onResume(). for reference - please see this link for better understanding of Android LifeCycle http://developer.android.com/reference/android/app/Activity.html
If you want your method to be called only once you must put that method in onCreate method of Activity. Because onResume is always called you come back to the activity as per Android lifecycle. So just replace you method fetchUserData(); into onCreate like below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_list);
fetchUserData();
}
#Override
protected void onResume() {
super.onResume();
}

Asynctask onpostexecute is not updating views if the screen is rotated while doinbackground is excuted

I had a simple program where i need to update the list and text based on the server response ...
But Asynctask onpostexecute is not updating views if the screen is rotated while doinbackground is executed .
I came to know the reason that , as the activity is recreated , onpostexecute wont update its views (Same problem..here is the link : Chek this link)
But i was not satisfied with the answer as it just suggesting to restricting to recreate the activity (i want recreating the activity as in my project i had some extra layout in landscape mode).
Please dont suggest setretaininstance(true) by taking fragments as it doesnt call oncreateview(), which is not suitable for my project.
May be as lastoption i can restrict orientation programatically in onpreexecute and release it in onpostexecute. But still it will not be good practice i think.
public class MainActivity extends ActionBarActivity {
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView) findViewById(R.id.textview);
if(savedInstanceState==null)
{
new myAsync().execute();
}
}
public class myAsync extends AsyncTask<Void, String, Void>
{
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
textView.setText("started");
Log.e("started", "started");
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#SuppressWarnings("deprecation")
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.e("executed", "executed");
}
}
}
This is my sample program . textview is not updating if screen is rotated.
Please suggest . Thanks in advance .
You could provide myAsyncTask with a TextView member with a setter and store the current task as static member of the activity.
class MyActivity extends Activity {
private static AsyncTask myTask = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.textview);
if (myTask == null) {
new myAsync(textView).execute();
} else if(myTask.getStatus() != AsyncTask.Status.FINISHED) {
myTask.set(textView);
}
}
private class myAsync extends AsyncTask<Void, String, Void>
{
TextView textView;
myAsync(TextView textView) {
this.textView = textView;
}
synchronized void setTextView(TextView textView) {
this.textView = textView;
}
...
}
}
You would still have to deal with race conditions. E.g. you would probably want to impelemnt a mechanism to pause/resume your task, whenever the activity pauses/resumes.
You'd also have to make sure that the tasks textView is still valid and that you cleanup your static task in onPostExecute.
You can use the concept of bundle to put some string in it. When the activity is recreated after rotation check if saved instance state is null or not in the oncreate method. If not null retrieve the string using the bundle and update the textview. For more information on this rotation thing check out the videos of slidenerd on YouTube in the asynctask and threads playlist. Hope it helps.

Saving data across rotation does not seem to work in my android project

PLESAE NOTE: The solution to my problem is in bold text at the bottom. I accepted Melquiades's answer because he helped me filter out everything that could have been the problem. It turns out, I was the problem, not android or anything else. So if you are looking for the answer, read below.
I'm trying to save the state of a variable as it is before onPause(); , onStop(); , onDestroy(); are called.
The book I am using has me override a method called
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt(KEY_INDEX, myIntVaraible);
}
the variables you see in the parameter are declared at the beginning of the class
private static final String KEY_INDEX = "index";
private int myIntVariable;
with this method created, the book tells me to then go the the onCreate method and add
if(savedInstanceState != null){
myIntVariable = savedIntanceState.getInt(KEY_INDEX, 0);
}
But this does not work.
Whenever the activity is destroyed and created, the myIntVariable is reset to 0.
What I did to fix this is I went to my manifest file and
added android:configChanges="orientation|screenSize".
However, I have read that this is not practical and is strongly advised against.
EDIT: As suggested, I am adding my onCreate(); and onResume(); methods..
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setContentView(R.layout.activity_main);
iterateQuestions();
mTrueButton = (Button)findViewById(R.id.trueBt);
mTrueButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
correctPressed = true;
checkForTrue();
}
});
mFalseButton = (Button)findViewById(R.id.falseBt);
mFalseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
falsePressed = false;
checkForFalse();
}
});
mNextButton = (ImageButton)findViewById(R.id.nextBt);
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
try{
mIndexCounter++;
mTextViewQuestion = (TextView)findViewById(R.id.text_question_view);
int QuestionToShow = mQuestionBank[mIndexCounter].getQuestion();
mTextViewQuestion.setText(QuestionToShow);
}
catch(Exception e){
iterateQuestions();
}
}
});
mTextViewQuestion = (TextView)findViewById(R.id.text_question_view);
mTextViewQuestion.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
try{
mIndexCounter++;
mTextViewQuestion = (TextView)findViewById(R.id.text_question_view);
int QuestionToShow = mQuestionBank[mIndexCounter].getQuestion();
mTextViewQuestion.setText(QuestionToShow);
}
catch(Exception e){
iterateQuestions();
}
}
});
mPrevButton = (ImageButton)findViewById(R.id.prevBtn);
mPrevButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
try{
mIndexCounter--;
mTextViewQuestion = (TextView)findViewById(R.id.text_question_view);
int QuestionToShow = mQuestionBank[mIndexCounter].getQuestion();
mTextViewQuestion.setText(QuestionToShow);
}catch(Exception e){
iterateQuestionsReverse();
}
}
});
}
and
#Override
public void onResume(){
super.onResume();
Log.d(TAG,"onResume()");
}
For all intents and purposes, the variable mIndexCounter is the "myIntVariable" I mentioned.
SOLUTION: I was using a book and unfortunately, since I am new to android programming, relied too much on the code written in the book. The authors usually add new code in their book as bold, black text. This time, they failed to do that and I had trouble figuring out why my data was not being saved. It turns out that it was saved all along, I just failed to update the view with the saved data whenever it was retrieved. After adding 3 lines of simple code, my mistake was obvious and the goal I had been trying to accomplish, a success.
My program displayed a string of text that was dependant on an int that was used to retrieve information from the R.java class. After launching the app, when the user presses Next, the data changes because the int is incremented and the String on the view changes.
This data was to be saved due to the nature of android destroying any unsaved data upon orientation change.
All I had to do was simply add the saved data, an int, the same way I used to display this string/text in the first place. Instead, I foolishly assumed it would do it automatically because the book did not add this code and I relied on it too much.
This was a great learning experience and if anyone ever comes across something like this, feel free to email me if my answer is not clear.
Instead of in onCreate(), restore your variable in onRestoreInstanceState():
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
myIntVariable = savedIntanceState.getInt(KEY_INDEX, 0);
}
The docs also say:
Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity.
Btw, change your onCreate() signature to:
#Override
protected void onCreate(Bundle savedInstanceState) {
as in the docs.
Try this:
android:configChanges="keyboard|keyboardHidden|orientation"
As stated here

CharSequence Restarts After Orientation Change

I have a CharSequence which displays a sequence of text after each imageview click however the CharSequence seems to restart if the orientation is changed mid sequence.
Does anyone know how this can be resolved?
On an orientation change the activity is restarted, and the inCreate() is called again. You have to take that in consideration.
A small example of how to store and retrieve a value:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
isStarted = savedInstanceState.getBoolean("isStarted");
}
}
#Override
protected void onResume() {
isStarted = true;
super.onResume();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("isStarted", isStarted);
super.onSaveInstanceState(outState);
}
For more information and methods: Saving Android Activity state using Save Instance State
using android:configChanges="orientation|keyboardHidden|screenSize"> resolved the issue

Android onsaveinstancestate()

so i get the main idea of how to use
protected void onSaveInstanceState (Bundle outState)
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
also from Saving Android Activity state using Save Instance State
but my problem is what if this was the first time the application is being created? then nothing would have been stored in the bundle before....and if so then when i try to call something out from the bundle that hasn't been saved before what do i get?null?
for example
i have this in my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String [] b=savedInstanceState.getStringArray("MyArray");
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
String [] a={"haha"};
savedInstanceState.putStringArray("MyArray", a);
}
in the FIRST time the application is ever opened what would the value of b be?
and after the application has been used once what would the value of b be?
Many thanks!
in your onCreate()
add a condition
if(savedInstanceState==null){
//meaning no data has been saved yet or this is your first time to run the activity. Most likely you initialize data here.
}else{
String [] b=savedInstanceState.getStringArray("MyArray");
}
by the way to retrieve data that was saved in your onSaveInstanceState you will override this
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
}
You have to check for null always in the onCreate() or in onRestoreInstanceState() like below:
String [] b = new String[arraysize];
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
b = savedInstanceState.getStringArray("MyArray");
// Do here for resetting your values which means state before the changes occured.
}
else{
default..
}
Here you do general things.
}

Categories