I want to show an overlay view at some specific bound in screen ( like Rect(30,60,200, 400)). My code always gives a fullscreen overlay view, not the desired rect with specific top left, width, height.
My layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#50018786"/>
</RelativeLayout>
Main Activity code:
public class MainActivity extends AppCompatActivity {
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
} else {
onAuthorizedOverlay();
}
}
private void onAuthorizedOverlay() {
Button button = findViewById(R.id.inflate_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);
// params.x = 30; // these code have no effect
// params.y = 60;
// params.width = 170;
// params.height = 340;
Rect r = new Rect(30,60,200, 400);
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
RelativeLayout mTopView = (RelativeLayout) li.inflate(R.layout.my_overlay, null);
windowManager.addView(mTopView, params);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
} else {
// Do as per your logic
onAuthorizedOverlay();
}
}
}
}
I noticed that the commented code I made for params has no effect.
How can I show an overlay view at a certain rect?
You are not using mentioned rectangle anywhere.
Check this out.
private void onAuthorizedOverlay() {
Button button = findViewById(R.id.inflate_button);
button.setOnClickListener(view -> {
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
RelativeLayout mTopView = (RelativeLayout) li.inflate(R.layout.my_overlay, null);
WindowManager.LayoutParams overlayParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
overlayParams.height = 100;
overlayParams.width = 200;
overlayParams.x = 300;
overlayParams.y = 400;
windowManager.addView(mTopView, overlayParams);
});
}
Related
Below code snippet only shows view but click on buttons not working. I have tried all solution but nothing seems to work. Another service have same code fragment with different layout works.
public int onStartCommand(final Intent intent, int flags, int startId) {
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
if (inflater!=null)
v = inflater.inflate(R.layout.layout_accept_sos, null);
close = v.findViewById(R.id.close);
close.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onDestroy();
}
});
getDirection = v.findViewById(R.id.getDirection);
getDirection.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent1=new Intent();
intent1.setAction("open_map");
sendBroadcast(intent1);
// onDestroy();
}
});
params = new WindowManager.LayoutParams(LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 0;
params.y = 0;
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(v, params);
return START_STICKY;
}
You need to use WindowManager.FLAG_NOT_FOCUSABLE to make it clickable.
params = new WindowManager.LayoutParams(LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
More description available at https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_NOT_FOCUSABLE
I want to create system overlay view, which detect gestures without blocking other apps. How can i do it (apps like OmniSwipe, Easy Swipe detect gestures without blocking anything)? Below code, which blocking other apps cause of system overlay view.
package com.carxsing.anglelockscreen.GestureDetector;
public class GestureService extends Service implements
GestureOverlayView.OnGesturePerformedListener{
private WindowManager windowManager;
private GestureOverlayView GestureOverlay, GestureOverlay2;
private GestureLibrary mGestureLib;
public GestureService() {
}
#Override public IBinder onBind(Intent intent) {
return null;
}
#Override public void onCreate() {
super.onCreate();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
GestureOverlay = new GestureOverlayView(this);
GestureOverlay2 = new GestureOverlayView(this);
GestureOverlay.setGestureColor(00000000);
GestureOverlay.setUncertainGestureColor(00000000);
GestureOverlay2.setGestureColor(00000000);
GestureOverlay2.setUncertainGestureColor(00000000);
GestureOverlay.addOnGesturePerformedListener(this);
GestureOverlay2.addOnGesturePerformedListener(this);
mGestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!mGestureLib.load()) {
mGestureLib.save();
}
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
params.height = 450;
params.width = 75;
params.gravity = Gravity.BOTTOM | Gravity.LEFT;
windowManager.addView(GestureOverlay, params);
params.height = 450;
params.width = 75;
params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
windowManager.addView(GestureOverlay2, params);
}
#Override
public void onDestroy() {
super.onDestroy();
if (GestureOverlay != null) windowManager.removeView(GestureOverlay);
if (GestureOverlay2 != null) windowManager.removeView(GestureOverlay2);
}
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = mGestureLib.recognize(gesture);
if (predictions.size() > 0) {
Prediction prediction = predictions.get(0);
if (prediction.score > 1.0) {
if (prediction.name.equals(Gestures.bottomleft) || prediction.name.equals(Gestures.bottomright)) {
Intent i = new Intent(GestureService.this, LockScreenActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("start", 1);
startActivity(i);
}
}
}
}
}
In an android application I have to show an internal notification that comes over the top of every screen in my app . I have used WindowManager. But it doesn't seem to work as expected. Sometimes I see the first notification but the second is not shown though when debugged ,step by step execution of the following method is visible. Can't figure out why is this happening. Help!!
public void addNotification(String message, Bundle bundle) {
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.END | Gravity.BOTTOM;
lp.x = getResources().getInteger(R.integer.notification_side_margin);
lp.y = getResources().getInteger(R.integer.notification_side_margin);
// Initialise container view first in which every notification is to be
// added.
if (notificationConatinerView == null) {
notificationConatinerView = getLayoutInflater().inflate(
R.layout.custom_notification_main_layout, null);
notificationContainer = (LinearLayout) notificationConatinerView
.findViewById(R.id.notification_container);
notificationContainer.setPadding(
(int) getResources().getDimension(R.dimen.mini_margin),
(int) getResources().getDimension(R.dimen.mini_margin),
(int) getResources().getDimension(R.dimen.mini_margin),
(int) getResources().getDimension(R.dimen.mini_margin));
windowManager.addView(notificationConatinerView, lp);
// Add that container to the window manager
windowManager.updateViewLayout(notificationConatinerView, lp);
}
final View view = getLayoutInflater().inflate(
R.layout.notification_custom, null);
view.setTag(bundle);
view.setId(notificationContainer.getChildCount());
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = (Bundle) v.getTag();
setClickForNotifications(bundle);
}
});
final ImageView crossImage = (ImageView) view
.findViewById(R.id.notification_cross);
crossImage.setTag(view);
TextView messageTextView = (TextView) view
.findViewById(R.id.message_text);
messageTextView.setText(message);
crossImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (notificationContainer.getChildCount() == 1) {
showNotificationExitingView(v);
} else {
if (!isFinishing())
notificationContainer.removeView((View) crossImage
.getTag());
}
}
});
LinearLayout.LayoutParams childLP = new LinearLayout.LayoutParams(
(int) getResources().getDimension(
R.dimen.notification_view_width),
RelativeLayout.LayoutParams.WRAP_CONTENT);
if (notificationContainer.getChildCount() == getResources().getInteger(
R.integer.no_of_notifications)) {
notificationContainer.removeViewAt(notificationContainer
.getChildCount() - 1);
}
notificationContainer.addView(view, 0, childLP);
notificationContainer.updateViewLayout(view, childLP);
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (notificationContainer.getChildCount() == 1) {
showNotificationExitingView(view);
} else {
if (!isFinishing())
notificationContainer.removeView(view);
}
}
}, 10000);
try {
windowManager.updateViewLayout(notificationConatinerView, lp);
} catch (Exception e) {
windowManager.addView(notificationConatinerView, lp);
windowManager.updateViewLayout(notificationConatinerView, lp);
}
if (notificationContainer.getChildCount() == 1) {
showNotificationEnteringAnimation();
}
}
Thanks!!
use
windowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
instead of
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
I am trying to display a webview inside popupwindow which is being displayed by a service. When a user
touch on an image displayed by a service then a popupwindow should appear displaying a webview in it.
The code for the whole process is given below:
ChatHeadService.java
public class ChatHeadService extends Service {
private WindowManager windowManager;
float screenWidth=0, screenHeight=0;
private ImageView chatHead;
WindowManager.LayoutParams params;
WebView popUpWebView;
private static final int MAX_CLICK_DURATION = 200;
private long startClickTime;
private GestureDetector gestureDetector;
#Override public IBinder onBind(Intent intent) {
// Not used
return null;
}
#Override public void onCreate() {
super.onCreate();
screenWidth= getResources().getDisplayMetrics().widthPixels;
screenHeight= getResources().getDisplayMetrics().heightPixels;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 0;
chatHead = new ImageView(this);
chatHead.setImageResource(R.drawable.ic_launcher);
windowManager.addView(chatHead, params);
addChatHeadListener();
}
public void addChatHeadListener(){
chatHead.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
showPopUpWindow();
}
});
}
public void showPopUpWindow(){
LayoutInflater layoutInflater = (LayoutInflater)getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.popupwindow, null);
final PopupWindow popupWindow = new PopupWindow(popupView,
(int)screenWidth,
(int)screenHeight);
popupWindow.setFocusable(true);
popupWindow.setBackgroundDrawable (new BitmapDrawable());
popUpWebView = (WebView) popupView.findViewById(R.id.idWebView1);
popUpWebView.getSettings().setJavaScriptEnabled(true);
popUpWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
popupWindow.showAsDropDown(chatHead, 0, 0);
popUpWebView.loadUrl("http://wwww.google.co.in");
}
}
And here is my xml file
popupwindow.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ffffff" >
<WebView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:id="#+id/idWebView1"/>
</LinearLayout>
Problem is nothing displayed when i clicked on the icon but when i use textview instead of webview
it diplayed textview successfully.
I hava a app, it will receive msg from server and make a dialog to user.So when phone is on lock screen i want dialog will show on the top of lock screen but not unlock it.could anyone give me suggestion ?
I solved something similar in the following way.
Create services, to broadcast the action "ACTION_SCREEN_ON & ACTION_USER_PRESENT & ACTION_SCREEN_OFF", create function to show the windows with WINDOW_SERVICE. I use a service for my requirements, but it can adapt.
public class OverlayService extends Service {
private static final String TAG = OverlayService.class.getSimpleName();
WindowManager mWindowManager;
View mView;
Animation mAnimation;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerOverlayReceiver();
return super.onStartCommand(intent, flags, startId);
}
private void showDialog(String aTitle){
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mView = View.inflate(getApplicationContext(), R.layout.fragment_overlay, null);
mView.setTag(TAG);
int top = getApplicationContext().getResources().getDisplayMetrics().heightPixels / 2;
RelativeLayout dialog = (RelativeLayout) mView.findViewById(R.id.dialog);
LayoutParams lp = (LayoutParams) dialog.getLayoutParams();
lp.topMargin = top;
lp.bottomMargin = top;
mView.setLayoutParams(lp);
ImageButton imageButton = (ImageButton) mView.findViewById(R.id.close);
lp = (LayoutParams) imageButton.getLayoutParams();
lp.topMargin = top - 58;
imageButton.setLayoutParams(lp);
imageButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mView.setVisibility(View.INVISIBLE);
}
});
TextView title = (TextView) mView.findViewById(R.id.Title);
title.setText(aTitle);
final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
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);
mView.setVisibility(View.VISIBLE);
mAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.in);
mView.startAnimation(mAnimation);
mWindowManager.addView(mView, mLayoutParams);
}
private void hideDialog(){
if(mView != null && mWindowManager != null){
mWindowManager.removeView(mView);
mView = null;
}
}
#Override
public void onDestroy() {
unregisterOverlayReceiver();
super.onDestroy();
}
private void registerOverlayReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(overlayReceiver, filter);
}
private void unregisterOverlayReceiver() {
hideDialog();
unregisterReceiver(overlayReceiver);
}
private BroadcastReceiver overlayReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "[onReceive]" + action);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
showDialog("Esto es una prueba y se levanto desde");
}
else if (action.equals(Intent.ACTION_USER_PRESENT)) {
hideDialog();
}
else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
hideDialog();
}
}
};
}
I hope it useful!
public void onAttachedToWindow() {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
Finally I achieved the same. Don't go for activity, because android will not show lock screen behind your activity for security reason, so use service instead of Activity.
Below is my code in onStartCommand of my service
WindowManager mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
View mView = mInflater.inflate(R.layout.score, 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);
And add <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> to manifest