检测android中的用户活动

时间:2014-01-21 19:28:33

标签: android user-interaction

我想检测用户最后一次与屏幕交互的时间。我对任何恶意软件/间谍软件都不感兴趣,只需要计算自用户上次点击屏幕以来经过了多长时间。

目标是实现类似的功能

我一直在做一些研究,并在网站上关注一些Q& A(例如Android Best Way to Detect and Handle User INACTIVITYAndroid: Detect General Use by User等)但是当涉及到检测用户在android中的互动时我就没有了找到了我需要的东西。

提前致谢。

4 个答案:

答案 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的回答)

相关问题