1

当我的应用程序当前处于后台时,我需要知道检测 android 设备何时空闲了一段时间(如果它空闲,请将我的应用程序放在前面)。我能想到的唯一两种方法是:

  1. 以某种方式检测应用程序之外的用户交互,如果 X 分钟内没有任何输入,请将我的应用程序放在前面。

    或者:

  2. 当设备进入睡眠模式时,将我的应用程序放在前面。

我不知道怎么做,但 2 对我来说似乎是最可行的选择。这将是什么代码?

4

1 回答 1

2

我能够完成 1. 通过使用放置在所有视图之上的“透明”视图,它检查用户触摸

达到所需效果的步骤:

1) 创建一个 Service,它在其 onCreate 方法中创建透明视图并将其附加到视图堆栈
2) onStartCommand 调用 initTimer() 方法
3) 在服务上实现 View.OnTouchListener
4) 覆盖 onTouch 方法
5) 收到 onTouch 事件 -在服务的 onDestroy 上调用 initTimer()
6) - 从视图堆栈中删除透明视图
7) 在调用主活动的 onPause 时启动服务
8) 在应用程序打开时停止服务

这是代码:

private Handler mHandler;
private Runnable mRunnable;
private final int mTimerDelay = 60000;//inactivity delay in milliseconds
private LinearLayout mTouchLayout;//the transparent view

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

    mTouchLayout = new LinearLayout(this);

    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT);
    mTouchLayout.setLayoutParams(lp);

    // set on touch listener
    mTouchLayout.setOnTouchListener(this);

    // fetch window manager object
    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    // set layout parameter of window manager

    WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT
    );

    mParams.gravity = Gravity.LEFT | Gravity.TOP;
    windowManager.addView(mTouchLayout, mParams);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    initTimer();

    return START_NOT_STICKY;
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
    Log.d("IdleDetectorService", "Touch detected. Resetting timer");
    initTimer();
    return false;
}

@Override
public void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacks(mRunnable);
    WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    if (windowManager != null && mTouchLayout != null) {
        windowManager.removeView(mTouchLayout);
    }
}

/**
 * (Re)sets the timer to send the inactivity broadcast
 */
private void initTimer() {
    // Start timer and timer task
    if (mRunnable == null) {

        mRunnable = new Runnable() {
            @Override
            public void run() {
                Log.d("IdleDetectorService", "Inactivity detected. Sending broadcast to start the app");

                try {
                    boolean isInForeground = new ForegroundCheckTask().execute(getApplicationContext()).get();

                    if (!isInForeground) {
                        Intent launchIntent = getApplication()
                                .getPackageManager()
                                .getLaunchIntentForPackage("<your-package-name>");
                        if (launchIntent != null) {
                            LogUtil.d("IdleDetectorService", "App started");
                            getApplication().startActivity(launchIntent);
                        }
                    }

                    stopSelf();
                } catch (Exception e) {
                }
            }
        };
    }

    if (mHandler == null) {
        mHandler = new Handler();
    }

    mHandler.removeCallbacks(mRunnable);
    mHandler.postDelayed(mRunnable, mTimerDelay);
}

private class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {

    @Override
    protected Boolean doInBackground(Context... params) {
        final Context context = params[0];
        return isAppOnForeground(context);
    }

    private boolean isAppOnForeground(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = null;

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            appProcesses = activityManager.getRunningAppProcesses();
        } else {
            //for devices with Android 5+ use alternative methods
            appProcesses = AndroidProcesses.getRunningAppProcessInfo(getApplication());
        }

        if (appProcesses == null) {
            return false;
        }

        final String packageName = context.getPackageName();

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
                    appProcess.processName.equals(packageName)) {
                return true;
            }
        }

        return false;
    }
}

请注意,您应该在 AndroidManifest.xml 文件中添加其他权限: android:name="android.permission.SYSTEM_ALERT_WINDOW"

于 2017-03-30T11:22:51.623 回答