我想检测用户最后一次与屏幕交互的时间。我对任何恶意软件/间谍软件都不感兴趣,只需要计算自用户上次点击屏幕以来经过了多长时间。
目标是实现类似的功能
。我一直在做一些研究,并在网站上关注一些Q& A(例如Android Best Way to Detect and Handle User INACTIVITY,Android: Detect General Use by User等)但是当涉及到检测用户在android中的互动时我就没有了找到了我需要的东西。
提前致谢。
答案 0 :(得分:9)
经过一些研究和测试后,我成功地找到了解决方案。
我所做的是创建一个后台服务,在其中我获得了一个WindowManager实例,并添加了一个零大小的视图,该视图得到了用户的通知 触摸它之外...但由于视图的大小为零,因此每次都可以调用它。 为此,我们可以检查https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html
每次用户点击屏幕并将其写入首选项时, InactivityService.java 类都会检测到它,以便稍后在应用的其他组件中显示或使用它。 注意我们可以广播时间,或者将其传递给我们的app对象或任何其他适合或需要的解决方案,这是有效的。
/**
* Detects user taps on screen (user interaction).
*
* @author Junior Buckeridge A.
*
*/
public class InactivityService extends Service {
protected static final String LOG_TAG = InactivityService.class.getSimpleName();
private boolean isAdded = false;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!isAdded){
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
0, 0, 0, 0,
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);
View view = new View(this);
view.setOnTouchListener(new OnTouchListener() {
@SuppressLint("DefaultLocale")
@Override
public boolean onTouch(View v, MotionEvent event) {
GregorianCalendar calendar = new GregorianCalendar();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(InactivityService.this);
String log = prefs.getString(LOG_KEY, "");
log = String.format("User interaction detected at: %02d:%02d:%02d \n%s",
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND),
log);
prefs.edit().putString(LOG_KEY, log).commit();
return false;
}
});
wm.addView(view, params);
}
return START_STICKY;
}
}
我们应该向清单添加以下权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
同样有效的是,此方法与使用 ActivityManager 获取正在运行的任务相结合,是确定用户是否与手机进行交互的一种非常有效的方法。
答案 1 :(得分:1)
您可以使用AccessibilityService,这样您就可以收听点击,滚动和其他互动事件。一个限制是它不会报告原始触摸事件,除非它们触发操作。
答案 2 :(得分:0)
我设法改进了Junior Buckeridge的解决方案,因此不再需要SYSTEM_ALERT_WINDOW权限。想法是一样的:我们添加一个接收所有onpress事件的视图。但是我的解决方案只是在活动的onCreate中添加了这个视图,并在创建LayoutParams时使用WindowManager.LayoutParams.TYPE_APPLICATION而不是WindowManager.LayoutParams.TYPE_SYSTEM_ALERT。
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);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
View view = new View(this);
view.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("DefaultLocale")
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("Test", "Hello World!");
return false;
}
});
wm.addView(view, params);
答案 3 :(得分:0)
所以我使用@Junior Buckeridge解决方案,但实际上我遇到了崩溃,因为我们不允许绘制应用程序窗口。 (不良令牌例外)
真正帮助我的是什么:
performSegue(withIdentifier: "accountSegue", sender: nil)
在您的活动中:
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//here is all the science of params
final LayoutParams myParams = new LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
PixelFormat.TRANSLUCENT
);
并添加:
if(Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(Activity.this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1234);
}
}else{
Intent intent = new Intent(Activity.this, Service.class);
startService(intent);
}
源: Android: Unable to add window. Permission denied for this window type (Anam Ansari的回答)