I want to launch a Notification in my app in a specific situation only when a certain Activity is not visible.
I managed to do it doing the bind/unbind of the Service when I create and destroy the Activity (using onCreate/onDestroy) e saving in a boolean if this Activity is visible through onPause/onResume methods, as the following code bellow shows:
public void onCreate(Bundle savedInstanceState) {
// ...
bindService(...);
}
public void onDestroy() {
// ...
unbindService(mConnection);
}
public void onResume() {
// ...
// this method sets to true the Service's boolean which retain Activity's visibility.
mService.registerActivity(true);
}
public void onPause() {
mService.registerActivity(false);
}
And on the Service, I check this boolean to launch the Notification.
It works for all the cases except in a specific one: when the app is opened in this Activity but the lock screen is enabled.
By some tests I've made, when the lock screen appears, the Activity.onPause method is called. I was hoping that the Activity.onResume method was just called when the lock screen was unlocked, but that's not what happens. When I press the power button to summon the lock screen, the Activity.onResume method is called already. In this sense, what I am doing is not right.
How can I make the Activity.onResume method to be called only when the user unlock the lock screen? Or... how can I identify that the lock screen was unlocked and the user is REALLY looking at the Activity?
Activity.onWindowFocusChanged(boolean hasFocus) should return true every time your Activity regains focus after the screen is unlocked.
2 thoughts, untested and i'm still kind of an android noob :
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> list2 = am.getRunningAppProcesses();
Then, filter your Activity from this list and check the importance property of it. Front running apps it's 100, don't know if it's still 100 when a lock screen is in front of it.
Or, you could create a running process what checks ever x seconds if the screen was locked, and, does something when it's unlocked again.
Related
Firstly, I believe this is not a duplicate question, although the solution for the error has been asked a lot of times. I have tried atleast 5 different solutions but they either don't change anything or make things worse. I want to pause the activity when the screen is locked/focus changed and allow the user to unpause the activity when the app is opened again.
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus && pauseFragment == null) {
exercisePlayPause(isPaused, workoutExerciseNum);
isPaused = !isPaused;
}
}
exercisePlayPause calls the following method
public void PassExerciseNum(int exerciseNum, Boolean isPaused) {
if (!isPaused) {
pauseFragment = new PauseFragment();
pauseFragment.getExNum(exerciseNum);
getFragmentManager().beginTransaction().add(R.id.aworkout_layout, pauseFragment, "pause").commit();
} else {
getFragmentManager().beginTransaction().remove(pauseFragment).commit();
pauseFragment = null;
exercisePlayPause(true, exerciseNum);
}
}
This works fine when the home button is pressed or some other app is activated or the notification bar is clicked. But when the screen is locked then I get the following error
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1411)
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1429)
at android.app.BackStackRecord.commitInternal(BackStackRecord.java:687)
at android.app.BackStackRecord.commit(BackStackRecord.java:663)
The offending line is getFragmentManager().beginTransaction().add(R.id.aworkout_layout. I am pausing few processes when any event that makes the user move away from the app. And when the user comes back to the app, he/she can resume from there. Hence, I am not destroying the activity. I have tried using commitAllowingStateLoss() but that makes me lose data for the paused processes and becomes a bit messy.
So in short the question is how to make a fragmenttransaction happen before onSaveInstanceState is triggered when the screen lock button is pressed?
The activity's orientation was sensorLandscape. When a screen locks it converts the screen to portrait and when the screen is unlocked it starts from a portrait mode and then becomes landscape. Hence, onDestroy was called when screen is locked. And when the screen is unlocked, onCreate gets called. This orientation change overrides the activity's orientation set in manifest. What happens when this forceful orientation happens can be controlled by adding android:configChanges="orientation|screenSize|keyboardHidden"/> to the manifest. This prevents onDestroy being called and the "illegalStateException" can be avaoided.
For example, an user opens an app, presses the home button, and then comes back to the app again.
Is there any way to trigger certain functions when the user navigates back to the app? Such as auto load a view object when the user is back to the app.
This question is for both Android & iOS.
Use the following to your likings in the projects's AppDelegate.m file (iOS only)
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
for android you can right your code in onResume function which is called when backgroud app come to front. but remember android life cycle which is
onCreate-->onResume.
so onResume is always called even app runs first time or come from background.
but onCreate called only when Activity created first time.
you can set some variable on onPause method which is called when app is going to background
and when you get that variable "true" and onResume called you can perform you task.
enjoy.
In onPause() method write this code to know that your application is went to background.
public void onPause()
{
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
Boolean flag=false;
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
flag=true;
}
}
if(flag)
{
//App went to background...
}
}
Use the above flag in onResume() to know that your application was resumed.
try to use a boolean variable in Two methods of the acitivity, onKeyDown and onPause.
boolean backFromBackground = false;
onCreate(){
//whatever you want
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME)
{
backFromBackground = true;
}
}
onPause(){
if(backFromBackground){
//do what ever you want
}
}
I need to do some network request when user restores my app from background (for example: worked with app - pressed home button - home screen - switched to my app again via task manager or clicked app icon). I don't want this to be triggered by screen rotate or simple change of current activity by startActivity(). What is the best approach?
Override the onResume() method.
#Override
public void onResume() {
super.onResume();
//Your work goes here
}
onResume() will be called when the user returns to the Activity.
I declare my variable 'shake' as a global variable, then I created new object inside the oncreate, then I call this :
#Override
public void onPause() {
super.onPause();
shake.cancel();
}
my phone can still vibrate although home button is pressed! I tried onStop(), same doesn't work..
my app is like this : countdown 10 sec, after that vibrate.. but the problem is onPause cannot be call so the user may feel where's the vibrate come from if it's set 2 minutes on the countdown ticker.. help!
Since I can't see the rest of your code, I'm gonna assume a few things.
Assumption #1
If you have your activity open, and the countdown starts and expires after 10 seconds, your phone vibrates (with your activity still open). If you go to home screen, the vibration stops.
Assumption #2
You have your activity open, and the countdown starts. Before the 10 second expires, you go to home screen. Your activity is not visible, but the phone starts vibrating soon.
If this is what you are seeing, it's the correct behavior. The problem is that in the 2nd case, your shake.cancel() from onPause() is called when you go to the home screen, before it actually starts vibrating. shake.cancel() can only cancel if it's already vibrating.
If that's what you are trying to fix (I can only assume since I can't see the rest of your code), you can try this:
private boolean mAllowShake = false;
#Override
public void onResume() {
super.onResume();
mAllowShake = true;
}
#Override
pulic void onPause() {
super.onPause();
mAllowShake = false;
shake.cancel();
}
// wherever you are calling the shake.vibrate()
if (mAllowShake)
shake.vibrate();
This way, when your activity is not visible and your timer goes off, since mAllowShake is false, it won't actually vibrate.
If that's not what you are trying to fix, please update your question with more code and description of your exact use case. Hope it helps!
I want to disable the lock screen in a certain app. My problem is that this also disables the lock screen for the whole phone. So I added lock.reenableKeyguard(); to the onPause() method, but this is called not only when the user exits the app but everytime a new activity starts in that app. Do I have to disable the lock screen in every activity and add this onPause method? Is there way to manage this only in the first activity that is shows when the app starts?
Btw I also reenable the lock screen in the onStop and onDestroy methods. The other problem with onPause is that it is also called when I turn off the phone's screen (by pressing the power button or what is that called), so when I first open the app, I turn off the screen then turn it on, there is no lock screen, but when I turn it off-on again, there is it, as I reenable it in the onPause method.
After playing with this a couple of hours I figured out I forget to implement onResume():
public void onResume() {
lock.disableKeyguard();
super.onResume();
}
This way every time I open the activity/turn on the screen, the lock screen is disabled.