Garbage value getting produced in textView - java

I have two activities : lets say A and B
A has a button which opens B using intent concept.
Through B I am saving data in database using SQLite concept.
A is the main activity which has a textView which is showing some value !
code:
Using SharedPreferences to store int value and display in MainActivity A
c=sp.getInt(Salaryflag, 0);
str=Integer.toString(c);
tv.setText(str);
Now I am using some algorithm to calculate sum() in one row in the database a store its value in an int variable
Now in onResume I am using this concept to change the value of the A textView ! :
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
ItemsDataBase xyx=new ItemsDataBase(this);
xyx.open();
int lola;
lola=xyx.getSum();
xyx.close();
c=c-lola;
str=Integer.toString(c);
tv.setText(str);
}
Now what I want is that when I go back from second Acitvity B to A it should immediately show the changes.
But actually It is showing some garbage value and when I restart the app after closing then it shows the desired changes in the textView
How to remove this logical error ?
Garbage value:
After closing the app and reopening it:

You should write c=sp.getInt(Salaryflag, 0); in your on resume too as you are assigning c-lola to c.
When you are restarting the activity, line c=sp.getInt(Salaryflag, 0) is getting executed first so it displaying perfactly.
When you coming from B to A , the onResume() of A gets called so you have to initialize/assign variable c in onResume() as well.

Related

Transfering int between activities does not work correctly

I need to transfer User and int between 2 activities, this happens when clicked on item in listview,
Activity 1:
Intent intent = new Intent(GameActivity.this,ServerActivity.class);
intent.putExtra("serverNum",position);
intent.putExtra("currentUser",currentUser);
Log.d("position", position + "");
startActivity(intent);
finish();
the position is by defult the number of the item that the user clicked on, The log.d shows the currect position indeed, but when I try to get that Int in activity 2 its always 0.
In activity 2:
Log.d("Server Number",getIntent().getExtras().getInt("serverNum")+"");
this log.d always shows 0.
the user transfers well though.
EDIT
I found out it has something to do with android:launchMode="singleTask" in the manifest, for some reason the activity opens twice, one opens well and one for some reason opens with the extra "serverNum" equals to 0, any suggestions on how to fix this?
Try this in your Activity 2.
int id=getIntent().getIntExtra("serverNum", 0);
Log.d("ServerNumber",id+"");
Try overriding method and check value there as well
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
int id=intent.getIntExtra("serverNum", 0);
Log.d("ServerNumber",id+"");
setIntent(intent);
}
You should get rid of android:launchMode="singleTask". The reason is that this creates only one instance of the activity. Once you go back to it, it resets the extra to 0. Here you can read up on launch types: https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en

SharedPreferences String Set data lost after app kill (android emulator)

I am running this on an emulator: 5554:Nexus_5_API_22_x86.
I am trying to learn SharedPreferences and have written a simple test program.
It contains two buttons: one adds a String + random # to a set which will be stored in SharedPreferences, and the other prints the contents of that set.
Whenever I press the square button on the bottom right hand of the screen and press 'x' to close the app window, then relaunch the app, the contents of the set are reset - in other words, printing the set yields nothing.
However, if I exit the app using only the back button, the contents remain - in other words, printing the set yields whatever was in it before.
Java:
...
public class MainActivity extends AppCompatActivity
{
final int PREF_MODE_PRIVATE = 0;
TextView output;
Set<String> testSet;
Random randomGenerator = new Random();
SharedPreferences data;
SharedPreferences.Editor dataEditor;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
output = (TextView) findViewById(R.id.textView); //getting the output textfield
data = getPreferences(PREF_MODE_PRIVATE);
//If first-time setup has not been completed, execute the following block
//I don't want the String Set to be reset to empty every time the app is launched
if(data.getBoolean("initialized", false) == false)
{
//Adding the empty set to storage
testSet = new HashSet<String>();
dataEditor = data.edit();
dataEditor.putStringSet("testSet", testSet); //Add the empty Set to storage
dataEditor.putBoolean("initialized", true); //Set initialized flag to true
dataEditor.apply();
}
}
public void printTestSet(View view)
{
output.setText(""); //Clears the text field
Set<String> toBePrinted = data.getStringSet("testSet", null); //Gets the String Set
//Prints content of the String Set
if(toBePrinted != null)
{
for(String word : toBePrinted)
{
output.append(word + '\n');
}
}
}
public void addToTestSet(View view)
{
//Generate a string followed by a random number and add it to the String Set
int randomInt = randomGenerator.nextInt(1000);
data.getStringSet("testSet", null).add("NEW STRING #" + randomInt);
}
}
The button that prints the String Set calls printTestSet and the one that adds a String to the Set calls addToTestSet.
Upon creation, the app uses a simple boolean to check if it has been initialized the for the first time. If not, it adds an empty String Set to storage and sets the boolean to true. If the boolean is already true (meaning it has already added the empty string set), that step is skipped.
You need to either commit your data either realtime (where you are doing apply) or in application life cycle handler onpause (when your app goes to background). Use option 1 when you have little data or 2 when you have large amount of data to commit.
It looks like you're not saving the shared preferences in addToTestSet.
When you do getStringSet and then add, you need to again save the string Set back into shared prefs like you do in your onCreate() using dataEditor.apply().
Or if you want to be a bit more efficient, you can save your stringSet in the activity's onPause() method to prevent constantly writing to SharedPrefs
When you hit back, your app process isn't being killed, which means when you open it up again the Android system is restoring whatever it can (what was written in textViews, checkboxes that were checked, etc. simple things like that). What you see in the box might not actually be getting populated by SharedPrefs.

wrong number after converting

I try to send position of array from my MainActivity to another Activity with this code:
Main Activity:
contactinfo.putExtra("position", String.valueOf(position));
I have a toast and that shows the right position I have clicked in this Activity.
Another Activity that gets the data:
position = getIntent().getExtras().getInt("position");
Toast.makeText(this,String.valueOf(position),Toast.LENGTH_SHORT).show();
This Toast always shows 0, even when I have click on position 1 or another one.
What's the problem with converting int to String or sending an int via Intents?
The problem is that you are sending a String, but trying to retrieve an int.
You don't need to convert your integer to a String to pass it to the next Activity.
Change contactinfo.putExtra("position", String.valueOf(position)); to contactinfo.putExtra("position", position);.
In Main Activity Use :
contactinfo.putExtra("position" , position);
In Another Activity Use :
position=getIntent().getIntExtra("position", 0);

Switching between activities without data loss

I'm working on an app that has two activities.
When I go from one activity to another then return I loss the data.
Imagine:
First activity shows a random number on a text view that changes on a button click
Second activity does nothing it only has a return to the main activity button
*I know this app is worthless but its easier than showing you my large application...
So you have a random number on the textview, I go to the next activity then return to the main activity and the textview loses the number and shows another.
What the question is, is how to return to the activity without lossing the data (random number)?
I dont want to save it on a database or on the sharedprefes since that wouldn't be good when being used in a large app with many data shown...
Thx in advance
Edit:
Code to act1:
//public clas... oncreate...
Onclick(...){
Intent intent = New intent (this, acttwo.class);
StartActivity (intent);
Finish ();
}
Code to act2:
//public clas... oncreate...
Onclick(...){
Intent intent = New intent(this, actone.class);
StartActivity (intent);
Finish ();
}
Your problem cause, because
You are calling finish() in Activity 1 when you starting Activity 2.
So remove finish() from Activity 1. and implement onActivityResult()
Like,
Onclick(...){
Intent intent = New intent (this, acttwo.class);
StartActivityForResult(intent, 0); // Result to ensure about back track of proper activity
}
Now Activity 2 just call finish() no need to call start Activity 1 again as Activity 1 is already in back stack of Application task.
So it should be,
//public clas... oncreate... of acttwo
Onclick(...){
finish(); // We are just finishing Activity 2 not starting Activity 1 again
}
Note:
In future it may happen Android system may kill your Application on Low Memory issue, so better to save your data and state of activity in SharedPreferences or Database.
You need to save your data one way or another. Without using DB or other classical methods(shared preferences) used for saving data in Android, as I see it, you are left with two options:
Pass the data with Intents as extras
Save it using method described in Accepted Answer at Saving Activity state in Android
You could use a static variable in your Activity to hold whatever random number your TextView is meant to hold and set its text to that every onResume() call. Something like;
class MyActivity extends Activity {
private static int randomNumber;
private TextView myTextView;
...
#Override
public void onResume(Bundle b){
super.onResume(b);
myTextView.setText(randomNumber);
}
}
Your TextView should persist the number that you had before. If you were setting these values in the onResume() method, then they would change every time the activity resumes. If you terminate your activity with a call to finish (while calling B) and then start a new activity A again (from B), then it will show a random number
If you have to do either of the methods I mentioned, you can add the values you want to persist in an intent as an extra, pass this to the second activity and then pass it back like so:
// Start activity B and pass the value you want to save in there
Intent A = new Intent(this, ActivityB.class);
A.putExtra("value", number);
// Start activity A from B and pass the value you saved in there
Intent B = new Intent(this, ActivityA.class);
B.putExtra("value", getIntent().getExtra("value");
Then retrieve number and set the TextView in your onResume (or onCreate if you are starting a fresh activity. But in this case do a check to see if the intent starting this activity has an extra named value - if yes, then display it else generate a new random number).

Counting how many times my Android app has been opened

I am developing an android app and I want to know how many times it has been opened. Is there a way to do this?
The problem with using onCreate in an Activity is that this will increment the counter even on orientation changes. Using onCreate in an Application also has a downside in that your counter will only be incremented when after the VM has closed - so even if the app exits and reopens this will not necessarily increment.
The truth is there is no fool-proof method for handling this sort of count, however I have come up with a very good way of doing this, that is about as close to 100% accurate as possible. It requires work in both an Application class and your main Activity class, and relies on timestamps to differentiate between orientation changes and actual app launches. To start, add the following Application class:
/**
* Application class used for correctly counting the number of times an app has been opened.
* #author Phil Brown
* #see Stack Overflow
*
*/
public class CounterApplication extends Application
{
private long lastConfigChange;
/** #param buffer the number of milliseconds required after an orientation change to still be considered the same event*/
public boolean wasLastConfigChangeRecent(int buffer)
{
return (new Date().getTime() - lastConfigChange <= buffer);
}
#Override
public void onCreate()
{
lastConfigChange = new Date().getTime();
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
lastConfigChange = new Date().getTime();
}
}
You should add this Application to your AndroidManifest.xml by specifying the name application attribute:
android:name="path.to.CounterApplication"
Now, in your main Activity, add the following in onCreate:
//note that you can use getPreferences(MODE_PRIVATE), but this is easier to use from Fragments.
SharedPreferences prefs = getSharedPreferences(getPackageName(), MODE_PRIVATE);
int appOpenedCount = prefs.getInt("app_opened_count", 1);
if (!((CounterApplication) getApplication()).wasLastConfigChangeRecent(10000))//within 10 seconds - a huge buffer
{
appOpenedCount += 1;
prefs.edit().putInt("app_opened_count", appOpenedCount).commit();
}
//now say you want to do something every 10th time they open the app:
boolean shouldDoThing = (appOpenedCount % 10 == 0);
if (shouldDoThing)
{
doThing();
appOpenedCount += 1;
//this ensures that the thing does not happen again on an orientation change.
prefs.edit().putInt("app_opened_count", appOpenedCount).commit();
}
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 eg.:
System.out.println("Total Application counter Reach to :"+totalCount);
In your Application or Activity's onCreate() method, increment a counter stored in persistent storage such as SharedPreferences.
You can use shared preferences. Every time the app is opened, retrieve the preferences, increment the count, then store it right away. The only issue is that if a user deletes the app along with all preferences, then the count will be erased too. Here is an example of committing to the preferences. Use getPreferences to retrieve them at the startup of the app.
SharedPreferences prefs=getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor=prefs.edit();
editor.putString("pref 1", "some text");
editor.commit();
1. For a simple approach, keep a text file where you increment the value by 1, after reading it. Keep the count increment on OnCreate() method of Activity
2. You can use SharedPreference.
3. Well DataBase can also be used...but i think that too over-kill for this....
One way:
Keep a property in preferences and on launching activity update preference count by '1', but you may not be able to see this increased value because it stays on phone.
Otherway
Call a service to your server (if you have any) to increment the visit count.
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 onFinishing() 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(!onFinishing()){
c = mPref.getInt("numRun",0);
c--;
mPref.edit().putInt("numRun",c).commit();
}
//Other pause stuff.
}
As I have said in another answer, I think the following is the best solution:
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 && valueOfCountModified){
//Do whatever you want
}
}
If we remember the definition of a static variable, we will discover that is perfect for us:
They are associated with the class, rather than with any object. Every instance of the class shares a class variable.
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.

Categories

Resources