Is there any way to know in "real-time", via broadcast I guess, when a user has cleared data of the app?
I have a widget showing some user details, which are stored in the Preferences, but when the user clear the app data, I am not able to know it until the next refresh/update (the onUpdate() call) which is every 30min.
During that time, the widget is showing useless values. So I need to trigger somehow any broadcast to capture it from a receiver and update the widget when that happens.
Is that possible?
Looks like there is no way to get an event for that. The app's process should be terminated after clearing data. https://stackoverflow.com/a/10701338/450243
You can use a service that implements a http://developer.android.com/reference/java/util/prefs/PreferenceChangeListener.html to monitor when your preferences change.
Even if the service is killed by the system, if you use START_STICKY it will be brought to live, and you'll be able to determine if your keys are available or has been deleted. I've used this approach in a couple of apps and it works like a charm.
If you want to make even more efficient, you can add a receiver for screen on/off, so you can start your service only when the screen starts and terminate your service when the screen gets on.
Hope it helps.
You can also have a look at this solution, you will not exactly get a callback but you will get a fighting chance to update your widget before clearing the data
android:manageSpaceActivity=".path.to.MyActivity"
This will replace the button "Clear Data" from the settings to "Manage Space". Now you can redirect the user to a custom activity that is controlled by you.
The launch of the activity will act as callback for you. Manipulate your data in your activity and use the following code
private void clearPreferences() {
try {
// clearing app data
Runtime runtime = Runtime.getRuntime();
runtime.exec("pm clear YOUR_APP_PACKAGE_GOES HERE");
} catch (Exception e) {
e.printStackTrace();
}
}
to clear the app data.
Related
The problem is only when my activity already shown it begins updates and it look no good. How it works: in onStart of activity I send cmd to service to get update data, also I register brodcast listener there. I want to prepare received data from service to show before activity appears. How to do that? Thanks.
How it works now: when I back from another activity first I see old data and then it changes (very fast but you can see it) to new.
if you want to setup things before your activity is shown you need to do things in the onCreate method instead of onStart method.
further informations in android documentation
When you send the command to the service to update your data, you should change the views in your Activity to show loading indicators, or a blank view, or whatever you want the user to see until the Broadcast comes in that your new data is ready. Then you shouldn't need to worry about old data being visible.
On Android, I'm trying to catch the event where my app comes back to the foreground from the background. In other words, the app was active, then the user minimized it (by clicking the home button or starting another app or something), and then the user runs the app again.
I can add the onRestart() method to an activity as follows:
#Override
public void onRestart() {
super.onRestart();
Log.d("MAIN", "onRestart called.");
}
But this only works when that specific activity is the active one when the user minimizes the app.
Is there a way to catch this for the whole app somehow? Or do I need to add onRestart to every single activity I have? (I suppose I could create a superclass on which all the other activities are based).
Thanks!
Is there a way to catch this for the whole app somehow?
No, because there is no concept of an app "restarting".
Or do I need to add onRestart to every single activity I have?
Presumably. Or, find a way to avoid needing to "catch the event where [your] app comes back to the foreground from the background".
I think the method you need is void onResume()
here is there android developers page for activities , check the "Implementing the lifecycle callbacks" part of the page .
http://developer.android.com/guide/components/activities.html
hope this helps.
I have the following script that monitors the android back button actions -
document.addEventListener("backbutton", backKeyDown, true);
function backKeyDown() {
if($.mobile.activePage.is('#homepage')){
setTimeout( function() {navigator.app.exitApp();}, 100 );
}
else {
setTimeout( function() {$.mobile.changePage("#homepage");}, 100 );
}
}
I would like to also close the app when the physical home button is pressed - does anyone know how to detect this?
Cheers
Paul
You can't do that but you can kill your app in onPause() method instead see more here
EDIT:
Doing that in onPause will get your app killed whenever the user leaves the activity, I am not sure if there is a way to do what you want in android though, also is not recommended!
You can create some complex broadcast messaging system that sends messages from your activities to the application instance at a given interval of time and if you don't get any message in the application instance for x seconds then you know that the app is in background..
You can do that using a base activity class that sends messages at x seconds until onPause is called and extend that activity in all the other activities that you use so you can have this behaviour.
This is for sure not the best option that is out there and will consume battery life depending on the implementation so you have to be really sure that you need this before implementing such thing.
Capturing the Hardware's Home key event is bad approach and Android will never allow you to do that. and for closing the app, android framework will automatically send your app to background so you don't need to care about closing your app on Home button pressed event.
I agree with Adil.. but if you really want to or need to exit your app, adding the same listener/function for PhoneGap's "pause" event would probably do the trick.
At the moment I'm a little bit confused about the lifecycle management in Android. There are at least 4 possibilities to resume retained data after an Activity comes back to the foreground:
Android handling: If there is enough memory, Android stores and resumes the important data (checked radio buttons, text of EditText,-... and so on) after Activity restart, the user has the same state as before as the Activity went into background.
onPause, onResume: Overriding onPause and save the important data to a database or text file and resume it when onResume is executed next time.
onSavedInstance(Bundle), onRestoreInstance(Bundle): I can save the data as key-value-pair into bundles and restore them after onRestoreInstance is executed.
onRetainNonConfigurationInstance(), getLastNonConfigurationInstance(): I handle all my storage issues in one big object and read getLastNonConfigurationInstance() out when onCreate is executed.
Although it is confusing which approach is best, I guess it relies on development experience to know when to use which possibility. If you have some good examples for each I would be glad, but this is not my question. I wonder how to deal with all that when I have different Activities and one Activity will be killed by Android when it pauses in background:
In my case I have a MainActivity and a MessageActivity. The MessageActivity consists of a ViewSwitcher which consists of two states. State one is a radio button choice list. State two is an EditText with two buttons (send and abort). When I monkey test each state, hit the Android home button, and restart the application, the right Activity with the right state and the old data comes into foreground, when I leave the handling to Android. So that works.
But what happens when Android destroys the MessageActivity in background:
If I use the Android way, the data is lost and I guess MainActivity (instead of MessageActivity->state(1 or 2)) will start next time after I relaunch the application (is that correct?). So when I'd like to keep the data of MessageActivity, I have to use one of the other three possibilities.
How to do that neatly, when the application entry point (so the MainActivity) differs from the last active Activity. The problem is that I have to resume a special Activity with a special state of ViewSwitcher. I could start MessageActivity out of MainActivity with startActivity(Intent) in onStart() or onResume() method (because MainActivity is probably the entry point) but then I run into a lot of logical problems in Lifecycle management. Due to this fact I don't think that this is the right way to do that.
But, what's the right and best way to do that?
I guess MainActivity (instead of MessageActivity->state(1 or 2)) will start next time after I relaunch the application (is that correct?)
No, I don't believe this is correct, depending on what your code does in onCreate(). It certainly doesn't need to be correct if you go about things the right way. A simple way to test this is to rotate your screen, which recreates the running activities, unless you have overridden the default configuration change behaviour.
I recommend reading this section in the android docs carefully:
http://developer.android.com/guide/topics/fundamentals/activities.html#SavingActivityState
In particular:
even if you do nothing and do not implement onSaveInstanceState(), some of the activity state is restored by the Activity class's default implementation of onSaveInstanceState(). Specifically, the default implementation calls onSaveInstanceState() for every View in the layout, which allows each view to provide information about itself that should be saved. Almost every widget in the Android framework implements this method as appropriate, such that any visible changes to the UI are automatically saved and restored when your activity is recreated. For example, the EditText widget saves any text entered by the user and the CheckBox widget saves whether it's checked or not. 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.
What this means is, that so long as you don't force any UI state in any onCreate() calls, your activity stack and UI state will be restored.
Personally, my preferred approach is to keep as little state as possible in member variables of my activities, saving and restoring it with onSave/RestoreInstanceState(), and relying on the default implementations to save the rest of the UI state (text box contents, etc). Data that should persist between sessions I commit straight to my DB or preferences as soon as it's changed (e.g. in the on-click handler). This means I don't need to worry about the activity lifecycle for that. As much as possible, my UI just presents a view of the data in my DB (using CursorAdapter etc.).
Edit:
Regarding restoration of the whole activity stack:
When the user leaves a task by pressing the HOME key, ... The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.
(See http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html)
It's not my attempt for a best answer, but it's too long to get in the comments section.
First I will suggest not to rely on the "Android way" - this will result in inconsistent application behavior depending on the free memory of the device - bad practice.
My suggestion is to save your state-dependent data in key-value pairs in SharedPreferences, every time you go into onPause() in your MessageActivity. Store a flag in SharedPreferences, which indicates which was the Activity that was last opened (if you only have two Activities you can easily go 0/1 or true/false flags).
When you re-launch your application, it's normal to start the Activity marked in your AndroidManifest.xml as "entry point". So naturally you'll check the flag in onResume() in your MainActivity and start the other Activity if needed. In MessageActivity's onResume() check the values in SharedPreferences and fill in what's necessary...
If your application is "resumed" to the last Activity in the ActivityStack this will call onResume() in the last Activity in the ActivityStack.
The way I have handled an issue like this in the past, is to have a service running in the background, which handles the flow of information from different activities via either Intents and listeners (preferable, since they are the most easily decoupled solution), or if you are extremely careful, and the only viable solution for some reason is to store the data through direct property access or method calls, you can use static properties/methods on the service class as well. However, I would strongly recommend using the Intent/listener method as it is generally more flexible, thread safe, and decoupled. Additionally, it is wise to make sure that not much is happening at any point in time (in other words, only use this service for Intent handling) when it's not needed, otherwise the Service will tend to hog CPU time as well as RAM, when it's not really needed.
Some resources to look at when it comes to this approach would be IntentService and its related classes, including the superclass, Service. IntentService, however, it is worth noting handles a few more things about async Intent processing, etc that Service does not automatically come with.Hope this helps you!
login.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String name=username.getText().toString();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = settings.edit();
editor.putString("username", name);
if(name.equals("xxx")) {
Intent intent=new Intent(currentactivity.this,nextactivity.class);
intent.putExtras(bundle);
startActivityForResult(intent,0);
}
}
});
I am trying to detect if my app became active from multi-tasking and display a dialog.
The use-case is something like this: User is using the app -> Hits the home button -> Does something -> User taps on the app again
As expected, the last activity the user was on is being shown.
I want to display a dialog when this happens. I used onRestart() for the same and it works. Only problem is, even when the user goes to some activity in the app and then hits back, the dialog is being displayed.
I went through the activity lifecycle several times, but couldn't figure out the solution. Any ideas?
Well, you can tell the foreground application using the technique outlined in Determining the current foreground application from a background task or service: look for getForegroundApp. You could run a timer that checks periodically to see if the app is foreground, and if its not then set a variable after a suitable delay (to make sure you don't happen to hit it in the wrong order when switching Activities). Clear the variable in onStart, and if onCreate of the rooth Activity is ever called you know that the app just became Active.
I achieved this by setting a flag in Shared Preferences in onStop() and cleared it in onDestroy().
Then I overrided the Back button to clear the flag whenever it is pressed. This solves the problem I had stated.
Now in onRestart(), if the flag is true.... I display the dialog.
I know it is not the most elegant solution but does the job! Hope this helps somebody.