Java Android服务:检测设备空闲X分钟的时间
我需要知道,当我的应用程序当前处于后台时,android设备何时处于空闲状态一段时间(如果处于空闲状态,请将我的应用程序带到前台)。我能想到的唯一两种方法是:Java Android服务:检测设备空闲X分钟的时间,java,android,idle-timer,Java,Android,Idle Timer,我需要知道,当我的应用程序当前处于后台时,android设备何时处于空闲状态一段时间(如果处于空闲状态,请将我的应用程序带到前台)。我能想到的唯一两种方法是: 以某种方式检测应用程序外的用户交互,如果X分钟内没有任何输入,请将我的应用程序放在最前面 或: 当设备进入睡眠模式时,将我的应用程序放在最前面 我不知道如何实现这两个目标,但2对我来说似乎是最可行的选择。这方面的代码是什么?我能够完成1。通过使用“透明”视图,该视图位于所有视图之上,用于检查用户触摸 实现所需效果的步骤: 1) 创建一个服
我不知道如何实现这两个目标,但2对我来说似乎是最可行的选择。这方面的代码是什么?我能够完成1。通过使用“透明”视图,该视图位于所有视图之上,用于检查用户触摸 实现所需效果的步骤: 1) 创建一个服务,该服务在其onCreate方法中创建透明视图并将其附加到视图堆栈
2) onStart命令调用initTimer()方法
3) 在服务上实现View.OnTouchListener
4) 重写onTouch方法
5) 收到onTouch事件-调用initTimer()
6) 在服务的onDestroy上-从视图堆栈中删除透明视图
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;
}
}
私有处理器mHandler;
私人可运行的mRunnable;
私人最终int mTimerDelay=60000//不活动延迟(毫秒)
私人线路布局mTouchLayout//透明视图
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
public void onCreate(){
super.onCreate();
mTouchLayout=新的线性布局(本);
LinearLayout.LayoutParams lp=新的LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_父项,
LinearLayout.LayoutParams.MATCH_PARENT);
mTouchLayout.setLayoutParams(lp);
//触摸式监听
mTouchLayout.setOnTouchListener(this);
//获取窗口管理器对象
WindowManager WindowManager=(WindowManager)getSystemService(窗口服务);
//设置窗口管理器的布局参数
WindowManager.LayoutParams mParams=新建WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_内容,
WindowManager.LayoutParams.WRAP_内容,
WindowManager.LayoutParams.TYPE\u系统错误,
WindowManager.LayoutParams.FLAG\u不可触摸|
WindowManager.LayoutParams.FLAG\u WATCH\u OUTSIDE\u TOUCH|
WindowManager.LayoutParams.FLAG_不可聚焦,PixelFormat.半透明
);
mParams.gravity=gravity.LEFT | gravity.TOP;
windowManager.addView(mTouchLayout,mParams);
}
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
initTimer();
返回开始时间不粘;
}
@凌驾
公共布尔onTouch(视图、运动事件、运动事件){
Log.d(“IdleDetectorService”,“检测到触摸。重置计时器”);
initTimer();
返回false;
}
@凌驾
公共空间{
super.ondestory();
mHandler.removeCallbacks(mRunnable);
WindowManager WindowManager=(WindowManager)getSystemService(窗口服务);
if(windowManager!=null&&mTouchLayout!=null){
windowManager.removeView(mTouchLayout);
}
}
/**
*(Re)设置计时器以发送非活动广播
*/
私有void initTimer(){
//启动计时器和计时器任务
如果(mRunnable==null){
mRunnable=newrunnable(){
@凌驾
公开募捐{
Log.d(“IdleDetectorService”,“检测到不活动。正在发送广播以启动应用程序”);
试一试{
布尔值ISINFORGROUND=new ForegroundCheckTask().execute(getApplicationContext()).get();
如果(!IsInfo重新研磨){
Intent launchIntent=getApplication()
.getPackageManager()
.getLaunchIntentForPackage(“”);
if(launchIntent!=null){
LogUtil.d(“IdleDetectorService”,“应用程序已启动”);
getApplication().startActivity(launchIntent);
}
}
stopSelf();
}捕获(例外e){
}
}
};
}
if(mHandler==null){
mHandler=新处理程序();
}
mHandler.removeCallbacks(mRunnable);
mHandler.postDelayed(mRunnable,mTimerDelay);
}
私有类ForegroundCheckTask扩展了AsyncTask{
@凌驾
受保护的布尔doInBackground(上下文…参数){
最终上下文=参数[0];
返回isAppOnForeground(上下文);
}
专用布尔值isAppOnForeground(上下文){
ActivityManager ActivityManager=(ActivityManager)context.getSystemService(context.ACTIVITY_服务);
列表appprocesss=null;
if(Build.VERSION.SDK_INT)我以前也见过类似的讨论,例如这里:@Scalar,用于检测应用程序内的空闲时间。当设备进入睡眠模式时,什么都没有(至少在普通软件中是这样)正在运行。@ChrisStratton我意识到了这一点,这正是我的问题。但是,也许有一种方法可以覆盖某种“屏幕关闭”事件,使其打开我的应用程序(或类似的内容)?但他们实际上是在屏幕关闭,这可能发生在实际睡眠之前。谢谢!这对我来说适用于以下内容:val mParams=WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_父项、WindowManager.LayoutParams.MATCH_父项、WindowManager.LayoutParams.TYPE_应用程序_覆盖、WindowManager.LayoutParams.FLAG_不可触摸或WindowManager.LayoutParams.FLAG_监视_外部触摸或