Android can we save BufferedReader object in onpause - android

I am new to android. I need some help to work on my app. Basically I am trying to develop a quiz app. I have questions stored in a file. So my app reads each question from the file and displays it on the screen using InputStream and BufferedReader objects.
is = this.getResources().openRawResource(R.raw.sampletest);
br = new BufferedReader(new InputStreamReader(is));
So now when user quits the app in the middle, I want my app to save is and br values(pointing to the question where the app left) and restore them again during the next app run. After doing some browsing, I learned that if we wish to persist the app state between different runs, onPause() is the one for such tasks. But can we save these is and br objects?How to save them in onPause().can someone help me out with a code snippet of saving these objects?
Thank you so much in advance...

No. What you should do is save something simple like the position (question number) and a list of the answers that can be persisted in a bundle in onSaveInstanceState. You can then get these saved values from the Bundle in onCreate.
e.g.
private int position;
private ArrayList<String> answers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
position = savedInstanceState.getInt("position");
answers = savedInstanceState.getStringArrayList("answers");
} else {
answers = new ArrayList<String>();
}
// This should load up the right question.
displayQuestion(position);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("position", position);
outState.putStringArrayList("answers", answers);
}

I guess you should write a code that saves the data into file, and on load parses the data from the saved file and creates the object.
onPause is not helpful here because like you said it is about app exit, so all the memory (and your objects) are lost..
edit:
if you are sure your app continues running in background, try to save the objects outside the activity:
Very rough example:
void onPause(...) {
SomeSingleton.getInstance().setObjects(is, br);
}
void onCreate(...) {
is = SomeSingleton.getInstance().getIs();
br = SomeSingleton.getInstance().getBr();
}

Related

How to save multiple values to a single variable through an activity.

I am creating an application in which I scan a number of bar codes and keep extracting their values and clubbing them in a single place. As simple as this sounds I have been unable to create either an array in which I keep storing new values or a string where I keep concatenating them.
Please comment in case someone needs more code or explanation, I understand the question might not be very rich in either.
EDIT :
public class example
{
String val;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try
{
String list_id=ToolList3.ID;
String list_qty=ToolScanDet3.qty;
// val is returned from the barcode scanning app.
val=val+issue_id+"~"+issue_qty+";";
Log.d("Tools issued till yet...", val);
/* Club all the tool IDs together and fire a single query to issue
them all against one name. */
Intent i=new Intent(Issue.this,Issue1.class);
startActivity(i);
//Issue1 again returns a pair of id and qty which needs to be saved along with the previous set of values.
}
I am basically having trouble trying to save the returned set of values along with the previous ones, the new ones that are returned wipe out the previous values. I tried putting them in an array too but that requires a counter which again defeats the purpose because the counter will be initialized to zero and start over again.
Unless the number of elements is known and constant, it is preferred to use ArrayList instead of array. In the case when you want to keep the data when the activity is destroyed caused by orientation change, you can save them in onSavedInstanceState :
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("temp", tempString);
}
Then retrieve it back in onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
your_arraylist = savedInstanceState.getString("temp");
}
EDIT:
According to what you want, the Scan activity should not initialize any string. It should obtain the string value which is passed to it by the main instead:
public class ScanActivity extends Activity {
String tempString;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
tempString = getIntent().getStringExtra("temp");
} else {
// orientation change
tempString = saveInstanceState.getString("temp");
}
}
Once you have finished the scan, do
Intent output = new Intent();
output.putExtra("temp", tempString);
setResult(RESULT_OK, output);
finish();
to send back the string to your Main activity.
I could not find any solution that was feasible to my situation and thats why I had to create a local database using SQL Lite. Pushing values to the database each time needed and then retrieving the values after my work flow was over.
Comment in case anyone needs help with the creation of a local database using SQL Lite. Happy to help :)

android don't restart thread when orientation changes

my apps was based on this code http://www.41post.com/4588/programming/android-coding-a-loading-screen-part-1 .on the doInBackground my app will connect to the internet and download some data and populate the database and it will usually take some time to complete. the problem is when the orientation changes, the doInBackground function is restarted and it will cause problems.
I referred http://developer.android.com/guide/topics/resources/runtime-changes.html and it says to do something like
#Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {
data = loadMyData();
}
...
}
but on my apps, I don't know what should I put under the onRetainNonConfigurationInstance() because as you can see from the codes at http://www.41post.com/4588/programming/android-coding-a-loading-screen-part-1 I called a class instead of functions..

Saving string on orientation change FC's app if changed too quickly

I'm having trouble saving a string on orientation changed. I've tried using onSaveInstanceState()/onRestoreInstanceState() and onRetainNonConfigurationInstance()/getLastNonConfigurationInstance() with no luck.
I have:
#Override
public String onRetainNonConfigurationInstance(){
final String savedType = currentType;
return savedType;
}
and in onCreate() I have:
currentType = (String) getLastNonConfigurationInstance();
This hasn't worked for me yet and currentType is always null after an orientation change. Any suggestions?
Revision
So this is what I currently have and it's still not working:
#Override
protected void onSaveInstanceState(Bundle outState){
outState.putString("savedType", currentType);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
currentType = savedInstanceState.getString("savedType");
super.onRestoreInstanceState(savedInstanceState);
}
I've tried putting the super method calls at the beginning and end of each method in every combination I could think of but am still getting a NullPointerException for currentType when the view is created again.
Also
This is happening in a Dialog, I'm not sure if that has anything to do with it but thought that might be a useful bit of info.
Partial Solution/Partial New Question
So I got this working somewhat like I wanted. There was a statement buried in a method that set currentType to null towards the end of the life cycle when the variable wouldn't be needed again. That's now out of the way. The screen will successfully change orientations but if it's changed between the two successively too quickly it will FC. This is what I used to get it working in this state:
Class Field:
private String currentType;
At the end of onCreate I have:
currentType = (String) getLastNonConfigurationInstance();
And then:
#Override
public Object onRetainNonConfigurationInstance() {
final String s = currentType;
return s;
}
It works fine if the orientation doesn't change and then change back again quickly. I'd like to fix this though because department and retail stores are using/will use this and I can see people dropping it, which will cause an FC (dropped it on my couch to test). I'm only storing one string so what I'm storing doesn't take up much memory. Any suggestions for this new situation?
Have you tried putting it in a Bundle?
private static final String CURRENT_TYPE = "currentType";
private static final String DEFAULT_TYPE = "defaultType";
#Override
protected void onSaveInstanceState (Bundle outState) {
outState.putString(CURRENT_TYPE, currentType);
super.onSaveInstanceState(outState);
}
#Override
protected void onCreate (Bundle savedInstanceState) {
...
currentType = (savedInstanceState == null)? null :
savedInstanceState.getString(CURRENT_TYPE, DEFAULT_TYPE);
...
}
So I got this working somewhat like I wanted. There was a statement buried in a method that set currentType to null towards the end of the life cycle when the variable wouldn't be needed again. That's now out of the way. The screen will successfully change orientations but if it's changed between the two successively too quickly it will FC. This is what I used to get it working in this state:
Class Field:
private String currentType;
At the end of onCreate I have:
currentType = (String) getLastNonConfigurationInstance();
And then:
#Override
public Object onRetainNonConfigurationInstance() {
final String s = currentType;
return s;
}
It works fine if the orientation doesn't change and then change back again quickly. Asking new question about this new bug,

Android - persisting activity instance

I am using instances of two activies (A and B) among my application. Now I am facing problem of persisting each of them. When I use sharedpreferences, I can get only to persisting A.class and B.class with SharedPreferences, but when I use instance A again. It's persistent state in SharedPreferences is overriden. I think, I should use Bundle wtih onSavedInstanceState and onRestoredInstanceState. But how to pass saved Bundle into onCreate()? Goal is to be able to persist activity instances.
Thanks
When launching activity A. You can use intent.putExtra( String name, Bundle value ) to pass the bundle to your activity and then in Activity A's onCreate use getIntent.getBundleExtra( String name ) to get your bundle again.
You need to consider what state you need to persist.
For example;
which checkboxes have been ticked?
what level is the user on?
what is the position of their cursor
As an example,
I just finished an application where a user can view different levels of flashcards.
I care about;
which level of flashcard they are looking at (maybe they're at level 2)
which card are they looking at (maybe they're on the 4th card)
Here's the code.
// a variable to store the level
private final static String CARD_LEVEL_STATE = "currentCardLevel";
// a variable to store the current card
private final static String CURRENT_CARD_STATE = "currentCardNumber";
#Override
protected void onSaveInstanceState(Bundle outState) {
// save the level
outState.putInt(CARD_LEVEL_STATE, flashCardList.currentLevel());
// save the current card
outState.putInt(CURRENT_CARD_STATE, flashCardList.currentCardNumber());
// do the default stuff
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// ignore if we have no saved state
if (savedInstanceState != null) {
// record the level
if (savedInstanceState.containsKey(CARD_LEVEL_STATE)) {
int currentCardLevel = savedInstanceState.getInt(CARD_LEVEL_STATE);
flashCardList.setCardLevel(currentCardLevel);
}
// recover the current card
if (savedInstanceState.containsKey(CURRENT_CARD_STATE)) {
int currentCardNumber = savedInstanceState.getInt(CURRENT_CARD_STATE);
flashCardList.setCurrentCardNumber(currentCardNumber);
}
// refresh the view
refreshCard();
}
super.onRestoreInstanceState(savedInstanceState);
};

How to use onSavedInstanceState example please

I'm confused when it comes down to saving a state. So I know that onSaveInstanceState(Bundle) is called when the activity is about to be destroyed. But how do you store your information in it and bring it back to its original state in onCreate(Bundle savedInstanceState)? I don't understand how this bundle will restore information. It would be helpful if someone can provide an example.
The Dev guide doesn't do a good job of explaining this.
public class Conversation extends Activity {
private ProgressDialog progDialog;
int typeBar;
TextView text1;
EditText edit;
Button respond;
private String name;
private String textAtView;
private String savedName;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.dorothydialog);
text1 = (TextView)findViewById(R.id.dialog);
edit = (EditText)findViewById(R.id.repsond);
respond = (Button)findViewById(R.id.button01);
if(savedInstanceState != null){
savedInstanceState.get(savedName);
text1.setText(savedName);
}
else{
text1.setText("Hello! What is your name?");
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = edit.getText().toString();
text1.setText("Nice to meet you "+ name);
}
});
}
}
#Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putString(savedName, name);
}
}
The Bundle is a container for all the information you want to save. You use the put* functions to insert data into it. Here's a short list (there are more) of put functions you can use to store data in the Bundle.
putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)
In your onCreate function, this Bundle is handed back to the program. The best way to check if the application is being reloaded, or started for the first time is:
if (savedInstanceState != null) {
// Then the application is being reloaded
}
To get the data back out, use the get* functions just like the put* functions. The data is stored as a name-value pair. This is like a hashmap. You provide a key and the value, then when you want the value back, you give the key and the function gets the value. Here's a short example.
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("message", "This is my message to be reloaded");
super.onSaveInstanceState(outState);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String message = savedInstanceState.getString("message");
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
Your saved message will be toasted to the screen.
One major note that all new Android developers should know is that any information in Widgets (TextView, Buttons, etc.) will be persisted automatically by Android as long as you assign an ID to them. So that means most of the UI state is taken care of without issue. Only when you need to store other data does this become an issue.
From Android Docs:
The only work required by you is to
provide a unique ID (with the
android:id attribute) for each widget
you want to save its state. If a
widget does not have an ID, then it
cannot save its state
A good information: you don't need to check whether the Bundle object is null into the onCreate() method. Use the onRestoreInstanceState() method, which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null
Store information:
static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
If you don't want to restore information in your onCreate-Method:
Here are the examples: Recreating an Activity
Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}
Basically onSaveInstanceState(Bundle outBundle) will give you a bundle.
When you look at the Bundle class, you will see that you can put lots of different stuff inside it. At the next call of onCreate(), you just get that Bundle back as an argument.
Then you can read your values again and restore your activity.
Lets say you have an activity with an EditText. The user wrote some text inside it.
After that the system calls your onSaveInstanceState().
You read the text from the EditText and write it into the Bundle via Bundle.putString("edit_text_value", theValue).
Now onCreate is called. You check if the supplied bundle is not null. If thats the case,
you can restore your value via Bundle.getString("edit_text_value") and put it back into your EditText.
This is for extra information.
Imagine this scenario
ActivityA launch ActivityB.
ActivityB launch a new ActivityAPrime by
Intent intent = new Intent(getApplicationContext(), ActivityA.class);
startActivity(intent);
ActivityAPrime has no relationship with ActivityA.
In this case the Bundle in ActivityAPrime.onCreate() will be null.
If ActivityA and ActivityAPrime should be the same activity instead of different activities,
ActivityB should call finish() than using startActivity().
If Data Is not Loaded From savedInstanceState use following code.
The problem is url call is not to complete fully so, check if data is loaded then to show the instanceState value.
//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
mAlreadyLoaded = true;
GetStoryData();//Url Call
} else {
if (listArray != null) { //Data Array From JsonArray(ListArray)
System.out.println("LocalData " + listArray);
view.findViewById(R.id.progressBar).setVisibility(View.GONE);
}else{
GetStoryData();//Url Call
}
}

Categories

Resources