In my app I use a BroadcastReceiver to catch incoming calls. So when someone calls and in case that I have the phone number stored in my application's DB, I display a window with the name of the caller.
The problem is that in some devices this window is not displayed if the device's screen is off before the phone rings.(If the screen of the device is on, when the phone rings, the window is displayed).
I also delay the drawing of the window for 3 seconds, but this doesn't seem to work.
To display the window I use the following code, where mView is a RelativeLayout with a TextView. This code runs in a Service.
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
dpToPx(72),
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
mParams.gravity = Gravity.TOP;
WindowManager mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mView, mParams);
After several failing tries I found it.
I had to replace the flag TYPE_PHONEwith TYPE_SYSTEM_OVERLAY.
try this, this will surely work
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Layout_Flag = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Layout_Flag = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Layout_Flag = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
Layout_Flag,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER;
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
try {
mWindowManager.addView(windowView, params);
Related
I am using Window Service to draw Overlay over screen. But my Overlay not covering the whole screen, It leaves out Status bar and Navigation Bar.
I have tried different approaches to solve it, but didn't find any solution. But the solution is available, as some Apps (Edge Lighting) on Play Store drawing border over full screen(Even on Android O).
My code snippet to achieve the task.
Window Manager
int Layout_Flag;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Layout_Flag = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else {
Layout_Flag = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
Layout_Flag,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
windowManager.addView(customView, params);
Drawing Edge
`override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// draw a shape
val width = measuredWidth
val height = measuredHeight
val strokeWidthCalculation = paint.strokeWidth / 2
path?.moveTo(strokeWidthCalculation, strokeWidthCalculation)
path?.lineTo(width - strokeWidthCalculation, strokeWidthCalculation)
path?.lineTo(width - strokeWidthCalculation, height - strokeWidthCalculation)
path?.lineTo(strokeWidthCalculation, height - strokeWidthCalculation)
path?.close()
paint.pathEffect = cornerPathEffect
canvas.drawPath(path!!, paint)
}`
Result
sample image, not covering status and navigation bar
In order to achieve it, the fourth parameter of WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS.
That's it.
The whole complete code:
val LAYOUT_FLAG: Int
LAYOUT_FLAG = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_TOAST
}
params = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
LAYOUT_FLAG, // NOTE
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT
)
I am using window manager to show a popup from service, but my popup view is not visible. It is blank. Does someone have any idea why this is happening?
I have written android.permission.SYSTEM_ALERT_WINDOW permission in manifest too. My code looks like this.
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= 26) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else if (Build.VERSION.SDK_INT >= 22) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_TOAST;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
WindowManager.LayoutParams p = new WindowManager.LayoutParams(
// Shrink the window to wrap the content rather than filling the screen
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
// Display it on top of other application windows, but only for the current user
LAYOUT_FLAG,
// Don't let it grab the input focus
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
// Make the underlying application window visible through any transparent parts
PixelFormat.TRANSLUCENT);
// Define the position of the window within the screen
p.gravity = Gravity.TOP | Gravity.RIGHT;
p.x = 0;
p.y = 100;
windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
LayoutInflater layoutInflater =
(LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
binding = DataBindingUtil.inflate(layoutInflater, R.layout.activity_lock, null, false);
windowManager.addView(binding.getRoot(), p);
It requires 'draw over other apps' permission by the user. Please search in the settings for this permission and allow it for your app.
i m trying to put window manager( using service not activity) over lockscreen and it works fine in other device except oreo device...in oreo device it display after lock screen.here is my permision foe window manager..so please suggest other solution to resolve the issue.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
}
mParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
LAYOUT_FLAG,WindowManager.LayoutParams.FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LAYOUT_STABLE,
PixelFormat.TRANSLUCENT);
mParams.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
mParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
I got a view that I am able to display on the lockscreen. But I want it to make it optional. Currently I use these params to achieve this:
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSPARENT);
And for not showing it on the lockscreen I use
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSPARENT);
Separately they work fine, but I want to change the type and flags programmatically. So I tried changing the WindowManager.LayoutParams with
params.flags &= ~WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
params.flags |= WindowManager.LayoutParams.TYPE_PHONE;
windowManager.updateViewLayout(myView,params);
to remove the type, remove the flag and set a new type,
but that doesn't seem to work. Does anyone know how to do this correctly?
You are setting type values into flag. Try this instead:
params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
// type is no bit flag, so this should do it
params.type = WindowManager.LayoutParams.TYPE_PHONE;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
int type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
int flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
int format = PixelFormat.TRANSLUCENT;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
type, flags, format);
params.gravity = Gravity.RIGHT | Gravity.TOP;
wm.addView(lockScreenView, params);
I tried to use FLAG_LAYOUT_NO_LIMIT or FLAG_FULLSCREEN. But it's only available on devices that have a hard home button. They are unavailable in devices have a navigation bar or virtual keyboard.