I've built an app that has this activities LifeCycle:
StartActivity -> TemplateChooseOptions -> ChooseTemplate -> Templates
and i have a class that has boolean in it. the boolean will change when a server error is occurred.
when the boolean change, i want that all the activities will finish exept for Start Activity.
I've tried this:
new Thread(new Runnable() {
public void run() {
ClientLogic CL = Globals.getInstance().getCL();
while(!CL.isErrStatus());
if(CL.isErrStatus()){
finish();
}
}
}).start();
but it takes too much CPU power.
what can I do?
Don't use a thread, create your own listener and implement it in your activities
public class MainActivity extends Activity implements ServerErrorListener {
#Override
onServerError() {
finish();
}
#Override
protected void onResume() {
if(ClientLogic.getInstance().getCL().isErrStatus) {
// Todo finish
}
ClientLogic.getInstance().addErrorListener(this);
}
#Override
protected void onPause() {
ClientLogic.getInstance().removeListener(this);
super.onPause();
}
}
Or use a BroadcastReceiver as #mubeen says.
Related
In my application i want to sign out to loginActivity after 3 min when user inactive
i am currently use this code to do that but in my application there is more than 20 activities
so without pasting this bunch of code every activity i want common method to do that,
please help me
Here is the my code
public class HomeActivity extends AppCompatActivity {
private Handler handler;
private Runnable r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
handler = new Handler();
r = new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
finish();
Toast.makeText(HomeActivity.this, "Logged out after 3 minutes on inactivity.", Toast.LENGTH_SHORT).show();
}
};
startHandler();
}
public void stopHandler() {
handler.removeCallbacks(r);
}
public void startHandler() {
handler.postDelayed(r, 3 * 60 * 1000);
}
#Override
public void onUserInteraction() {
super.onUserInteraction();
stopHandler();
startHandler();
}
#Override
protected void onPause() {
stopHandler();
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
startHandler();
Log.d("onResume", "onResume_restartActivity");
}
#Override
protected void onDestroy() {
super.onDestroy();
stopHandler();
}
}
Define a class like
public class BaseActivity extends AppCompatActivity {
// Write logic of logout same as what you wrote in HomeActivity
}
Now extend this BaseActivity to each activities which meant to show after login. like
public class HomeActivity extends BaseActivity {
// Remove code related to logout from this class.
}
You can make a BaseActivity Class here you can implement your functionality.
And then extend this activity with all your Activities.
Also you can use Application Class to control over the app
In the onCreate() method of my activity I have a Timer + TimerTask that will schedule a ParseQuery. On The ParseQuery callback, which is on mainThread, I delegate an interface callback to make a simple UI update. This works when I let the Activity unchanged. But if I exit from the activity and enter again it (A new timer will NOT be created here, because it gets created only when starting the activity from a certain point) wouldn't work. I think is something with Activity instances but I cannot handle it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
updateUI(){
Log.i(TAG, "Show changed layout"); //This is always shown, this way I ensure it gets here!!
mTextView.setText(foo); //this doesn't work
mLayout.setVisibility(View.GONE); //this doesn't work
}
The ParseQuery is executed in done() callback method, I call the function that updates the UI:
public class Utils{
.......
doParseQuery(Context ctx, MyListener listener){
.......
query.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e == null){
....
listener.onSuccess();
}
}
});
}
}
What I have tried, with no success:
1. make the `uiTimer` and `uiTask` static global variables; // I thought that maybe it gets leaked into activity instances
2. update the UI using
runOnUiThread(new Runnable() {
#Override
public void run() {}
});
OR
mLayout.post(new Runnable() {
#Override
public void run() {
mLayout.setVisibility(View.GONE);
}
});
3. android:launchMode= "singleInstance" //in Manifest
If you want that your UITimer to gets executed every time your activity goes to foreground, you should implement the onStart or onResume method and move your uiTimer implementation to one of both method. Even your activity being already started these two methods are called after exiting the activity and reopening it again.
A better explanation of Android Activity lifecycle is well explained by google documentation https://developer.android.com/guide/components/activities/activity-lifecycle.html.
Your code would look like this:
#Override
protected void onStart() {
super.onStart();
....
uiTimer = new Timer();
uiTask = new TimerTask() {
#Override
public void run() {
doParseTask();
}
};
uiTimer.schedule(uiTask, shortCodeLeft);
}
doParseTask(){
Utils.doParseQuery(this, new MyListener{
#Override
public void onSuccess() {
updateUI();
}
});
}
When you exit from your activity, the instances mTextView and mLayout will be destroyed.
Then, when you create a new activity, the activity creates new instances of the text view and layout.
Your timer goes off and tries to update the original elements, which are now invalid as the activity has been closed (but the log still works as this is separate to your activity).
You should initialise the timer & task in onCreate(), and then in order to stop updating the old UI elements:
#Override
protected void onStop() {
if (uiTimer != null) {
uiTimer.cancel();
}
super.onStop();
}
Activity.onPause() and onStop() are called in (at least) two situations:
The another Activity was launched on top of the current one.
The app was minimized.
Is there an easy way to tell the difference?
You could do it this way. Make all of your activities extend from a base activity. The base activity needs to keep a visibility counter that is incremented/decremented during onResume/onPause:
public abstract class MyBaseActivity extends ActionBarActivity {
private static int visibility = 0;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
visibility++;
handler.removeCallBacks(pauseAppRunnable);
}
#Override
protected void onPause() {
super.onPause();
visibility--;
handler.removeCallBacks(pauseAppRunnable);
// give a short delay here to account for the overhead of starting
// a new activity. Might have to tune this a bit (not tested).
handler.postDelayed(pauseAppRunnable, 100L);
}
#Override
protected void onDestroy() {
super.onDestroy();
// uncomment this if you want the app to NOT respond to invisibility
// if the user backed out of all open activities.
//handler.removeCallBacks(pauseAppRunnable);
}
private Runnable pauseAppRunnable = new Runnable() {
#Override
public void run() {
if (visibility == 0) {
// do something about it
}
}
};
}
I have a Service which is performing a data update. I have an activity which attaches a listener to the service (via a local binding). The listener receives progress updates. Upon receiving a progress update, it schedules a runnable to be run on the UI thread. Here's the code (updated to show the full listing):
public class MyActivity extends Activity {
static final int UPDATE_DIALOG = 0;
ProgressDialog updateDialog;
private TaskService taskService;
private ServiceConnection taskServiceConnection = new ServiceConnection() {
private final TaskServiceObserver taskServiceObserver = new TaskServiceObserver() {
public void updateProgress(final int progress, final int total) {
runOnUiThread(new Runnable() {
public void run() {
if (updateDialog == null || !updateDialog.isShowing()) {
showDialog(UPDATE_DIALOG);
}
updateDialog.setProgress(progress);
}
});
}
public void updateCompleted() {
runOnUiThread(new Runnable() {
public void run() {
dismissDialog(UPDATE_DIALOG);
startNextActivity();
}
});
}
};
public void onServiceConnected(ComponentName name, IBinder binder) {
taskService = ((LocalBinder) binder).getService();
taskService.addObserver(taskServiceObserver);
}
public void onServiceDisconnected(ComponentName name) {
taskService.removeObserver(taskServiceObserver);
taskService = null;
}
};
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, TaskService.class);
startService(intent);
bindService(intent, taskServiceConnection, Context.BIND_AUTO_CREATE);
}
protected void onStop() {
super.onStop();
if (taskService != null) {
unbindService(taskServiceConnection);
}
}
protected Dialog onCreateDialog(int id) {
switch (id) {
case UPDATE_DIALOG:
updateDialog = new ProgressDialog(this);
updateDialog.setTitle("My App");
updateDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
updateDialog.setMessage("Preparing to run for the first time...");
return updateDialog;
default:
return null;
}
}
}
If I tap the home button while the dialog is showing, then return to the app, I get a crash on the showDialog line. With the debugger I was able to determine that the activity is in the finished state.
What would be an appropriate check to put in my runnable which would determine whether it is safe to call showDialog?
I would personnally dismiss the progress dialog when the activity goes to pause (override onPause) and recreate it if necessary when the activity is resumed (override onResume). You could be leaking memory by keeping references to your activity in other separate objects (your dialog)
You should detach the listener in the onPause method so that since your activity is going into the background, the listener won't fire and try to update the UI.
The solution I ended up going with was to create a flag taskServiceBound which was set to true after binding to the service in onStart and set to false before unbinding from the service in onStop. Because the flag is updated on the UI thread, I can use it to gate the Runnables in updateProgress and updateCompleted. For example:
public void updateCompleted() {
runOnUiThread(new Runnable() {
public void run() {
if (taskServiceBound) {
dismissDialog(UPDATE_DIALOG);
startNextActivity();
}
}
});
}
I have one activity. OnCreate the activity gets the source (html) of a web page to a string and presents the result (after parsing it a bit) in a textview.
I would like the activity to reload/refresh periodically to always present the latest information.
What is the best solution for this?
First of all... separate the updating logic from your onCreate method. So, for instance, you can create an updateHTML().
Then, you can use a Timer in order to update the page periodically:
public class YourActivity extends Activity {
private Timer autoUpdate;
public void onCreate(Bundle b){
super.onCreate(b);
// whatever you have here
}
#Override
public void onResume() {
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
updateHTML();
}
});
}
}, 0, 40000); // updates each 40 secs
}
private void updateHTML(){
// your logic here
}
#Override
public void onPause() {
autoUpdate.cancel();
super.onPause();
}
}
Notice that I'm canceling the updating task on onPause, and that in this case the updateHTML method is executed each 40 secs (40000 milliseconds). Also, make sure you import these two classes: java.util.Timer and java.util.TimerTask.