exit() and killProcess() doesn't work - android

I'm trying to close my app when back button is pressed. So I overridden onBackPressed() in my activity:
public void onBackPressed()
{
Process.killProcess(Process.myPid());
}
I also tried:
public void onBackPressed()
{
exit(0);
}
my app got 3 tasks and 5 activities: A, B, C, D and E. Where I placed A, B and C in one task While D and E got their own tasks. I want to exit the app when the back button is pressed in activities A, D and E.
I try toasting from onBackPressed() and function callback works fine.
When I click the back button on my device in activities A or D or E it just goes to the previous activity from another task !!

public class CloseApplication
{
private static boolean isToCloseApp = false;
public static boolean isToCloseApp()
{
return isToCloseApp;
}
public static void updateFlagToCloseTheApp(boolean flag)
{
isToCloseApp = flag;
}
}
onBackKey Press UseCode
public void onBackPressed()
{
CloseApplication.updateFlagToCloseTheApp(true);
finish();
}
One more Thing in each activity of your application Override the onResume method.
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(CloseApplication.isToCloseApp())
{
finish();
}
}
mark the answer solve if it solve your problem and so that it helps the other to find the answer.

Related

Android implementing onBackPress on Fragment cause of disable exit from application

In my application i have some fragment and i can exit from application by click on back on phone without problem, but when i implementing onBackPress on that i can't exit from application
My code:
#Override
public void onResume() {
super.onResume();
if (getView() == null) {
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (slider_call_phones.isOpened()) {
slider_call_phones.closeLayer(true);
}
return true;
}
return false;
}
});
}
I want to handle onBackPressed on fragment not Activities
Here's how I do it,
create an interface that would receive onBackPressed() in any class
that implements it and would return true if it's handling the method or false otherwise. This would make sure that your app would exit when your return false.
create a stack of these interfaces in your Activity, then add any of such interfaces to it.
override onBackPressed() in your activity, then anytime it's called, get a listener from the stack and call its own onBackPressed() if it returns true. If it returns false, then it's not handling onBackPressed() so Activity can take over and remove fragment or exit the application.
Here's a sample implementation.
In your Activity
public class MyActivity extends Activity {
//a stack of OnBackPressedListeners, stack one when you want it to receive onBackPressed() from
//this activity.
//PS used stack so that by LIFO, the last listener would be the first to be called.
private Stack<OnBackPressedListener> onBackPressedListeners = new Stack<>();
#Override
public void onBackPressed() {
if (!onBackPressedListeners.isEmpty()) {
if (onBackPressedListeners.peek().onBackPressed()) //if interface is handling onBackPressed(), return. Otherwise super would be called below.
return;
}
//if no listeners, then do super. This would ensure natural behaviour such as closing the app or popping a fragment when no listeners are using onBackPressed()
super.onBackPressed();
}
//listener interface
public static interface OnBackPressedListener {
/**
* #return true if you're handling onBackPressed, false otherwise to let super.onBackPressed() take over
*/
public boolean onBackPressed();
}
public void addOnBackPressedListener(OnBackPressedListener listener) {
onBackPressedListeners.add(listener);
}
public void removeOnBackPressedListener(OnBackPressedListener listener) {
onBackPressedListeners.remove(listener);
}
}
In your Fragment
//implement OnBackPressedListener in your fragment.
public class MyFragment extends Fragment implements OnBackPressedListener {
//find somewhere to add the listener to your Activity, most likely in onCreateView(...)
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
...
((MyActivity)getActivity()).addOnBackPressedListener(this);
...
return view;
}
//overide onBackPressed(), then return true if you're handling the onBackPressed(), false otherwise.
#Override
public boolean onBackPressed() {
if (slider_call_phones.isOpened()) {
slider_call_phones.closeLayer(true);
return true;
}
return false;
}
//lastly remember to remove the listener when your fragment is destroyed, so that it stops receiving callbacks,
//if you don't do this, you might get a NullPointerException.
#Override
public void onDestroy() {
super.onDestroy();
((MyActivity)getActivity()).removeOnBackPressedListener(this);
}
}
I mostly use a single Activity and a whole lot of Fragment's in my Android apps, this is exactly how I solve such problems you are having, for example closing a drawer in a Fragment if its open when the back button is pressed, or exiting the application if it's closed.
You should call onBackPressed() in the following manner in order to exit from the app:
public void onBackPressed(){
finishAffinity();
}

Understanding Window#getSharedElementTransition()

I have two Activities A and B which have a SharedElement. If Activity A starts Activity B and listens to the the transition, both the listener for exit and reenter are called.
Here the code for the calling Activity A:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().getSharedElementReenterTransition().addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.i("Log", "A REENTER");
}
...
});
getWindow().getSharedElementExitTransition().addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.i("Log", "A EXIT");
}
...
});
getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.i("TestApp", "A ENTER");
}
...
});
getWindow().getSharedElementReturnTransition().addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
Log.i("TestApp", "A RETURN");
}
...
});
}
public void onClick(View v){
Intent intent = new Intent(this, Act2.class);
Pair<View, String> pair1 = Pair.create(findViewById(R.id.textView), findViewById(R.id.textView).getTransitionName());
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pair1);
startActivity(intent, options.toBundle());
}
}
If I now execute onClick() (to start Activity B) and then hit the back button to return to Activity A, the Log will be as follows:
A REENTER
A EXIT
B ENTER
B RETURN
B ENTER
B RETURN
A REENTER
A EXIT
I would expect it to be
A EXIT
B ENTER
B RETURN
A REENTER
By default, the same transition is used for both the exit and reenter transitions as well as the enter and return transitions. If you explicitly set them, they will be different.
I believe that you are adding listeners to the same transition, so they are all being called.
I ran into the similar problem and found a similar question
There is a bug in Lollipop that causes the shared element return transition to be interrupted if it takes longer than the reenter
transition duration. If you adjust your reenter transition duration
(on the calling Activity), that should fix the interruption problem.
You better use the enter and return shared element transitions.

Application Level onResume Android

Problem
The idea is very simple. Whenever an user comes back to my app from the Recents I want to show a simple dialog prompting with the password.
I know how to prompt the dialog with password, but my problem is how do I understand that the user has entered my app from the recents. If I put the prompt in the onResume in every activity, then it will get triggered everytime even if the user doesn't enter from the Recents menu.
There are lots of activities and fragments in my app. So, I would love to have a more generic or application level solution.
Implement Application.ActivityLifecycleCallbacks, that will provide all activity callback in your application class.
public class AppController extends Application implements
Application.ActivityLifecycleCallbacks
{
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
}
You could try with this flag FLAG_ACTIVITY_LAUNCHER_FROM _HISTORY:
if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY )!=0){
Log.d(TAG, "Called from history");
//clear flag from history
Intent intent = getIntent().setFlags( getIntent().getFlags() & (~ Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY));
setIntent(intent);
}
Source : Android - detecting application launch from home or history
When "A" Activity is start from recent, this flag is present.
Now this flag will be also present if "A" activity call "B" activity and on "B" user press back.
So you have to check flag and when you detect it you have clear intent by removing this flag, source: Remove a Paint Flag in Android
Try below sample
/**
* TODO : After update to API level 14 (Android 4.0),
* We should implement Application.ActivityLifecycleCallbacks
*/
public class GlobalApplication extends android.app.Application
{
private boolean inForeground = true;
private int resumed = 0;
private int paused = 0;
public void onActivityResumed( Activity activity )
{
++resumed;
if( !inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void onActivityPaused( Activity activity )
{
++paused;
if( inForeground )
{
// Don't check for foreground or background right away
// finishing an activity and starting a new one will trigger to many
// foreground <---> background switches
//
// In half a second call foregroundOrBackground
}
}
public void foregroundOrBackground()
{
if( paused >= resumed && inForeground )
{
inForeground = false;
}
else if( resumed > paused && !inForeground )
{
inForeground = true;
}
}
}
Put below code in your all activities.
public class BaseActivity extends android.app.Activity
{
private GlobalApplication globalApplication;
#Override
protected void onCreate()
{
globalApplication = (GlobalApplication) getApplication();
}
#Override
protected void onResume()
{
super.onResume();
globalApplication.onActivityResumed(this);
}
#Override
protected void onPause()
{
super.onPause();
globalApplication.onActivityPaused(this);
}
#Override
public void onDestroy()
{
super.onDestroy();
}
}
I would suggest using LifecycleObserver. If your Application class implements this interface it marks a class as a LifecycleObserver, it does not have any methods, instead, it relies on OnLifecycleEvent annotated methods. The usage is simple:
public class AndroidApplication extends Application implements LifecycleObserver {
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppStart() {
//enter code here
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppStop() {
//enter code here
}
...etc
}
With Lifecycle.Event you can access all lifecycle states through Enum. It is part of androidx.

Free up memory on Android when push Back Button

I have 2 activities, Activity1 and Activity2. In Activity1 I have a button to go to Activity2.
Activity2 has a lot of Edittext and other Views.
When I start the app, the memory of the process is 10mb. If I click on the button and Activity2 is loaded, my memory's process is about 59mb.
The issue is, in Activity2, if I push Back Button, I return to Activity1 and my memory's process is about 59mb, and I don't need this information about Activity2.
Now, If I click again the button, I have an OutOfMemory.
How can I force to free up the memory when I push Back Button?
I try to call finish() and System.gc() but It doesn't work.
Thank you
try this one....
first close your activity...
use following code...
public class ur_clss extends Activity {
private ur_class c1;
//ur content here
#Override
public void onBackPressed () {
c1.finishActivity(0);
}
}
You need to override the BackButton and free up the memory when it is pressed.
#Override
public void onBackPressed()
{
Activity.finish() // the activity that you want to terminate
}
Or, there is another way to do it. When you start the new activity, the old activity goes onPause(). You could try calling finish() in the onPause() of the old activity.
This is the structure of the code:
public class Activity2 extends Activity {
// Global variables
private CarregaOperacions carrega_operacions;
private TableLayout taula;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Some code of UI
// Show a ProgressBar
loadProgress();
carrega_operacions = new CarregaOperacions(Activity2.this);
carrega_operacions.execute(null);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}
static class CarregaOperacions extends AsyncTask<Void, Void, Void> {
WeakReference<Activity2> context;
Activity2 act;
public CarregaOperacions(Activity2 activity) {
context = new WeakReference<Activity2>(activity);
act = context.get();
}
#Override
protected Void doInBackground(Void... arg0) {
act.carregaOperacions();
return null;
}
protected void onPostExecute(Void result) {
ArrayList<LinearLayout> llista = act.getLlistaFiles();
for (int i = 0; i < llista.size(); i++ ) {
act.getTable().addView(llista.get(i));
}
act.getScroll().setVisibility(View.VISIBLE);
act.treuProgres();
}
}
With this code, I explain a bit:
The real case is, Activity1 calls a TabActivity, that has the Activity2. Activity2 loads a lot of registers, and I do this asynchronously. I Override onKeyDown in Activity2 and on the TabActivity, but it seems that only is onKeyDown's Activity2 executed.

Run code when Android app is closed/sent to background

I have an Android application which sends some data to a webservice. I need to send this data as soon as the application is closed or sent to background.. But how do I accomplish this?
My current solution is to run it on the OnPause() on my home activity, but I need this to run no matter which activity the user is on when closing the app.. Is this possible or do I have to add the OnPause method to all activities?
Check this solution first https://stackoverflow.com/a/5862048/1037294 before you decide to use the code below!
To check if your application is sent to background, you can call this code on onPause() or onStop() on every activity in your application:
/**
* Checks if the application is being sent in the background (i.e behind
* another application's Activity).
*
* #param context the context
* #return <code>true</code> if another application will be above this one.
*/
public static boolean isApplicationSentToBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
For this to work you should include this in your AndroidManifest.xml
<uses-permission android:name="android.permission.GET_TASKS" />
This is the method that I used and it seems to work pretty well:
I have a top level Application class of my own that extends Application as such
public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
You also need to register this Application object in your manifest file:
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher" android:name=".MyApplication">
Notice how I also implement the ActivityLifeCycleCallbacks interface. This interface has the following methods:
public static interface ActivityLifecycleCallbacks {
void onActivityCreated(android.app.Activity activity, android.os.Bundle bundle);
void onActivityStarted(android.app.Activity activity);
void onActivityResumed(android.app.Activity activity);
void onActivityPaused(android.app.Activity activity);
void onActivityStopped(android.app.Activity activity);
void onActivitySaveInstanceState(android.app.Activity activity, android.os.Bundle bundle);
void onActivityDestroyed(android.app.Activity activity);
}
You need to implement those methods and then register for these events in your applications onCreate() as follows
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
This will then call the callback (the MyApplication object) whenever an activity lifecycle method happens such as onCreate(), onPause etc.
In your onActivityPaused() you can then check if the app was backgrounded or not by calling #peceps method : isApplicationSentToBackground(...)
This is what my code looks like then...
/**
* Application.ActivityLifecycleCallbacks methods
*/
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
try {
boolean foreground = new ForegroundCheckTask().execute(getApplicationContext()).get();
if(!foreground) {
//App is in Background - do what you want
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
Create a new class to go the Foreground checking (which is an async. task). See check android application is in foreground or not? for more.
class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
#Override
protected Boolean doInBackground(Context... params) {
final Context context = params[0];
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
Edit
This answer only serves for one purpose, that is, running a code in onPause() for all activities. It doesn't let you run a code when your app is sent to background.
Original Answer
Make an Activity named YourBasicActivity and override its onPause() method and extend every Activity from YourBasicActivity
Maybe this can be helpfull, tell me if it worked for you.
only when you return from background the value of activities would be 0 (zero)
the rest of the times would be a number higher than 0(zero) when the onRestart()
is executed.
public class FatherClass extends Activity {
private static int activities = 0;
public void onCreate(Bundle savedInstanceState, String clase) {
super.onCreate(savedInstanceState);
}
protected void onRestart()
{
super.onRestart();
if(activities == 0){
Log.i("APP","BACK FROM BACKGROUND");
}
}
protected void onStop(){
super.onStop();
activities = activities - 1;
}
protected void onStart(){
super.onStart();
activities = activities + 1;
}
}
All of your classes must extend from this class for this to work.
Explanation: The onStart is executed one the activity is "visible" and the onStop when the activity is "not visible". So when your APP (it says APP not activity) goes to background all the activities are "not visible" so they execute the onStop method, so the idea behind this is to ADD ONE each time an activity es started, and SUBTRACT ONE each time an activity es hided, so if the value of the variable "activities" is zero that means that all the activities that where started in some point are now not visible, so when you APP returns from background and executes the onRestart method on the activity in "front" you can check whether comes from background or is just restarting an activity.
you can use onAppForegroundStateChange() method which call when app is open and closed.this method is only called when your app comes in foreground/background.
onAppForegroundStateChange() method is better then you used onPause() method because onPause method is also called every time when you go to other activity.
you can use this method like that
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
AppForegroundStateManager.getInstance().addListener(this);
}
#Override
public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) {
if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND == newState) {
// App just entered the foreground. Do something here!
} else {
// App just entered the background. Do something here!
}
}
}
override the onStop() method of your Home activity and run the code there.
I think you need to run your own thread which will check whether all running activities in background or destroyed.
MyBasicActivity extends Activity
{
private static ArrayList<MyBasicActivity> activities=new ArrayList<MyBasicActivities);
private boolean started;
public void onCreate()
{
activities.add(this);
}
public void onDestroy()
{
activities.remove(this);
}
public void onStart()
{
this.started=true;
}
public void onPause()
{
this.started=false;
}
public boolean isStarted()
{
return started;
}
}
MyThread implements Runnable
{
private ArrayList<MyBasicActivity> activities;
public MyThread(ArrayList<MyBasicActivity> activities)
{
this.activities=activities;
}
void run()
{
while(!stopped)
{
boolean inBackground=true;
for(MyBasicActivity activity:activities)
{
if(activity.isStarted())
{
inBackground=false;
break;
}
}
if(inBackground)
//run your code here;
sleep(10000); //10 secs
}
}
}
If you are trying to submit/save data the user input, there are better ways to go about it than doing it when he tries to close the app. There are many ways to close an app. The user could even turn down the phone. So it's hard to take precautions against all of them.
I'd suggest you submit the data everytime the user stops writing, every any number of seconds or when he presses a button for example if your call to the webservice is too slow.
This way it's more safeproof and it's easier to implement.

Categories

Resources