How to Detect If Any of My Activity Is Front-Most and Visible to User

How to detect if any of my activity is front-most and visible to user?

I don't know that there's a method to get the currently displayed activity, but you could do something combining the Activity Lifecycle and a flag.

For the flag, if you've extended the Application class, that's probably a decent place to store it. For extending the application class, the top answer to this question has info. (d).

So probably keep track of the current active activity (or a flag that the activity is visible) in onResume/onPause or onStart/onStop depending on exactly what behavior you want.

Since you have multiple activities, you'll need a centroid place for storing the flag, which is why the Application makes sense. You can get the custom Application object by casting the application context (e.g. ((MyApplication)getApplicationContext()).isMyActivityActive).

You could extend Activity as well to help keep this code clean and contained.


If you're using a service you could bind to the service in every activity in the onStart/onStop (or onResume/onPause). If bound, you're visible.

How to check if activity is in foreground or in visible background?

This is what is recommended as the right solution:

The right solution (credits go to Dan, CommonsWare and NeTeInStEiN)
Track visibility of your application by yourself using
Activity.onPause, Activity.onResume methods. Store "visibility" status
in some other class. Good choices are your own implementation of the
Application or a Service (there are also a few variations of this
solution if you'd like to check activity visibility from the service).

Example
Implement custom Application class (note the isActivityVisible() static method):

public class MyApplication extends Application {

public static boolean isActivityVisible() {
return activityVisible;
}

public static void activityResumed() {
activityVisible = true;
}

public static void activityPaused() {
activityVisible = false;
}

private static boolean activityVisible;
}

Register your application class in AndroidManifest.xml:

<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >

Add onPause and onResume to every Activity in the project (you may
create a common ancestor for your Activities if you'd like to, but if
your activity is already extended from MapActivity/ListActivity etc.
you still need to write the following by hand):

@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}

@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}

In your finish() method, you want to use isActivityVisible() to check if the activity is visible or not. There you can also check if the user has selected an option or not. Continue when both conditions are met.

The source also mentions two wrong solutions...so avoid doing that.

Source: stackoverflow

How to detect if a window is in front of other windows

I ended up using both Matiiss and acw1668 solutions to make this menu/toolbar compatible with both Microsoft Windows and Linux. In the second version below I added a bit more code to show how the menu/toolbar looks like. Both parent and child move to the back when opening another app on top, and both return to the front when selecting the parent again. acw1668' solution reduced the amount of code.

Simple version:

from tkinter import Tk, Toplevel, Button
from sys import platform

def start_side_menu():
global menu
menu = Toplevel(root)
menu.geometry("90x300+620+123")
menu.title("top")
menu.resizable(False, False)

# Remove borders in Windows
if platform == "win32":
menu.overrideredirect(1)

# Remove borders in Linux + keep child with parent
else:
menu.wm_attributes('-type', 'splash')
# acw1998 solution to keep the child with the parent with Linux
menu.transient(root)

def push_menu_front_win(event=None):
# Matiiss solution to keep the child with the parent with Windows
menu.attributes('-topmost', True)
menu.attributes('-topmost', False)

root = Tk()
root.title('master')
root.geometry("300x300+300+100")

# Microsoft Windows OS call this function ----------

if platform == "win32":
root.bind("<FocusIn>", push_menu_front_win)

start_side_menu()

root.mainloop()

Longer version to show final size and buttons on the floating menu:

from tkinter import Tk, Toplevel, Button
from sys import platform

def start_side_menu():
global menu

menu = Toplevel(root)
menu_width = 85
menu_height = 377
menu.title("")
menu.resizable(False, False)

# Remove borders in Windows
if platform == "win32":
r = (mon_width / 1) - (menu_width * 5.55)
t = (mon_height / 2) - (menu_height / 1.2)
menu.geometry(f'{menu_width}x{menu_height}+{int(r)}+{int(t)}')
menu.overrideredirect(1)

# Remove borders in Linux + keep child with parent
else:
r = (mon_width / 1) - (menu_width * 5.75)
t = (mon_height / 2) - (menu_height / 1.5)
menu.geometry(f'{menu_width}x{menu_height}+{int(r)}+{int(t)}')
# acw1998 solution to keep the child with the parent with Linux
menu.transient(root)
menu.wm_attributes('-type', 'splash')

# a couple of button just to show how to toolbar looks like
search_checklist_btn = Button(menu, text='SEARCH', font=('FreeSans', 11), width=11, height=2, bg="#729FCF")
search_checklist_btn.place(x=0, y=0, width=85)
save_checklist_btn = Button(menu, text='NEW', font=('FreeSans', 11), width=11, height=2, bg="#729FCF")
save_checklist_btn.place(x=0, y=47, width=85)

def push_menu_front_win(event=None):
# Matiiss solution to keep the child with the parent with Windows
menu.attributes('-topmost', True)
menu.attributes('-topmost', False)

root = Tk()
root.title('')
root.geometry("920x980+500+20")
mon_width = root.winfo_screenwidth()
mon_height = root.winfo_screenheight()

# For Microsoft Windows OS
if platform == "win32":
root.bind("<FocusIn>", push_menu_front_win)

# start the menu function
start_side_menu()

root.mainloop()

How to check if the fragment is visible to user

I finally came across the solution while trying myself:

Simple check for isResumed() and it'd only return true if the fragment is in the foreground and resumed state.

Just to be safe, check for isVisible which also checks for isAdded internally and would reduce the condition, so a simple if-condition:

if (isVisible() && isResumed()) {
// perform your action here
}

This worked for me!

make my application visible for all network users

Judging by the error message, your app is attempting to make a request to http://localhost:8000/api/v1/users?search=.. Probably because your front-end has http://localhost:8000 back-end address hardcoded somewhere. Make sure that your backend is available on port 8000 to your network users at http://10.68.10.20:3000, and then change it in your app.

In production apps, such addresses would usually not be hard-coded into the app itself, but configured using environment variables that would be applied at build/bundled step for a front-end application.

Edit: as you've specified that you're already using environment variables with .env files, what you typically do is:

  • Create a different file (name something like .prod.env) to use for production deployment
  • Specify all the environment variables that your app uses in it, so for example you would put REACT_APP_API_URL=http://10.68.10.20:8000/api/v1 in it
  • When you deploy your app for other users, use this file instead of the .env file you use for local development

This way you have an easy way to switch between configuration for local development and production, and can even launch the two environments simultaneously.

How can Service determine, if UI visible now

If you already have code to keep track of the state of your app's UI, you can probably get it to work simply by putting the code in onPause() and onResume(), instead of onStart() and onStop().

It is possible for the UI not to be visible, or partially hidden, even before onStop() gets called ... as you found out.

Take a look at the Android Activity lifecycle diagram here:

http://developer.android.com/images/activity_lifecycle.png

and note the description:

The foreground lifetime of an activity happens between a call to
onResume() until a corresponding call to onPause(). During this time
the activity is in front of all other activities and interacting with
the user. An activity can frequently go between the resumed and paused
states -- for example when the device goes to sleep, when an activity
result is delivered, when a new intent is delivered -- so the code in
these methods should be fairly lightweight.

Read more about this in another question here.

How to check if my activity is the current activity running in the screen

When your Activity comes to the foreground, its onResume() method will be invoked. When another Activity comes in front of your Activity, its onPause() method will be invoked. So all you need to do is implement a boolean indicating if your Activity is in the foreground:

private boolean isInFront;

@Override
public void onResume() {
super.onResume();
isInFront = true;
}

@Override
public void onPause() {
super.onPause();
isInFront = false;
}


Related Topics



Leave a reply



Submit