Here is the use case:
1. User logs into the app and presses the hardware home button and app is sent to background
2. I run a handler in the background to check if the inactivity time out is 5 mins. Then I need to call the logout API and start the loginactivity, Without launching or bringing the app to foreground
Here is what I have tried
if (!mIsAppInForeground) {
Log.d("App in background", "App in background and timing out");
activity.startService(new Intent(activity,LogOutBackGroundService.class).addFlags( Intent.FLAG_ACTIVITY_MULTIPLE_TASK ));
}
public class LogOutBackGroundService extends Service {
public static final String HAS_SIGNED_OUT = "hasSignedOut";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent.putExtra(HAS_SIGNED_OUT, true);
startActivity(new Intent(this, LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
The app is timing out properly and login activity is being launched, but the app is being brought to foreground (i.e app is being launched). I want this to happen in the background only. Only when the user relaunches the app, he should see the login screen again
startactivity(intent) pops up the backstack activity or creates a new one if it doesn't exist.. so your solution is there is onResume() and onPause().. onPause() is called when you the activity is gone, onResume() is called when you see the activity, so my advice to you is create a boolean, it can be in a singleton class
public class MySingletonClass {
public static boolean startloginpage; // by default its false
}
then you in mainactivity or the activity that the user will launch or come back to, put the code in its onresume
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(MySingletonClass.startloginpage){ //check if your boolean is true
// if it checks out then call do what you want to do when the user times run out
}else{
// if it doesn't check out continue without telling user to login,
}
}
in your service remove the intent code and put this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent.putExtra(HAS_SIGNED_OUT, true);
MySingletonClass.startloginpage = true;
return START_NOT_STICKY;
}
In a typical logout scenario , clicking on logout button should just start the login activity clearing the login details. In your case after 5 mins you should try to clear the stored token for login ( assuming you store the login details for the user to login automatically when required). When the user launches the app next time your LAUNCHER activity would check for the stored token to launch the required activity.
Related
I need to do a logout after some time, so I'm opening the login window in my app using.
startActivity(intent);
Problem is that, if the user has my app in the background, my activity will pop up.
Is there a way to easily open an activity but keep my app in the background?
It can be done with Android appliaction component Service.
you can read about it in official documentation by links below.
https://developer.android.com/training/run-background-service/create-service#java
https://developer.android.com/guide/components/services?hl=en
Initialize your Service
public class MyBackgroundService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
//onCreate - Service created
}
#Override
public void onDestroy() {
//onDestroy - Service destroyed (Stopped)
}
#Override
public void onStart(Intent intent, int startid) {
//onStart - Service started
}
}
Then call Service in your Main Activity
startService(new Intent(this, MyBackgroundService.class));
And don't forget about declare in Manifest.
<service android:enabled="true"
android:name=".MyBackgroundService" />
You can implement "local logout" after some time and when user returns to activity you can detect it. More: https://developer.android.com/guide/components/activities/activity-lifecycle
My app uses a Service for background tasks. I want the Service to keep running when user kills the app(swipes it away). There are two scenario's in which the user kan kill the app:
Scenario 1: When in app:
1 User presses **backbutton**, apps goes to background and user is on the homescreen.
2 User presses the multitasking button and swips the app away.
3 The Service should restart because its sticky.
Scenario 2: When in app:
1 User presses **homebutton**, apps goes to background and user is on the homescreen.
2 User presses the multitasking button and swips the app away.
3 The Service should restart because its sticky.
Scenario 1 works exactly as expected. The Service restarts after the app is swiped away in a matter of seconds.
Scenario 2 does not work as expected. The service does get restarted but after more than 5 minutes.
I don't understand why it takes so long to restart the service in scenario 2. Is there a known solution to this?
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent test = new Intent(this, TestService.class);
startService(test);
}
}
public class TestService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Service", "Service is restarted!");//In Scenario 2, it takes more than 5 minutes to print this.
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
When you press the back button, you are essentially destroying the activity which means the onDestroy() is called where you stop() the STICKY_SERVICE. Hence the STICKY_SERVICE boots up again immediately.
When you press the home button, you are pausing the activity (onPause()), essentially putting it in background. The activity is only destroyed when the OS decides to GC it. It is only at that point of time that the onDestroy() is called at which you stop() the service and STICKY_SERVICE boots up again.
Hope this helps.
I am building an application using PhoneGap, which revolves around a timer I have created. I am struggling at the moment as I need a way of having the app open itself if the timer reaches zero. I have currently put in place a notification for when the timer runs out, and the user can launch the app from there. However I need a way of launching the app if the user "misses" the notification or something similar.
For example, when the timer on the local "timer" app on a mobile device runs out, it will open itself to notify the user that the time has ran out.
Any suggestion would be appreciated,
Thanks.
Just write the code for opening the launcher Activity instead of showing notification in your service class.When the timer runs out the launcher activity will start instead of notification.
the code will look similar to this:
public class AlarmService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//calling Launcher Activity
Intent alarmIntent = new Intent(getBaseContext(), AlarmScreen.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.putExtras(intent);
getApplication().startActivity(LauncherActivity.class);
AlarmManagerHelper.setAlarms(this);
return super.onStartCommand(intent, flags, startId);
}
}
I hope you are satisfied with this answer.
I have an activity with two tabs. Clicking on two tabs will change the the fragments below the tabs. While that activity is in front I give out a notification, After that I minimize the app and kill that activity(not force stopping).
My problem is that am not getting call back in onDestroy while the activity is been killed by the user. Now if I click the notification the app will force close and thats because the activity for pending intent is been missing. Why am not getting the call back in onDestroy?
I found solution of that:
Create service:
public class MyService extends Service {
#Override
public final int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public final IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Toast.makeText(getApplicationContext(), "APP KILLED", Toast.LENGTH_LONG).show(); // here your app is killed by user
try {
stopService(new Intent(this, this.getClass()));
} catch (Exception e) {
e.printStackTrace();
}
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
super.onTaskRemoved(rootIntent);
} else{}
}
}
and then start your service when app start:
startService(new Intent(this, MyService.class));
make sure you register service in your AndroidManifest.xml
<service
android:enabled="true"
android:name="yourPackageName.MyService"
android:stopWithTask="false" />
onDestroy is guaranteed to be called when you explicitly call finish().
On the contrary, when you are minimizing your app by pressing Home key onDestroy may well not be called right now. If your app stays in the background for a long time then onDestroy will be called.
For debugging purposes you can enable Settings|Developer Options|Don't save Activities. This way onDestroy will be called immediately when your app goes to background.
It is not sure to get callback in fragment's onDestroy(). When we kill the app Activity's onDestroy() will get the callback and the activity will be killed and fragment may not get callback.
As stated jn the documentation, onDestroy() can't be depended on, it will be called when the OS wants to kill the app, say in low memory conditions. Thus when the user hits the back button or home, onPause() or onStop() are called in place of it. Try implementing your callback in thr onPause() or onStop() method.
I have a service that turn on my app sometimes, the main activity prompt Dialog message to user sometimes,
after the user answer YES\NO I call to finish() to close the app.
my problem is when the message is shown, user answers it and app was call to finish() and when you look in the recent history you played before (in samsung for example you press long on home button) you will see my app along with other apps user started.
when you push it to open it again the Dialog show again..
How to show the activity when launched from recent app without showing the Dialog
public void dialog_1(){
myDialogViewN = new MyDialogViewNegativeTime(MainActivity.this);
// Setting vibrator
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern= {100, 1000};
vibrator.vibrate( pattern,0 );
// Setting 2 Dialog Listeners
myDialogViewN.setOnDialogListener(new DialogListener() {
#Override
public void onNegativeClick()
{
// Stopping Vibraror
if (vibrator.hasVibrator()){
vibrator.cancel();
vibrator = null;
}
initialize_DialogToUser(); /// ??
SendDataToService(3); //doesn't want reminder
myDialogViewN.dismissDialog();
waitForDialogAnswer=false;
finish();
}
#Override
public void onPositiveClick()
{
// Stopping Vibrator
if (vibrator.hasVibrator()){
vibrator.cancel();
vibrator = null;
}
initialize_DialogToUser();
SendDataToService(1); //remind!
myDialogViewN.dismissDialog();
squre.setImageResource(R.drawable.triangle_red2);
waitForDialogAnswer=false;
finish();
} });
myDialogViewN.show();
}
#Override
public void onDestroy()
{
super.onDestroy();
// close/stop running application on background
int id= android.os.Process.myPid();
android.os.Process.killProcess(id);
}
finally i find solution,
the problem was when you open the app from history - the last intent that comes from service to your activity stay there and not goes, in contrary for openning the app by click it's own icon. (different openning ways).
my solution:
send 2 intent's from service to activity,
the first - with what you really need.
the second - after you receive your answer in the service. in the second you will not put any data! it is a mere intent that comes to change the "stuck" intent in history-app open way.
maby it is stupid, but it's the only solution i found :)