The question is pretty self explanatory.
I'm doing a class that registers the activity of the user in order to avoid inactivity, after 2 minutes of no activity or everytime the user minimizes the app, the app should close. My code is the one listed below:
public class InActivityTimer extends Activity {
public static final long DISCONNECT_TIMEOUT = 2*60*1000; // 2 min = 2 * 60 * 1000 ms
public static int ESTADO_ACTIVIDAD=0; //Variable para saber si la actividad está al frente o no.
private static Handler disconnectHandler = new Handler(){
public void handleMessage(Message msg) {
}
};
private Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
// Perform any required operation on disconnect
//finish();
finishAffinity();
Intent intent = new Intent(getApplicationContext(),VentanaInactividadCierreAplicacion.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
//intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
};
public void resetDisconnectTimer(){
disconnectHandler.removeCallbacks(disconnectCallback);
disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
}
public void stopDisconnectTimer(){
disconnectHandler.removeCallbacks(disconnectCallback);
}
#Override
public void onUserInteraction(){
resetDisconnectTimer();
}
#Override
public void onResume() {
super.onResume();
ESTADO_ACTIVIDAD ++;
resetDisconnectTimer();
comprobarEstado();
}
private void comprobarEstado() {
if (ESTADO_ACTIVIDAD == 0){
// Intent startMain = new Intent(getApplicationContext(), SplashScreen.class);
// startMain.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
// startActivity(startMain);
// finish();
finishAffinity();
Toast.makeText(getApplicationContext(), "RandomPassGEN cerrado por seguridad", Toast.LENGTH_SHORT).show();}
}
#Override
public void onStop() {
super.onStop();
ESTADO_ACTIVIDAD--;
stopDisconnectTimer();
comprobarEstado();
}
/* #Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(),"La aplicación se reiniciará por seguridad", Toast.LENGTH_SHORT).show();
finishAffinity();
}*/
}
As you can see, I'm using finishaffinty twice. How could I do it withous using that command? I'd like to avoid it because using finishAffinity() needs android +4.1
Thank you so much for your help.
To close your application, do the following:
Intent intent = new Intent(this, MyRootActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("exit", true);
startActivity(intent);
MyRootActivity should be the root activity of your task (this is the one with ACTION=MAIN and CATEGORY=LAUNCHER in the manifest).
In MyRootActivity.onCreate() add the following after super.onCreate():
if (getIntent().hasExtra("exit")) {
// User wants to exit, so do that
finish();
return;
}
... here is the rest of your onCreate() code
This will only work if MyRootActivity doesn't call finish() when it starts the next Activity in your workflow. If MyRootActivity does call finish() when it starts the next Activity, you should change it so that it doesn't. In that case you will need to handle the case where the user BACKs into MyRootActivity as a special case.
Related
I am creating one app In which I want to check status of activity like activity is in foreground or in background.this is working perfect from code but I want to bring activity to foreground when it is in background for that I am using service so when activity is going to background state I am calling that service and from that service I am launching activity but service is working ok upto version 10 after that same code of intent is not working.
This is my code.
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(android.os.Build.VERSION.SDK_INT>=29 &&
!Settings.canDrawOverlays(getApplicationContext())) {
MainActivity.this.startActivity(new
Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
}
}
This is DigitalApp class which extend application and from this I am calling service.
public class DigitalApp extends Application implements Application.ActivityLifecycleCallbacks
{
private int activityReferences = 0;
private boolean isActivityChangingConfigurations = false;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(Activity activity) {
if (++activityReferences == 1 && !isActivityChangingConfigurations) {
// App enters foreground
Toast.makeText(this,"App is in foreground with
activity::"+activity.getLocalClassName(),Toast.LENGTH_LONG).show();
Log.d("Tracking Activity Started", activity.getLocalClassName());
Log.d("TAG","App is in foreground");
}
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
Toast.makeText(this,"App enters background with
activity::"+activity.getLocalClassName(),Toast.LENGTH_LONG).show();
isActivityChangingConfigurations = activity.isChangingConfigurations();
if (--activityReferences == 0 && !isActivityChangingConfigurations) {
// App enters background
Log.d("Tracking Activity Stopped", activity.getLocalClassName());
Log.d("TAG","App enters background");
Intent i= null;
getApplicationContext().startService(new
Intent(getApplicationContext(),service.class));
}
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
This is Service class.
#Override
public void onCreate() {
super.onCreate();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "IN HANDLER OF SERVICE",
Toast.LENGTH_LONG).show();
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(i);
}, 3000);
}
I am passing intent in handler to launch activity when it is going to background state.handler is in oncreate method of service.I want launch activity from there again after it is going to background state.
I am using flag new task but with this flag activity is not launching will I add other flags?
from the onStop() of your activity start the service like this-
fun launchService(){
val serviceIntent = Intent(this, LaunchAppService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
}else{
startService(serviceIntent)
}
}
and show notification for foreground service like this
My app start with splash screen. Splash screen visible for 5 seconds then menu activity start. But when splash screen on display and I press back or home button app go in background but after few seconds its come on foreground automatically with menu activity. I want if user press home or back key app close permanently. Here is what I have tried so far.
Splash Screen Activity-
public class SplashScreen extends Activity
{
/** Called when the activity is first created. */
TimerTask task;
Intent objIntent, intent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
UtilClass.playing = true;
objIntent = new Intent(SplashScreen.this, PlayAudio.class);
startService(objIntent);
new Handler().postDelayed(csRunnable2, 5000);
}
Runnable csRunnable2=new Runnable()
{
#Override
public void run()
{
intent = new Intent(SplashScreen.this, MainActivity.class);
startActivity(intent);
finish();
}
};
public void onBackPressed()
{
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
return;
}
#Override
protected void onPause() {
super.onPause();
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
}
}
You can see in onPause and onBackPressed I am closing app. But its start with menu activity after few seconds.
what suitianshi suggests is
public class SplashScreen extends Activity
{
/** Called when the activity is first created. */
TimerTask task;
Intent objIntent, intent;
Handler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
UtilClass.playing = true;
objIntent = new Intent(SplashScreen.this, PlayAudio.class);
startService(objIntent);
handler = new Handler();
handler.postDelayed(csRunnable2, 5000);
}
Runnable csRunnable2 = new Runnable()
{
#Override
public void run()
{
intent = new Intent(SplashScreen.this, MainActivity.class);
startActivity(intent);
finish();
}
};
public void onBackPressed()
{
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
return;
}
#Override
protected void onPause() {
super.onPause();
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
}
#Override
protected void onStop() {
super.onStop();
handler.removeCallbacks(csRunnable2);
}
}
As, Chris mentioned, Declare your HANDLER globally as,
Handler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
UtilClass.playing = true;
objIntent = new Intent(SplashScreen.this, PlayAudio.class);
startService(objIntent);
handler = new Handler();
handler.postDelayed(csRunnable2, 5000);
}
Here in this Line,
handler.postDelayed(csRunnable2, 5000);
You are calling your "csRunnable2", after 5 seconds, So, it will come up after 5 seconds until unless,
=> You destroy your instance of handler class completely or ,
=> Make all the references Null.
So, When ever you are closing or pausing your activity(as in onBackPressed(), onPause(), onStop(), onDestroy() etc.,.) make sure to call :
handler.removeCallbacksAndMessages(null);
before you start next Activity.
This will makes null of all Handler instances.
For eg., in your code you can call,
public void onBackPressed()
{
handler.removeCallbacksAndMessages(null);
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
return;
}
#Override
protected void onPause() {
super.onPause();
handler.removeCallbacksAndMessages(null);
objIntent = new Intent(this, PlayAudio.class);
stopService(objIntent);
finish();
}
I have 2 activities.
In my first, i have a button and when i click on it, it start the second activity .
But when i go back to my first and i click for second time my button, my second activity start but i have to go back two time to go back in my firts activity.
If a click one again a will have to go back 3 time ...
help me please. and thank you in advance :)
this is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this._that = this;
_progressDialog = new ProgressDialog(this);
EditText editText = (EditText) findViewById(R.id.MainActivityEditText);
editText.setText("T_F81D4FA3F8");
Button button = (Button) findViewById(R.id.MainActivityButton);
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.MainActivityButton ) {
Log.w("MainActivity", "onClick");
_progressDialog.setMessage("Chargement en cours");
_progressDialog.show();
new Thread(new Runnable() {
public void run() {
EditText editText = (EditText) findViewById(R.id.MainActivityEditText);
String s = editText.getText().toString().replace(" ", "");
Log.i("EditText", s);
ID_APPLICATION = s;
//if (! Datas.getInstance().isUpdateDatas())
WebService.getInstance().datas(_that);
LocalBroadcastManager.getInstance(_that).registerReceiver(datasUpdateFail, new IntentFilter("datas-update-fail"));
LocalBroadcastManager.getInstance(_that).registerReceiver(datasUpdate, new IntentFilter("datas-update"));
}
}).start();
}
}
BroadcastReceiver datasUpdate = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
myStartActivity("ACCUEIL");
_progressDialog.dismiss();
}
};
BroadcastReceiver datasUpdateFail = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "Erreur : Veuillez verifier votre identifiant ou votre connexion", Toast.LENGTH_SHORT).show();
_progressDialog.dismiss();
}
};
public void myStartActivity(String page){
Intent intent = new Intent(this, PageActivity.class);
Bundle bundle = new Bundle();
bundle.putString("page", page);
intent.putExtras(bundle);
this.startActivity(intent);
}
unregister the receiver
#Override
protected void onPause() {
// Unregister receiver
LocalBroadcastManager.getInstance(this).unregisterReceiver(datasUpdate);
LocalBroadcastManager.getInstance(this).unregisterReceiver(datasUpdateFail);
super.onPause();
}
Every time you get into this activity you register a received. So the second time you come back, you have 2 receivers registered. Therefore when you click on button 2 activities will be opened.
Try uninteresting the regiseter when you are done with it. eg. Before starting the new activity.
LocalBroadcastManager.getInstance(_that).unregisterReceiver(datasUpdateFail);
LocalBroadcastManager.getInstance(_that).unregisterReceiver(datasUpdate);
I'm new to Android and I'm stuck on a conception problem.
I have an application with several activities, some of those activities are critical and require the user to be logged in a webApp.
When the user clicks a button to reach one of those critical activities, I call a background Service which ask if the user is still connected to the webApp (not timeout). If the user is logged in, the activity is started, otherwise a dialog pops up and ask for username and password. The problem is that there is several protected activities, and I want to use the same service to do the verification. The way I do it for the moment works but it's kind of kludgy.
public class A_Activity extends Activity {
Context context;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getApplicationContext();
setButtonClickListener();
}
private void setButtonClickListener() {
button_1 = (Button)findViewById(R.id.button1);
button_1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intentCall = new Intent(context,com.them.cp.ConnexionManagerService.class);
intentCall.putExtra("WHO_IS_CALLED","FIRST_ACTIVITY");
context.startService(intentCall);
}
});
button_2 = (Button)findViewById(R.id.button2);
button_2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intentCall = new Intent(context,com.them.cp.ConnexionManagerService.class);
intentCall.putExtra("WHO_IS_CALLED","SECOND_ACTIVITY");
context.startService(intentCall);
}
});
}
}
And my service
public class ConnexionManagerService extends Service{
public class IsConnectedAsync extends AsyncTask<String , Void, Void>{
protected Void doInBackground(String... whoIsCalled) {
String redirectedURL = getRedirectedURL();
if(redirectedURL.equalsIgnoreCase(IF_NOT_CONNECTED_URL)){
if(whoIsCalled[0].equalsIgnoreCase("FIRST_ACTIVITY")){
Intent trueIntent = new Intent(getBaseContext(), FirstActivity.class);
trueIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(trueIntent);
}
else if(whoIsCalled[0].equalsIgnoreCase("SECOND_ACTIVITY")){
Intent trueIntent = new Intent(getBaseContext(), SecondActivity.class);
trueIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(trueIntent);
}
}
else{
Intent falseIntent = new Intent(getBaseContext(), PopUpLoginActivity.class);
falseIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(falseIntent);
}
}
return null;
}
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d("service onCreate", "onCreate");
}
public int onStartCommand(Intent intent, int flags, int startId){
String whoIsCalled = intent.getStringExtra("WHO_IS_CALLED");
new IsConnectedAsync().execute(whoIsCalled);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
with my little knowledge I wish i could just send an intent, but it seems that it's not possible as it's not the UI thread.
My question is: What can I do to make this service more generic ?
I want to use the same service to do the verification.
If you don't destroy the service it will be the same service object. If an activity which started your service finishes or stops the service it could be destroyed if it was the unique activity that started the service. If you want to ensure that the service reminds on background start it on you application class (extending Application) and in each activity you need. When an activity stops the service or finishes the service will not be destroyed because your application class is still connected.
EDIT:
To avoid write putExtra again and again:
public class StartOrder1 extends Intent {
public StartOrder(Context ctx, String activity_name){
super(ctx, ServiceName.class);
if(activity_name != null)
super.putExtra("WHO", activity_name);
else
super.putExtra("WHO", "UNKNOWN");
}
public String getWho(){
reurn.getIntExtra("WHO");
}
}
To start it:
this.startService(new StartOrder1(this, "My activity name"));
The best solution:
public class StartOrder2 extends Intent {
public StartOrder(Activity a){
super(a, ServiceName.class);
super.putExtra("WHO", a.toString());
}
public String getWho(){
reurn.getIntExtra("WHO");
}
}
And you can override toString method in each Activity passing the activity name, class name, whatever you want. Then when you start an intent:
this.startService(new StartOrder2(this));
Or extends Activity with this utility:
public class EnhancedActivity extends Activity{
protected startMyService(String name){
Intent i = new Intent(this, MyService.class);
i.putExtra("who", name);
startService(i);
}
}
And call it on your final activity
[...]
super.startMyService("activity_name");
[...]
Consider i am using five screen pages for project "A".Each page is having switching between other pages sequentially one by one,my need is to do close all the page when i am clicking the button "exit" from the page five which is the last one.
I have used this below code,but the problem is only the last page is getting close others are not.
find my code below
Button extbtn = (Button)findViewById(R.id.but_Exit);
extbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
} });
Thanks for your time!
Make all five activities extend a BaseActivity that registers a BroadcastReceiver at onCreate (and unregisters at onDestroy).
When extbtn is clicked, send a broadcast to all those BaseActivities to close themselves
for example, in your BaseActivity add:
public static final String ACTION_KILL_COMMAND = "ACTION_KILL_COMMAND";
public static final String ACTION_KILL_DATATYPE = "content://ACTION_KILL_DATATYPE";
private KillReceiver mKillReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
...
mKillReceiver = new KillReceiver();
registerReceiver(mKillReceiver, IntentFilter.create(ACTION_KILL_COMMAND, ACTION_KILL_DATATYPE));
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mKillReceiver);
}
private final class KillReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
}
and at extbtn's onClick call:
extbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// send a broadcast that will finish activities at the bottom of the stack
Intent killIntent = new Intent(BaseActivity.ACTION_KILL_COMMAND);
killIntent.setType(BaseActivity.ACTION_KILL_DATATYPE);
sendBroadcast(killIntent);
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
}
});