setAlpha behaving weird - android

I have added a view with special params using windowmanager, it overlays the screen and I am trying to change the alpha of this view using a seekbar. I have tried changing the alpha of a button just to test my code, and it works properly, but when I try to change the alpha of the overlay view, it just changes colour to a transparent black (it is normally transparent pink or yellow). I was hoping to change the opacity of the yellow or pink, but it does not seem to work that way. I think it is because of the special params, or the fact that it is added using windowmanager. The float alpha = intent.getExtras().getFloat("alpha"); is passed down from my main activity and is the progress of my seekbar(max = 100)/100 so it ends up being a value of 0.0 to 1.0. If anybody has any ideas let me know, thanks. Here is the service:
`public class DrawOverAppsService extends Service {
public static final String TAG = "DrawOverAppsService";
View mOverlayView;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN|
WindowManager.LayoutParams.FLAG_DIM_BEHIND,
PixelFormat.TRANSLUCENT);
// An alpha value to apply to this entire window.
// An alpha of 1.0 means fully opaque and 0.0 means fully transparent
params.alpha = 0.2F;
// When FLAG_DIM_BEHIND is set, this is the amount of dimming to apply.
// Range is from 1.0 for completely opaque to 0.0 for no dim.
params.dimAmount = 0.5F;
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mOverlayView = inflater.inflate(R.layout.overlay_view, null);
wm.addView(mOverlayView, params);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mOverlayView != null) {
Boolean isBlack = intent.getExtras().getBoolean("black");
Boolean isPink = intent.getExtras().getBoolean("pink");
Boolean isOrange = intent.getExtras().getBoolean("orange");
Boolean isAlpha = intent.getExtras().getBoolean("isAlpha");
if(isBlack == true) {
mOverlayView.setBackgroundColor(Color.parseColor("#000000"));
}
if(isPink == true) {
mOverlayView.setBackgroundColor(Color.parseColor("#3d0d00"));
}
if(isOrange == true) {
mOverlayView.setBackgroundColor(Color.parseColor("#3d2f00"));
}
if (isAlpha == true) {
float alpha = intent.getExtras().getFloat("alpha");
mOverlayView.getBackground().setAlpha((int)alpha);
//mOverlayView.setAlpha(intent.getExtras().getFloat("alpha"));
}
}
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.removeView(mOverlayView);
}
}`

Open()
mOverlayView .animate().scaleX(1.0f).scaleY(1.0f).setDuration(200)
.start();
mOverlayView .setAlpha(0.5f);
Close()
mOverlayView .animate().scaleX(0f).scaleY(0f).setDuration(200).start();

Related

Android : disable swipe down and view wifi/airplane mode

How can I disable users can swipe down the title/notification bar as seen in the picture below. I want my app run in kiosk mode and my users must not be able to swipe down or anything else.
I tried using setting some flags but all I get is some kind of kiosk mode but users can still view the wifi/airplane etc screen on swipe down.
Please help, I can not find a good answer on Stackoverflow
I don not want my users can see the screen below.
Refer to this answer here
or
private void disablePullNotificationTouch() {
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (25 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.RGBX_8888;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
}
//Add this class in your project
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}

How comes that this code hangs after 1 hour?

I am running this code after every 30 second and after running app coninute 1 hour my phone and app hung up and i need to restart it again.
private void preventStatusBarExpansion(Context context) {
WindowManager manager = ((WindowManager)
context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
Activity activity = (Activity) context;
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = activity.getResources().getDimensionPixelSize(resId);
}
localLayoutParams.height = result;
localLayoutParams.format = PixelFormat.TRANSPARENT;
CustomViewGroup view = new CustomViewGroup(context);
manager.addView(view, localLayoutParams);
}
public class CustomViewGroup extends ViewGroup {
public CustomViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
You're effectively calling the following calls every 30 seconds.
CustomViewGroup view = new CustomViewGroup(context);
manager.addView(view, localLayoutParams);
This creates and adds a view every 30 seconds, so it will surely scrape out the memory when being run for long durations. You should clearly remove the view once it is not required. Otherwise you're repeatedly stacking up the memory with the new views.

Developing Android application with same result as Settings ->Developer options ->Show touch data

I want to develop an independent application to find user touch events(Similar to Settings>Developer Options>Show touch Data).
I have used WindowManager with type set to TYPE_SYSTEM_ALERT and flag set with FLAG_WATCH_OUTSIDE_TOUCH.
Here i am getting the user touch coordinates but, the touch is not passed on to the below window to open the corresponding touched application.
Please suggests me on how I can get the required result.
Below is the service which does the work.
public class HUD extends Service {
HUDView mView;
// #Override
// public IBinder onBind(Intent intent) {
// return null;
// }
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_SHORT).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
// WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_SHORT).show();
if(mView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
mView = null;
}
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
class HUDView extends ViewGroup {
private Paint mLoadPaint;
public HUDView(Context context) {
super(context);
Toast.makeText(getContext(),"HUDView", Toast.LENGTH_SHORT).show();
mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setTextSize(10);
mLoadPaint.setARGB(255, 255, 0, 0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText("Hello World", 5, 15, mLoadPaint);
}
#Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
}
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
Toast.makeText(getContext(),"X= "+ event.getX()+"Y= "+event.getY(), Toast.LENGTH_SHORT).show();
return true;
}
}
Here i am getting the user touch coordinates but, the touch is not passed on to the below window to open the corresponding touched application.
Fortunately, what you want is not possible on Android 4.0+, for privacy and security reasons. What you are proposing is the malware technique referred to as "tapjacking".

Android : How to show dialog or activity over lock screen[ not unlock the screen]

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

Creating a system overlay window (always on top)

I'm trying to create an always-op-top button/clickable-image
which stays on top of all the windows all the time.
The proof of
concept is
here - Smart Taskbar (on AppBrain)
and here V1.4.0 Sidebar style SWKey - Button savior (on xda-developers)
I have been successful and have a running service now. The service
displays some text on top left corner of screen all the time while
user can freely interact with rest of apps in normal manner.
What I'm
doing is subclass ViewGroup and add it to root window manager with
flag TYPE_SYSTEM_OVERLAY. Now I want to add a button/clickable-image
in place of this text which can receive touch events on itself. I
tried overriding "onTouchEvent" for the whole ViewGroup but it does
not receive any event.
How can I receive events only on certain parts
of my always-on-top view group? Kindly suggest.
public class HUD extends Service {
HUDView mView;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#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.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
if(mView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
mView = null;
}
}
}
class HUDView extends ViewGroup {
private Paint mLoadPaint;
public HUDView(Context context) {
super(context);
Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();
mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setTextSize(10);
mLoadPaint.setARGB(255, 255, 0, 0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText("Hello World", 5, 15, mLoadPaint);
}
#Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
}
This might be a stupid solution. But it works. If you can improve it, please let me know.
OnCreate of your Service: I have used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag. This is the only change in service.
#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. So, you need to rectify in your event handler.
In your ViewGroup touch event
#Override
public boolean onTouchEvent(MotionEvent event) {
// ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
// THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
Also you may need to add this permission to your manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Following #Sam Lu's answer,
Indeed Android 4.x blocks certain types from listening to outside touch events, but some types, such as TYPE_SYSTEM_ALERT, still do the job.
Example
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View myView = inflater.inflate(R.layout.my_view, null);
myView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "touch me");
return true;
}
});
// Add layout to window manager
wm.addView(myView, params);
Permissions
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Starting with Android 4.x, Android team fixed a potential
security problem by adding a new function adjustWindowParamsLw() in which it
will add FLAG_NOT_FOCUSABLE, FLAG_NOT_TOUCHABLE and remove FLAG_WATCH_OUTSIDE_TOUCH flags for TYPE_SYSTEM_OVERLAY windows.
That is, a TYPE_SYSTEM_OVERLAY window won't receive any touch event on ICS platform and, of course, to use TYPE_SYSTEM_OVERLAY is not a workable solution for ICS and future devices.
I'm one of the developers of the Tooleap SDK. We also provide a way for developers to display always on top windows and buttons, and and we have dealt with a similar situation.
One problem the answers here haven't addressed is that of the Android "Secured Buttons".
Secured buttons have the filterTouchesWhenObscured property which means they can't be interacted with, if placed under a window, even if that window does not receive any touches. Quoting the Android documentation:
Specifies whether to filter touches when the view's window is obscured
by another visible window. When set to true, the view will not receive
touches whenever a toast, dialog or other window appears above the
view's window. Refer to the {#link android.view.View} security
documentation for more details.
An example of such a button is the install button when you try to install third party apks. Any app can display such a button if adding to the view layout the following line:
android:filterTouchesWhenObscured="true"
If you display an always-on-top window over a "Secured Button", so all the secured button parts that are covered by an overlay will not handle any touches, even if that overlay is not clickable. So if you are planing to display such a window, you should provide a way for the user to move it or dismiss it.
And if a part of your overlay is transparent, take into account that your user might be confused why is a certain button in the underlying app is not working for him suddenly.
WORKING ALWAYS ON TOP IMAGE BUTTON
first of all sorry for my english
i edit your codes and make working image button that listens his touch event
do not give touch control to his background elements.
also it gives touch listeners to out of other elements
button alingments are bottom and left
you can chage alingments but you need to chages cordinats in touch event in the if element
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;
public class HepUstte extends Service {
HUDView mView;
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
final Bitmap kangoo = BitmapFactory.decodeResource(getResources(),
R.drawable.logo_l);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
kangoo.getWidth(),
kangoo.getHeight(),
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.BOTTOM;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mView = new HUDView(this,kangoo);
mView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
//Log.e("kordinatlar", arg1.getX()+":"+arg1.getY()+":"+display.getHeight()+":"+kangoo.getHeight());
if(arg1.getX()<kangoo.getWidth() & arg1.getY()>0)
{
Log.d("tıklandı", "touch me");
}
return false;
}
});
wm.addView(mView, params);
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
#SuppressLint("DrawAllocation")
class HUDView extends ViewGroup {
Bitmap kangoo;
public HUDView(Context context,Bitmap kangoo) {
super(context);
this.kangoo=kangoo;
}
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
// delete below line if you want transparent back color, but to understand the sizes use back color
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(kangoo,0 , 0, null);
//canvas.drawText("Hello World", 5, 15, mLoadPaint);
}
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
}
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
// Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
}
The TYPE_SYSTEM_OVERLAY constant was deprecated since API level 26.
Use TYPE_APPLICATION_OVERLAY instead.
For users below and above Android 8:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
Try this. Works fine in ICS.
If You want to stop service simply click the notification generated in statusbar.
public class HUD extends Service
{
protected boolean foreground = false;
protected boolean cancelNotification = false;
private Notification notification;
private View myView;
protected int id = 0;
private WindowManager wm;
private WindowManager.LayoutParams params;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
// System.exit(0);
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_SHORT).show();
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
params.gravity=Gravity.TOP|Gravity.LEFT;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
inflateview();
foregroundNotification(1);
//moveToForeground(1,n,true);
}
#Override
public void onDestroy() {
super.onDestroy();
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(0);
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_SHORT).show();
if(myView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(myView);
myView = null;
}
}
protected Notification foregroundNotification(int notificationId)
{
notification = new Notification(R.drawable.ic_launcher, "my Notification", System.currentTimeMillis());
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_ONLY_ALERT_ONCE;
notification.setLatestEventInfo(this, "my Notification", "my Notification", notificationIntent());
((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(id, notification);
return notification;
}
private PendingIntent notificationIntent() {
Intent intent = new Intent(this, stopservice.class);
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pending;
}
public void inflateview()
{
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
myView = inflater.inflate(R.layout.activity_button, null);
myView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getBaseContext(),"onToasttt", Toast.LENGTH_SHORT).show();
return false;
}
});
// Add layout to window manager
wm.addView(myView, params);
}
}
UPDATE
Sample here
To create an overlay view, when setting up the LayoutParams DON'T set the type to TYPE_SYSTEM_OVERLAY.
Instead set it to TYPE_PHONE.
Use the following flags:
FLAG_NOT_TOUCH_MODAL
FLAG_WATCH_OUTSIDE_TOUCH
Actually, you can try WindowManager.LayoutParams.TYPE_SYSTEM_ERROR instead of TYPE_SYSTEM_OVERLAY. It may sound like a hack, but it let you display view on top of everything and still get touch events.
Found a library that does just that:
https://github.com/recruit-lifestyle/FloatingView
There's a sample project in the root folder. I ran it and it works as required. The background is clickable - even if it's another app.
Here is some simple solution,
All you need is to inflate XML layout just like you do on list adapters,
just make XML layout to inflate it.
Here is code that all you need.
public class HUD extends Service {
View mView;
LayoutInflater inflate;
TextView t;
Button b;
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = wm.getDefaultDisplay(); get phone display size
int width = display.getWidth(); // deprecated - get phone display width
int height = display.getHeight(); // deprecated - get phone display height
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
width,
height,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER;
params.setTitle("Load Average");
inflate = (LayoutInflater) getBaseContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = inflate.inflate(R.layout.canvas, null);
b = (Button) mView.findViewById(R.id.button1);
t = (TextView) mView.findViewById(R.id.textView1);
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
t.setText("yes you click me ");
}
});
wm.addView(mView, params);
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
It uses permission "android.permission.SYSTEM_ALERT_WINDOW" full tutorial on this link : http://androidsrc.net/facebook-chat-like-floating-chat-heads/
This is an old Question but recently Android has a support for Bubbles. Bubbles are soon going to be launched but currently developers can start using them.They are designed to be an alternative to using SYSTEM_ALERT_WINDOW. Apps like (Facebook Messenger and MusiXMatch use the same concept).
Bubbles are created via the Notification API, you send your notification as normal. If you want it to bubble you need to attach some extra data to it. For more information about Bubbles you can go to the official Android Developer Guide on Bubbles.
Well try my code, atleast it gives you a string as overlay, you can very well replace it with a button or an image. You wont believe this is my first ever android app LOL. Anyways if you are more experienced with android apps than me, please try
changing parameters 2 and 3 in "new WindowManager.LayoutParams"
try some different event approach
If anyone still reading this thread and not able to get this working, I'm very sorry to tell you this way to intercept motion event is considered as bug and fix in android >=4.2.
The motion event you intercepted, although has action as ACTION_OUTSIDE, return 0 in getX
and getY. This means you can not see all the motion position on screen, nor can you do anything. I know the doc said It will get x and y, but the truth is it WILL NOT. It seems that this is to block key logger.
If anyone do have a workaround, please leave your comment.
ref:
Why does ACTION_OUTSIDE return 0 everytime on KitKat 4.4.2?
https://code.google.com/p/android/issues/detail?id=72746
by using service you can achieve this :
public class PopupService extends Service{
private static final String TAG = PopupService.class.getSimpleName();
WindowManager mWindowManager;
View mView;
String type ;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// registerOverlayReceiver();
type = intent.getStringExtra("type");
Utils.printLog("type = "+type);
showDialog(intent.getStringExtra("msg"));
return super.onStartCommand(intent, flags, startId);
}
private void showDialog(String aTitle)
{
if(type.equals("when screen is off") | type.equals("always"))
{
Utils.printLog("type = "+type);
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
WakeLock mWakeLock = pm.newWakeLock((PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "YourServie");
mWakeLock.acquire();
mWakeLock.release();
}
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mView = View.inflate(getApplicationContext(), R.layout.dialog_popup_notification_received, null);
mView.setTag(TAG);
int top = getApplicationContext().getResources().getDisplayMetrics().heightPixels / 2;
LinearLayout dialog = (LinearLayout) mView.findViewById(R.id.pop_exit);
// android.widget.LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) dialog.getLayoutParams();
// lp.topMargin = top;
// lp.bottomMargin = top;
// mView.setLayoutParams(lp);
final EditText etMassage = (EditText) mView.findViewById(R.id.editTextInPopupMessageReceived);
ImageButton imageButtonSend = (ImageButton) mView.findViewById(R.id.imageButtonSendInPopupMessageReceived);
// lp = (LayoutParams) imageButton.getLayoutParams();
// lp.topMargin = top - 58;
// imageButton.setLayoutParams(lp);
imageButtonSend.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Utils.printLog("clicked");
// mView.setVisibility(View.INVISIBLE);
if(!etMassage.getText().toString().equals(""))
{
Utils.printLog("sent");
etMassage.setText("");
}
}
});
TextView close = (TextView) mView.findViewById(R.id.TextViewCloseInPopupMessageReceived);
close.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
hideDialog();
}
});
TextView view = (TextView) mView.findViewById(R.id.textviewViewInPopupMessageReceived);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
hideDialog();
}
});
TextView message = (TextView) mView.findViewById(R.id.TextViewMessageInPopupMessageReceived);
message.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);
mWindowManager.addView(mView, mLayoutParams);
mWindowManager.updateViewLayout(mView, mLayoutParams);
}
private void hideDialog(){
if(mView != null && mWindowManager != null){
mWindowManager.removeView(mView);
mView = null;
}
}
}
#Sarwar Erfan's answer does not work any longer as Android does not allow adding view with WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY to window to be touchable anymore not with even WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH.
I found solution to this problem. You can check it out in following question
When adding view to window with WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, it is not getting touch event
TYPE_SYSTEM_OVERLAY is deprecated and will give a permission denied error.
Use WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY instead.
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL might be what you're looking for.
Window flag: even when this window is focusable (its FLAG_NOT_FOCUSABLE is not set), allow any pointer events outside of the window to be sent to the windows behind it. Otherwise it will consume all pointer events itself, regardless of whether they are inside of the window.
Docs
Implement View.OnClickListener or View.onTouchListener to listen for touch events.

Categories

Resources