I am trying to create an activity that would pop up in full screen and be shown over the screen lock (similar to every alarm clock in Android which shows a full screen dialog to dismiss an alarm). Here is my code to display the window:
if (Build.VERSION.SDK_INT>=26) windowType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
else windowType = WindowManager.LayoutParams.TYPE_TOAST;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
windowType,
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT
);
wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
mTopView = (ViewGroup) getLayoutInflater().inflate(R.layout.activity_alarm_screen, null);
getWindow().setAttributes(params);
wm.addView(mTopView, params);
My concern here is that my app will need a special permission to show this window over other applications, and this scares users off. In API25 and lower I used TYPE_TOAST instead of TYPE_APPLICATION_OVERLAY, but in API26 it leads to:
FATAL EXCEPTION: main Process: com.app.alarm, PID: 31372
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.app.alarm/com.app.alarm.Activities.AlarmScreenActivity}: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W#601b8a2 -- permission denied for window type 2009
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
I saw this question, but it does not avoid asking a special permission.
Any other trick in API26 to avoid making a user allow a special permission that my app doesn't really need?
Related
I am trying to click the force stop button using the accessibility service.when i find the FORCE STOP button i click it using:
childNodeView.performAction(AccessibilityNodeInfo.ACTION_CLICK);
this is successful in ordinary scenario, however when I try to hide the process from the user using a window manager overlay the click doesn't work. This makes since maybe because there is a screen over the button I am trying to click, however there are several applications on the play store that have the described functionality with a window overlay
these are my window manager params:
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.START;
oneTapProgressView = new OneTapProgressView(this);
windowManager.addView(oneTapProgressView, params);
Note: I run this from a different service and not from the accessibility service
How do I perform the click with the window overlay?
I believe this is related to the overlay type. Specifically TYPE_PHONE. Phone overlays have special mechanisms to trap events so that users don't accidentally touch buttons with their cheek why talking on the phone.
You should try a different type. For Android O Try:
TYPE_APPLICATION_OVERLAY
For prior operating systems you want:
TYPE_SYSTEM_ALERT
Both of these will require the following permission:
SYSTEM_ALERT_WINDOW
Also, the following flags may be useful if the above alone doesn't fix it:
FLAG_NOT_FOCUSABLE
Need to show the Activity (Theme dialog) over the dialer with some information populated in activity like true caller. In unlocked phone, it is working well.
But in locked phone, it didnt work as expected. Did some googling and found few flags needs to be added to make dialog appear in lock screen.
CallActivity.java
LayoutParams layoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_DIALOG | LayoutParams.TYPE_SYSTEM_ALERT |
LayoutParams.TYPE_SYSTEM_OVERLAY,
LayoutParams.FLAG_NOT_TOUCH_MODAL |
LayoutParams.FLAG_NOT_FOCUSABLE |
LayoutParams.FLAG_TURN_SCREEN_ON |
LayoutParams.FLAG_SHOW_WHEN_LOCKED |
LayoutParams.FLAG_KEEP_SCREEN_ON |
LayoutParams.FLAG_DISMISS_KEYGUARD,
PixelFormat.TRANSLUCENT);
getWindow().setAttributes(layoutParams);
In the above code, i added changes related to make activity appear as dialog and few flags (FLAG_TURN_SCREEN_ON, FLAG_SHOW_WHEN_LOCKED, FLAG_KEEP_SCREEN_ON, FLAG_DISMISS_KEYGUARD) related to make dialog work well in lock screen (but it didnt).
I also starting the activity with (from broadcast receiver)
Intent intent = new Intent(context, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
context.startActivity(intent);
add view on window manager with System Alert permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mParams = new WindowManager.LayoutParams();
mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mParams.format = PixelFormat.TRANSLUCENT;
mParams.flags = 262184;
mWindowManager.addView(view, mParams);
Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().
Is there any way to give an app permission to launch an activity on top of another app? For example, when someone calls you on your phone while you're using another app, the calling activity takes priority.
to grant permission, add
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
to your manifest file.
to display view on top of other apps use the window manager
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams paramsForButton = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
windowManager.addView(yourViewWindowManager.LayoutParams, paramsForButton);
I have a service in which, when the user shakes his/her phone, shows a full screen overlay window. I'm using this code to get it done:
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mOverlayView = inflater.inflate(R.layout.overlay, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_DIM_BEHIND | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mOverlayView, params);
It fills up the whole screen, EXCEPT for the navigation bar. Is there a way I can hide the navigation in my service that displays the overlay?
Note that my app is running in the background. The user may be running any other app in the foreground, and I want to show my full screen overlay window even if my main activity is not running.
All examples I could find online all seem to require an activity running...
Thanks for any help!
I'd like to be able to create an Activity that is always at the front of display of Android.
It should receive no input, just pass it down to whatever application is next below it. Something like a HUD.
I was able to research that I need to set underlying window type to TYPE_SYSTEM_ALERT but it looks like Android is ignoring my code - no exception thrown even if I delete android.permission.SYSTEM_ALERT_WINDOW permission from manifest. (it is required to use this window type). When I tried to use ALERT type on dialog, it worked OK, but I cannot make dialog into full screen transparent entity.
Here is my code, maybe there is something simple missing.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);
}
Translucent setting has to be enabled externally in xml manifest, otherwise it also didn't work.
<item name="android:windowIsTranslucent">true</item>
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
ViewGroup mTopView = (ViewGroup) App.inflater.inflate(R.layout.main, null);
getWindow().setAttributes(params);
wm.addView(mTopView, params);
I found that the accepted answer (by tmouse) did not quite work for me. Maybe it worked for an older API level? I'm using API level 24.
That particular answer had recommended:
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);
There is a problem with this. The constructors that exist for WindowManager.LayoutParams are as follows:
So the WindowManager.LayoutParams.FLAG_FULLSCREEN flag gets used as an explicit value for int w and int h. This is no good! Your view's dimensions get set to 1024*1024 — so it does not fill the screen. And even if you explicitly set the layout's width and height to match the device's dimensions: they will not update when the screen orientation changes. We need a different approach…
I found that the correct construction for a full-screen overlay is like so:
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, // TYPE_SYSTEM_ALERT is denied in apiLevel >=19
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT
);
This means we no longer explicitly specify a width and height. The layout relies entirely on our flags instead.
Yes, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN is a required flag still; it is necessary if you want to draw over decorations such as the status bar.
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY should be used instead of TYPE_SYSTEM_ALERT in API level >=19. This is a note I wrote a while ago, sadly I've been unable to find citation to corroborate why I thought that, so take that with a pinch of salt.
Bonus notes (if you're reading this, you're probably trying to make a full-screen overlay):
Your manifest will need these permissions (explanation here):
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
My understanding is that SYSTEM_ALERT_WINDOW is the actual permission required, but that ACTION_MANAGE_OVERLAY_PERMISSION is needed also: it lets you request at runtime that the user grant the SYSTEM_ALERT_WINDOW privilege.
I provide here the source code to my working API level 24 app that creates a full-screen overlay.
Check out this
mention it in your AndroidManifest.xml file
<activity android:name=".MyActivity" android:theme="#android:style/Theme.NoTitleBar.Fullscreen" />
if you want to make your Activity full screen and transparent also
check out this
<activity android:name=".MyActivity" android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen" />