Sometimes this method for detecting user interaction doesn't work - android

my Android application has to detect the user interactions in order to use method A or method B in a loop.
I call this method in the onCreate() of the MainActivity...
#SuppressLint("ClickableViewAccessibility")
private void detectUserInteraction() {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
0, 0, 0, 0,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
final View view = new View(this);
view.setOnTouchListener((v, event) -> {
UserInteractionManager.getInstance().setRecentUserInteraction(true);
return false;
});
wm.addView(view, params);
}
}
...and is not working for a few part of the users (latest Huawei owners). I have the log files of these users and the method only works as I expected a few minutes.
Anyone has any idea to fix the issue of the method?
Thank you a lot.

Related

Android: how to add view to WindowManager, and keep it floating at the top of my app all the time?

I need a view to show up at the top of my application, and when it's shown, it can keep showing at the top of all my application's other view(all the fragment and activity). It sounds like a Floating Action Button, but will always show at the top of my app.
I know I can do it via adding view to my phone's WindowManager, and hide it when I quit my app, show it again when I resume my app. This tricky method can work, but it also require some additional permission, which is I am trying to avoid.
If I only want to show in my app, can I achieve it without asking additional permission from user? If the answer is yes, then how? The key seems like some LayoutParams for the view, I tried but failed.
Would be nice if answer can show some detail code and explanation.
You have to use WindowManager for this purpose
First add permission in manifest
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Add image which you want to appear.
chatheadImg = (ImageView)chatheadView.findViewById(R.id.chathead_img);
Then make the service and add window manager to it.
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.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
And just register touch events on view
chatheadView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//To do
break;
case MotionEvent.ACTION_MOVE:
break;
});
check these tutorials for better understanding
http://www.androidhive.info/2016/11/android-floating-widget-like-facebook-chat-head/
https://github.com/henrychuangtw/Android-ChatHead
adding this permission in manifest
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater layoutInflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutView = layoutInflater.inflate(R.layout.ringing_layout, null);
phoneTv = layoutView.findViewById(R.id.phone);
Log.d("TAG", "showLayout: " + phoneTv );
p = new WindowManager.LayoutParams(
// Shrink the window to wrap the content rather than filling the screen
600, 600,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
layoutView.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
windowManager.removeView(layoutView);
}
});
p.gravity = Gravity.CENTER | Gravity.CENTER;
p.x = 0;
p.y = 0;
windowManager.addView(layoutView, p);
Log.d("TAG", "showLayout: ");

I want to create e view which has gesture overlay in it and this view can be called any where outside of an app. [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have created chathead that floats on the screen but how to call the view from it. Have been searching for this from long time.
want to make a view like this
this is the view I have been trying to make. it has gesture Overlay in itGesture Magic this app is using this view
The concept is simple, you basically need to create a Service that will dynamically manage your view by adding/removing it to the window manager.
public class StandOutViewService extends Service {
private WindowManager mWindowManager;
private View mStandOutView;
#Override
public void onCreate() {
super.onCreate();
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mStandOutView = new View(this);
WindowManager.LayoutParams 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 = 100;
params.y = 500;
mWindowManager.addView(mStandOutView, params);
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
You can check out this library to get a starting point:
https://github.com/pingpongboss/StandOut
Please be aware that you need to handle permissions by using:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
and for Android 6 and above you may need to instruct your users to active your service from the accessibility settings menu.
I found the answer and thought to share with you guys hope it will help
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
900,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.x=0;
if (FloatDirections.y>700){
params.y=FloatDirections.y-700;}
else {
params.y=0;
}
params.gravity= Gravity.TOP|Gravity.CENTER;
serviceRunning=true;
Toast.makeText(getApplicationContext(),String.valueOf(FloatDirections.x)+" "+String.valueOf(FloatDirections.y),Toast.LENGTH_SHORT).show();
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
myView = inflater.inflate(R.layout.gesture_recognition, null);
b11=(Button)myView.findViewById(R.id.newbtn);
GestureOverlayView ov = (GestureOverlayView)myView.findViewById(R.id.gestures_overlay_float);
ov.addOnGesturePerformedListener(this);
and then use OnGesturePerformed
#Override
public void onGesturePerformed(GestureOverlayView gestureOverlayView, Gesture gesture) {
// Toast.makeText(getApplicationContext(),"hi",Toast.LENGTH_SHORT).show();
mydatabase.execSQL("CREATE TABLE IF NOT EXISTS PackageName(GestureName VARCHAR,PackName VARCHAR,Action VARCHAR);");
cursor=mydatabase.rawQuery("select * from PackageName",null);
ArrayList<Prediction> predictions = store.recognize(gesture);

Block touch from a service

Is there a way to block touch on ANY application from a service? I've been thinking about getWindow(), but that is impossible in service. Also, I've been thinking about getting current activity and then use getWindow(). I hope you get the point of what am I tried to achieve.
Thanks to David Medenjak I have managed to solve the problem. This solution is working on Android APIs below 23 and it's going to make the screen black and block touches until you longpress on the screen.
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
ImageView black = new ImageView(this);
black.setImageResource(R.drawable.black);
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,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 0;
windowManager.addView(black, params);
black.getLayoutParams().height = windowManager.getDefaultDisplay().getHeight();
black.getLayoutParams().width = windowManager.getDefaultDisplay().getWidth();
black.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
return false;
}
});

How to get a clickable and moveable imageview just like Facebook messenger?

I want an imageview for my app just like fb messenger chat header which will be shown everywhere when the app is running in background and we are working on another app. I have seen some codes but they just make it visible at a fixed position not movable the code is here and i have just used textview for the time being instead of imageview.
public void onCreate() {
super.onCreate();
//mView = new HUDView(this);
mButton = new Button(this);
mButton.setText("Overlay button");
mButton.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getApplicationContext(),"Overlay button event", Toast.LENGTH_SHORT).show();
return false;
}
});
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.CENTER;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mButton, params);
}
Any help would be appreciated.
The link of Lalit Poptani is good. You have to use a service for this kind of feature.
Please, look the example form Waza_Be, here: https://stackoverflow.com/a/15980900/5098294

Android system overlay not shown outside my app

I need to show a system overlay window on top of any running apps. It works fine, but only when my app's activity is in foreground. Here is the code I use:
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_DIM_BEHIND |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER | Gravity.TOP;
params.dimAmount = 0.3f;
wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
mainAlertView = View.inflate(ctx, R.layout.system_alert_view, null);
wm.addView(mainAlertView, params);
The view added to WindowManager contains empty LinearLayout to which I add child views at runtime:
mainAlertLayout.addView(childView);
Manifest xml has SYSTEM_ALERT_WINDOW permission defined:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
It all works magnificently while my activity is running in foreground. As soon as I switch to any other app or home screen no overlay is shown. I debugged the code, and it indeed is running wm.addView(), and its not throwing any exceptions. I also played around with LayoutParams flags (removed KEEP_SCREEN_ON and related etc), but nothing made any difference.
Android 4.4.2 fwiw
You need to create a service to keep the system overlay( alert) to show even when your application closed.
Create a simple service , I will call as FloatingService , which will show the overlay(alert) when onStartCommand is called . Return START_STICKY to keep the service run in background.
public class FloatingService extends Service {
private WindowManager windowManager;
private View floatingView;
WindowManager.LayoutParams params;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flag, int startId){
// show the alert her
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// use your custom view here
floatingView = View.inflate(getBaseContext(),R.layout.floating_layout,null); //floatingView.setOnTouchListener(mOnTouchListener);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER | Gravity.CENTER;
// add the view to window manger
windowManager.addView(floatingView, params);
return START_STICKY;
}
}
Add an listener to the view so that you can close the overlay(alert) when required
floatingView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
windowManager.removeView(floatingView);
floatingView = null;
}
});
Finally , register the service in manifest
<service android:name="com.example.app.services.FloatingService" />
And System Alert permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
The problem was that I was running addView() call in main view's post() method:
mainView.post(new Runnable() {
public void run() {
wm.add(mainView);
}
);
Instead if I just run it in main thread it works fine. I use de.greenrobot.eventbus and its very simple to post Runnable to event bus and ensure it executes in main thread:
public void onEventMainThread(UIRunnableEvent event) {
event.r.run();
}
public static class UIRunnableEvent {
protected Runnable r;
protected UIRunnableEvent(Runnable r) {
this.r = r;
}
}

Categories

Resources