My main goal is to show UI (With EditText, so IME support) Over the lock screen (No matter if there's PIN/Code or simple lock screen).
I know that WhatsApp application is doing it (Settings > Notification > Always show popup) so there's a solution for that.
The UI must be initialized from Service.
The view is a simple textview:
textview = new TextView(this);
textview.setText("Hello There!");
textview.setTextColor(ContextCompat.getColor(this,
android.R.color.white));
textview.setTextSize(32f);
I've tried several ways so far:
(In order to reproduce like whats app i'm doing everything when screen off receiver called)
Using WindowManager
WindowManager Params:
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.BOTTOM;
params.screenBrightness = 0;
Result: TextView is shown only after we unlock the device
Using Transparent activity
Activity style:
true
#android:color/transparent
#null
true
true
false
Also, has android:showOnLockScreen="true" attribute
Result: TextView is shown only after we unlock the device
Any other suggestions?
Thanks.
Add this in onCreate() of your Activity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
Related
I am showing a webView as an alertDialog from a service when my app is not running on foreground, therefore, My webView is attached to the screen via WindowManager.addView() method.
The webView has an input field which I want to be accessible by the user. Unfortunately, when the user clicks on the input field, it is not showing the keyboard for users to allow input.
My webView is inside a cardView who's params are as follows:
public WindowManager.LayoutParams getParamsForOpenWebView() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.START | Gravity.TOP;
params.x = left;
params.y = top;
return params;
} else {
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.START | Gravity.TOP;
params.x = left;
params.y = 200;
return params;
}
}
If I connect the phone to my laptop and use the laptop keyboard to add inputs to the input field, it works fine but it's just that the keyboard on the phone does not pop-up.
Also, the input is inside the webView therefore I cannot use View.requestFocus() to get focus unlike in case of an EditText.
I would really appreciate any help regarding how to request focus to the webView to allow inputs.
Found an answer to the question myself after a while.
I tried a lot of combinations of different flags but none worked, unless I tried
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
These flags gave the results I wanted and hope it helps someone who goes through the same.
I'm using a transparent screenoverlay to detect when a user long presses the power key of their phone (or rather, when the shutdown option dialog appears), this is working fine.
Unfortunately, when this screenoverlay is active, the soft keyboard stops appearing and that is a problem for me. How can I prevent that?
The code I'm using is heavily based on this: Detect power button long press
public void warnOnShutdown() {
if (Settings.canDrawOverlays(this)) {
LinearLayout linearLayout = new LinearLayout(getApplicationContext()) {
public void onCloseSystemDialogs(String reason) {
if ("globalactions".equals(reason)) {
AntitheftStateManager.setShuttingDown(AntitheftService.this, true);
}
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
return super.dispatchKeyEvent(event);
}
};
linearLayout.setFocusable(true);
View view = LayoutInflater.from(this).inflate(R.layout.system_overlay, linearLayout);
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
//params
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
100,
100,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
windowManager.addView(view, params);
}
}
Layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="1dp"
android:layout_height="1dp"
android:orientation="vertical">
</LinearLayout>
Edit:
I should probably mention that the LinearLayout is attached to the window manager from a service, that means that the keyboard is not just blocked for my app, it's blocked for the whole phone as long as the service is running.
That's what happens when someone elses code is taken at face value. Turns out that changing the type from TYPE_SYSTEM_ALERT to TYPE_SYSTEM_OVERLAY solved my problem.
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
100,
100,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT);
I am showing a popup screen when the screen is locked when some event happens.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Problem is - after a lot of frustration I found this answer, saying that this doesn't work when the activity is using a Theme.Dialog.
I want my activity to not be full screen, its suppose to be more or less like a sms popup notification. how can I do that without the Theme.Dialog Theme?
Not sure if this is what you're looking for, but this wraped everything in the window that pops up for me:
Key part of code is 'WRAP_CONTENT':
WindowManager mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
View mView = View.inflate(getApplicationContext(), R.layout.dialogue_page, null);
WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.RGBA_8888);
mWindowManager.addView(mView, mLayoutParams);
I'm trying to make a custom navigation button and have disabled the default navigation buttons provided by android by rooting my device. I want my custom navigation buttons to disappear after some interval of time (say 5 seconds). I have managed to do so. I want to make something such that whenever I touch anywhere on the screen, I can detect the touch event and show my navigation bar. Whether I'm on homescreen or any application, I can receive touch event. Is there a way to do so or do I need to go android source code?
Thank you
OnCreate of your Service: used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag.
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
Now, you will start getting each and every click event.
see this Creating a system overlay window (always on top)
I made a View in service which runs always on top of every application in android.
Initially, the behaviour of service is TYPE_SYSTEM_ALERT .
WindowManager.LayoutParams layparams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
layparams .gravity = Gravity.CENTER_VERTICAL| Gravity.CENTER_HORIZONTAL;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(serviceView, layparams );
I am changing the behaviour of service at run time means switching between TYPE_SYSTEM_ALERT AND TYPE_SYSTEM_OVERLAY on touch. Switch take place when I touch outside the view parameters and when touch inside the view parameters.
layparams .type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
Using updateViewLayout(serviceView, layparams )
PROBLEM: Is when I touch outside of view , the first touch just activate TYPE_SYSTEM_OVERLAY and after then outside app works fine. When TYPE_SYSTEM_OVERLAY is working , after that when you touch within the view it will trigger the action of object behind the view not the action of the view. But when u once touch the view TYPE_SYSTEM_ALERT will be applied and now the View will behave normally .
Current Implementation : I have to touch twice to work that particular thing when switch take place between layout parameters.
use this one... works perfectly on ICS and above
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;//This one is necessary.
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
params.gravity = Gravity.TOP | Gravity.RIGHT;
params.x = 0;
params.y = -params.height;
windowManager.addView(tile, params);
you can do this by calling updateViewLayout() on instance of WindowManager class.
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
// create new layout params
WindowManager.LayoutParams newlayparams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
//update new layout
wm.updateViewLayout(serviceView, newlayparams);
Hope it help!