How to know activity has been finished? - java

I want to check to see if an activity is running or finished. Is there any method through which I can check the status of activity?
I found activity.isFinishing() but I am not sure about it.

If you want to perform any step before Activity is going to become invisible.
Their are several choices here.
onDestroy() - for final cleanup.
isFinishing() - right after act.finish() is called it will return true.
onStop() - when the Activity is killed by framework process. (not destroyed)
onPause() - when the Activity is covered by any other Activity
onBackPressed() - capturing the event of hardware Back key triggered by user.

Call isFinishing in the onPause method before the activity is destroyed:
#Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
// Here you can be sure the Activity will be destroyed eventually
}
}

I realize this is very old, but for anyone using Kotlin:
We can check within a Fragment:
// FRAGMENT
override fun onPause() {
super.onPause()
// Log.v(TAG, "onPause");
if(requireActivity().isChangingConfigurations) {
// Config change
} else {
if(requireActivity().isFinishing) {
// deal with activity ending (finish up viewModel etc)
}
// deal with rotate or other config changes as required
}
}
Of course, we can also just do this directly inside an activity (just remove the requireActivity() parts).

Related

onPause() without intent , onResume() without onCreate()

I'm building an app that plays music on the background with service. The music is muted when the user is not in the app and unmuted when he is back. I used the onPause() and onResume() methods to do this.
The problem is - every time the user enters a new activity, the music pauses for a second and then resumes, because for a second the current activity is paused.
another problem - for the first run of the activity, the onResume() and onCreate() both works, which makes my service stops from the onResume() without it even being created from the onCreate() (which makes the app shut down).
is there a way to use onPause() without the intent part (or another similar way?)
is there a way to use onCreate() without to onResume() on the first run?
protected void onCreate(Bundle savedInstanceState) {
counter++;
if (counter==1) {
alliesSPEditor.putBoolean("isAllies", true);
alliesSPEditor.commit();
startService(new Intent(this,MusicService.class));
}
#Override
protected void onPause() {
super.onPause();
MusicService.getMP().mute();
}
#Override
protected void onResume() {
super.onResume();
if (counter!=1) //because the counter is still 1, the app won't shut down this way but it will not unmute the music.
MusicService.getMP().unMute();
}
onResume() is always called after onCreate() before the activity starts running
See https://developer.android.com/guide/components/activities/activity-lifecycle
I see some ways to solve this:
the problem is - every time the user enters a new activity, the music pauses for a second and then resumes, because for a second the current activity is paused
The first is you set a flag in the handler that start your new activity and
check in your onPause() method the value of de flag, if false, do nothing othewise mute de music.
public static boolean openOtherActivity = false;
#Override
protected void onPause() {
super.onPause();
if (!openOtherActivity) {
MusicService.getMP().mute();
}
}
You can use Preferences too if you preferrer
To resolve de onCreate() and onResume() problem, you can use the same logic
creates a flag for the services started and control when you needs unmute the music in anothers methods
public static boolean isServiceCreated = false; // In your activity that start the service
protected void onCreate(Bundle savedInstanceState) {
counter++;
if (counter==1) {
alliesSPEditor.putBoolean("isAllies", true);
alliesSPEditor.commit();
startService(new Intent(this,MusicService.class));
isServiceCreated = true; // set the flag to true
}
}
OnResume() method you can check if the service is started an create your logic

Check if activity is visible (onResume&Pause dosen't suit, because of multiwindow mode)

I need to ensure somehow the activity is on screen visible to user eyes.
We can do this by listetning to onResume & onPause events in Activity class and setting some boolean in these functions.
But onPause is called not only when you minimize your activity, onPause is also called when you switched to other window in multiwindow mode (Android 7.x Nougat)
So the boolean onPause&onResume method will lead to mistakes.
Then how to know visibility of Activity?
Thanks for help.
On Nougat and above you must check the onStop method , it will tell you when your Activity is not visible , you could use this code:
#Override
public void onPause() {
super.onPause();
if (Build.VERSION..SDK_INT <= 23) {
//your activity is not visible
onHidden();
}
}
#Override
public void onStop() {
super.onStop();
if (Build.VERSION..SDK_INT > 23) {
//your activity is not visible
onHidden();
}
}
Assuming that your onHidden method will perform some action.
I found this interesting link about your problem: Multiwindow

Run App Twice To Work

I'm making an android app that test if certain security features on your phone are enabled. For example, if you have password log in enabled or if your data is encrypted on your phone.
For some reason, the app has to be run twice to test and see if these security features are enabled on the phone or not, and this is the problem I'm trying to solve. I'd like it to test and see if the security features are enabled when the app is created and the first time the app is run, not the second time it is run.
I test if these features are enabled in the onStart() function in my MainActivity file. I included the functions code below:
#Override
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#SuppressLint("NewApi")
public void onStart()
{
super.onStart();
//determine if phone uses lock pattern
//It returns 1 if pattern lock enabled and 0 if pin/password password enabled
ContentResolver cr = getBaseContext().getContentResolver();
lockPatternEnable = Settings.Secure.getInt(cr, Settings.Secure.LOCK_PATTERN_ENABLED, 0);//Settings.System
//returns 1 if pin/password protected. 0 if not
KeyguardManager keyguardManager = (KeyguardManager) getBaseContext().getSystemService(Context.KEYGUARD_SERVICE);
if( keyguardManager.isKeyguardSecure())
{
//it is pin or password protected
pinPasswordEnable=1;
}
else
{
//it is not pin or password protected
pinPasswordEnable=0;
}//http://stackoverflow.com/questions/6588969/device-password-in-android-is-existing-or-not/18716253#18716253
//determine if adb is enabled. works
adb=Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0);
//determine if bluetooth is enabled.works
bluetooth=Settings.Global.getInt(cr, Settings.Global.BLUETOOTH_ON, 0);
//Settings.System BLUETOOTH_DISCOVERABILITY
//determine if wifi is enabled. works
WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled())
{
//wifi is enabled
wifiInt=1;
}
else
wifiInt=0;
//determine if data is encrypted
getDeviceEncryptionencryption();
//determine if gps enabled
}//end of onStart() function
If any more code needs to be posted to answer this question, just let me know, and thanks for your help. Maybe the issue has something to do with the super.onStart();
Does anyone think that a splash loading screen might help solve the issue?
Here is good explanation how app lifecycle flows.
onStart() can be executed many times. You can keep counter how many times you had entered this method and act differently on each time:
static int counter=0;
public void onStart()
{
counter++;
Log.i("MyApp", "onStart() run "+counter);
switch (counter){
case 1: break; // first run
case 2: break; // second run
default: break;// other runs
}
}
To be more clear about life cycle and why your onStart() method is called twice I suggest to have counter and Log.i() in each important state of the cycle - at least in onCreate() and onRestart().
Keep in mind that app stays in memory when you click Home button. When you click app icon again it restarts already running app (calls onRestart() and then onStart() methods and no onCreate() ). When you really kill you app for real then sequence would be onCreate and onStart without onRestart. Having logcat records really helps you to understand app lifecycle flow and why your onStart() is called twice or more times.
Using a static variable to check how many times onStart has been called isn't a good idea, because an app can be killed if Android needs more memory for other apps while still allowing the user to navigate back to the app. That would be the path through the red box in the picture below (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle):
A static variable would be 0 again after that and your app would run the security check again.
What you need to do is use an instance variable that you persist in onSaveInstanceState and restore in onCreate. In case the app is killed, onSaveInstanceState is called and you save your Activity's state. If the user goes back to the app, onCreate is called and the state would be restored. This works for all other cases too when the app isn't killed but the user just navigates away from the app and later re-opens it. Here's a simple example of an app saving and restoring:
public class MainActivity extends Activity {
private boolean mSecurityCheckDone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
#Override
protected void onStart() {
super.onStart();
if (! mSecurityCheckDone) {
// run the security check
mSecurityCheckDone = true;
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("mSecurityCheckDone", mSecurityCheckDone);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
}
how about using flag ?
singleTop
If an instance of the activity already exists at the top of the target
task, the system routes the intent to that instance through a call to
its onNewIntent() method, rather than creating a new instance of the
activity.
singleTask
The system creates the activity at the root of a new task and routes
the intent to it. However, if an instance of the activity already
exists, the system routes the intent to existing instance through a
call to its onNewIntent() method, rather than creating a new one.
singleInstance
Same as "singleTask", except that the system doesn't launch any other
activities into the task holding the instance. The activity is always
the single and only member of its task.
http://developer.android.com/guide/topics/manifest/activity-element.html
I'm not sure why you are using onStart(), if you want it to be run the first time the activity is created I would probably use onCreate() instead.
There is no API in Android that will tell you if the app has been run at least once so you will need to use some type of persistent storage for that, e.g. SharedPreferences could be used to persist a flag that would be set the first time your app is run and thereafter you can check it as shown here.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences settings = getSharedPreferences("Prefs", 0);
if (settings.getBoolean("first_time", true)) {
//the app is being launched for first time, do something
Log.d("Comments", "First time");
// first time task
// record the fact that the app has been started at least once
settings.edit().putBoolean("first_time", false).commit();
}
}

Can't understand isFinishing

I've been studying Google IO 2012 code
In one of the activities (HomeActivity.java) they're doing as follows:
void onCreate(Bundle savedInstance)
{
if(someCondition) {
// start some other activity here
finish(); // finish this activity
}
if(isFinishing()) return;
// More code here
}
I wonder why they do not put return right after finish() but instead checking isFinishing() ?
An Activity can be finished in a number of ways.
finishActivity from an activity that has called startActivityForResult
finishAffinity and finishFromChild
So isfinishing is used to account for such cases.

OnResume() not called by Pressing back Button in ActivityGroup

As ActivityGroup manages the Activities in the form of view, so when I try to return back to the Parent Activity that called the child Activity in ActivityGroup the onResume() is not being called.
I tried calling the OnResume() like this.
((Activity)view.getContext()).onResume();
But its not working, instead finish() is working is fine for me.
((Activity)view.getContext()).finish();
So, I am able to get the Activity from the View, but not able to call the onResume(), any idea will be appreciable.
Try this, when you press back button using ActivityGroup.
public void back()
{
if ( arrList.size() > 1 )
{
arrList.remove(arrList.size() - 1);
View v = arrList.get(arrList.size() - 1);
Activity_name object = ((Activity_name)v.getContext());
object.onResume();
setContentView(v);
}
else {
this.finish();
}
}
onResume is a lifecycle method called by OS when activity comes to the top of the stack. You can't call it directly.

Categories