Edit:
I'm afraid my initial question didn't understood the way I intended so I will rephrase it.
Under some circumstances (permission revoke, memory clean) the OS doing a "soft" restart to the application process. When the user reopen the app the OS will launch the last activity used before the precesses restarted. Is there a way to tell the OS to not try to restore the application's last state and just start from the beginning?
Use this https://github.com/JakeWharton/ProcessPhoenix library. You can customize your restarting using this.
Start the default activity in a new process:
ProcessPhoenix.triggerRebirth(context);
Or, if you want to launch with a specific Intent:
Intent nextIntent = //...
ProcessPhoenix.triggerRebirth(context, nextIntent);
If you want to restart application when that goes to background and agin go to foreground use android:noHistory="true" for certain activities in android Manifest.xml file
the issue is still, that the OS does not notify of such an event - which leaves no other option than to manually handle it. eg. check for the permission not being granted onCreate() and onResume() of the Activity - and than act accordingly, eg. clear the back-stack and then inflate the first one fragment.
the only culprit there is split-screen mode, where onResume() won't be triggered, simply because it never caused an onPause() event. I mean, permission settings on the one side, the application on the other side. to handle this one would have to occasionally check for the state of permissions.
Related
TL;DR How to make a phone call while using Activity.startLockTask()?
I'm trying to setup a restricted environment on an Android device, i.e. what is usually called "Kiosk-Mode".
Official documentation can be found here:
https://developer.android.com/work/cosu.html
The official way of doing this suggest to use Activity.startLockTask.
This works fine until you want to start other apps from within your Activity which is in startLockTask() mode.
Any activity that launches must not start on a new task stack otherwise the system blocks the launch intent, i.e. no Intent.FLAG_ACTIVITY_NEW_TASK.
Some apps can just be launched, other seem to implicitly set this flag, but can be workedaround by using startActivityForResult(...) which seems remove the NEW_TASK flag. For apps that still don't work I could code my own replacement.
The real issue is the call application, which enforces a new task stack. Triggering a call initiated the call, doesn't show the call activity, but also puts a call notification in the status bar (which is not accessible in while using startLockTask().
In contrast to other apps the call app is also one that can't be replaced with a custom app...
DevicePolicyManager.html.setLockTaskPackages() has no effect on this behavior.
I tried to make start call intent under locked mode and this line pop up:
system_process E/ActivityManager: Attempted Lock Task Mode violation mStartActivity=ActivityRecord{56ab302 u0 com.android.server.telecom/.components.UserCallActivity t155}
So I add
setLockTaskPackages(<ComponentName>,new String[]{getPackageName(),"com.google.android.dialer","com.android.server.telecom"});
Managed to get the dialler out. Of course if I push the home button or back button, there's no way to get the dialler back... the recent button is still locked though. Receiving call works perfectly (all buttons are disabled)
Have you tried this?
setLockTaskPackages(new ComponentName(this, DeviceAdminReceiver.class),new String[]{getPackageName(),"com.google.android.dialer"});
I know that to open up the Bluetooth settings programmatically.
I do something like this:
Intent intentOpenBluetoothSettings = new Intent();
intentOpenBluetoothSettings.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intentOpenBluetoothSettings);
But doing so will take me to the Bluetooth settings page in the same view/application.
How should I go about if I want the Bluetooth settings page to open up in another view/window/page, outside the application?.
The reason why I want this to be done is so that the user will not confuse the settings page and my app.
Thanks.
Update
I tried doing intentOpenBluetoothSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
But no luck in getting it to open in another view.
There are two ways of requesting for enabling Bluetooth:
intentOpenBluetoothSettings.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
or
intentOpenBluetoothSettings.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
If none of them suit your needs, then you might rethink your idea.
I advice reading up a little on android activity lifecycle and backstack.
Settings is NOT running in your app.
But normally everything you start is put on the backstack.
So if you go from your app to some other app (settings) android will remember that.
Your app there is not destroyed but only set on pause (onPause is called).
If you close settings it will return to your app and delete the entry for settings on backstack. I assume that is not the problem here.
But if you don't close settings and then by some means try to start your app again it is not destroyed but only waked up (no onCreate but only onResume). Android will then check that your app has loaded settings currently and settings will show up again.
If you restart your app with an Intent you control (like from a service)
You can:
startMyAppIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
The flag will kill the backstack up to the point where your app is on top of the stack so your app will start no matter if it had started settings before.
Backstack is not cleared completely so if your app was started by another app you may be able to return to that when pressing the back button.
When i stop my application pressing home button, i need that the app restart from the same activity when i open it again.
Now my application always start from main activity :(
(i don't know why but on emulator work correctly...)
There are a lot of options for preserving the state of an application - the ost common of these include using the bundle passed in OnCreate to initiate the application correctly.
I suggest you look at the android developers documentation as regards to activity lifespan.
When you begin an Activity, store a SharedPreference that records which Activity you are on. Check this preference when you enter your main Activity and, if set, jump to that Activity.
(If you are just looking for a way to get back to your Activity and don't care about the code, use the Recents menu to get back to your Activity. On devices with dedicated keys, long-press Home.)
I have an application.In that if we press on home button app closes but when i launch the app it resumes where i stopped.I mean it do not closed completely.how to solve this problem.
When you press Home button, onDestroy method of the current activity is called. You can perform any shutdown operations there. Design of Android doesn't have a concept of explicit application shutdown, so that the user can continue on the same activity where he started.
You are trying to copy desktop application behavior (the application is shutdown explicitly) to Android with different usage patterns. While this is understandable, in most cases this will contradict to other applications behavior and will annoy users. So if you have anything to shutdown, do this in onDestroy method.
You can make your android app return to the root activity each time you open it by modifying your AndroidManifest.xml to include
android:clearTaskOnLaunch="true"
in the desired <activity> declaration.
Android does not allow you to terminate the application at any time. Application lifecycle is maintained by the Android OS itself. You are not supposed to meddle with it. Unlike desktop applications, Android application lifetime is determined by the OS itself. You can only end an activity.
For more Info refer to this bug http://code.google.com/p/android/issues/detail?id=1572
You need to call finish() in your onDestroy() method.
Android doc say:
"When the system, rather than the user, shuts down an activity to conserve memory, ... "
But how to simulate this situation?I want to debug the onRestoreInstanceState(Bundle) method,but don't know how to.
You can't do it in an automated way b/c its completely non deterministic.
See my answer here: https://stackoverflow.com/a/15048112/909956 for details.
But good news is that all you need to do is just simulate calling onSaveInstanceState and you are indirectly testing this low memory situation.
onSaveInstanceState can be triggered by:
losing focus (by pressing home which in essence is like switching from your app to launcher app), launching another activity, pressing recents
changing orientation. this is the easier way if you are using an emulator
changing developer setting: goto developer options --> Apps --> Don't keep activities. This is best option if you are testing temporarily on an actual device.
I've used the "Don't keep activities" developer option to reproduce a crash that happened when an activity was killed due to memory pressure. You can find it in the Apps section of Settings->Developer Options.
It destroys every activity as soon as you leave it. E.g. if you press home to put your app in the background the current activity is destroyed. See https://stackoverflow.com/a/22402360/2833126 for more information.
There's two way to simulate the android killing process: using the setting "Don't keep activities" in developer settings or killing the app process by yourself.
To kill the process, open the activity you want to test, then press home button to send your app to background, and then, using the DDMS in Android Studio (Android Device Monitor), select the process and then stop the process (as seen in the image below). Your app was killed. Now, open your app again (accessing the list of open apps). Now you can test the killed state.
For the purposes of debugging onRestoreInstanceState(), just change the screen orientation ([Ctrl]-[F11] in the emulator). Your activity will be destroyed and recreated, and the onSaveInstanceState()/onRestoreInstanceState() pair will be invoked.
Use the SetAlwaysFinish app (works on a real device and in the emulator) or use the Google DevTools app (works in the emulator only).
These apps use the hidden AlwaysFinish setting of the ActivityManagerNative class to change the behavior of the OS and cause it to immediate unload every activity as soon as it's no longer in the foreground. This will reliably trigger the onSaveInstanceState and onRestoreInstanceState events.
See link below for more details:
http://bricolsoftconsulting.com/how-to-test-onsaveinstancestate-and-onrestoreinstancestate-on-a-real-device/
To debug onRestoreInstanceState you could do the following:
make sure you can debug application right after its start (calling android.os.Debug.waitForDebugger() from your constructor helps, it hangs your application until debugger is connected),
put you application in some state,
causally kill it from Settings->Apps,
causally switch back to it through Recent Apps button (it will still be in the list),
at this moment your application will be started anew and onRestoreInstanceState will be immediately called on the top activity.
Good answers here.
Now, residing in the distant future, using Instant Run in Android Studio will also trigger a save and restore when activities are restarted with code changes.
There's a decent solution for this in Android 6 and newer. See my answer here: Simulate killing of activity in emulator