我的账户
动脑学院

教育培训在线课程

亲爱的游客,欢迎!

已有账号,请

如尚未注册?

写个程序,‘监视’你的手机!

[复制链接]
dnman 发表于 2019-3-29 16:14:55 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
最近遇到这样的一个需求,获取用户当前正在使用的App。
在Android5.0之前,使用下面的代码即可获得相关信息:
        //5.0及以下        private fun getTopAppOld(context: Context) {            val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager            val topActivity = activityManager.getRunningTasks(1)[0].topActivity.packageName            (context as TopAppInfoService).showToast(TopAppInfoService.getAppName(context, topActivity) + ":" + topActivity)        }
但是5.0以后此方法就不行了,需要使用UsageStatsManager应用使用数据统计服务。
使用UsageStatsManager应用使用数据统计服务需要用户手动授权。
startActivityForResult(    new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
同时需要在注册文件中注册权限
<uses-permission        android:name="android.permission.PACKAGE_USAGE_STATS"        tools:ignore="ProtectedPermissions"/>
我们可以同下面的方法判断是否取得权限:
//检测用户是否对本app开启了“Apps with usage access”权限    private boolean hasPermission() {        AppOpsManager appOps = (AppOpsManager)                getSystemService(Context.APP_OPS_SERVICE);        int mode = 0;        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {            mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,                    android.os.Process.myUid(), getPackageName());        }        return mode == AppOpsManager.MODE_ALLOWED;    }
取得权限之后,就可以启动一个后的service来监听当前用户使用的App。
import android.app.ActivityManagerimport android.app.Serviceimport android.app.usage.UsageStatsManagerimport android.content.Contextimport android.content.Intentimport android.content.pm.PackageManagerimport android.os.Buildimport android.os.Handlerimport android.os.IBinderimport android.os.Looperimport android.util.Logimport android.widget.Toastimport java.util.concurrent.TimeUnitclass TopAppInfoService : Service() {    private var myThread: MyThread? = null    class MyThread constructor(private val context: Context) : Thread() {        private var isRun = true        fun setStop() {            isRun = false        }        override fun run() {            while (isRun) {                try {                    TimeUnit.SECONDS.sleep(2)                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                        getTopAppNew(context)                    } else {                        getTopAppOld(context)                    }                } catch (e: InterruptedException) {                    e.printStackTrace()                }            }        }        //5.0及以下        private fun getTopAppOld(context: Context) {            val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager            val topActivity = activityManager.getRunningTasks(1)[0].topActivity.packageName            (context as TopAppInfoService).showToast(TopAppInfoService.getAppName(context, topActivity) + ":" + topActivity)        }        //5.0及以上        private fun getTopAppNew(context: Context) {            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                val m = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager                if (m != null) {                    val now = System.currentTimeMillis()                    //获取60秒之内的应用数据                    val stats = m.queryUsageStats(UsageStatsManager.INTERVAL_BEST, now - 60 * 1000, now)                    Log.i(TAG, "Running app number in last 60 seconds : " + stats!!.size)                    var topActivity = ""                    //取得最近运行的一个app,即当前运行的app                    if (stats != null && !stats.isEmpty()) {                        var j = 0                        for (i in stats.indices) {                            if (stats[i].lastTimeUsed > stats[j].lastTimeUsed) {                                j = i                            }                        }                        topActivity = stats[j].packageName//包名                    }                    if (!topActivity.isEmpty()) {                        (context as TopAppInfoService).showToast(TopAppInfoService.getAppName(context, topActivity) + ":" + topActivity)                    }                }            }        }    }    override fun onBind(intent: Intent): IBinder? {        return null    }    override fun onCreate() {        super.onCreate()        myThread = MyThread(this)        myThread!!.start()        Log.i(TAG, "Service is start.")    }    override fun onDestroy() {        super.onDestroy()        myThread!!.setStop()        Log.i(TAG, "Service is stop.")    }    fun showToast(txt: String?) {        if (txt == null) {            Log.e(TAG, "call method showToast, text is null.")            return        }        val handler = Handler(Looper.getMainLooper())        handler.post {            Toast.makeText(this@TopAppInfoService, txt, Toast.LENGTH_LONG)                    .show()        }    }    companion object {        val TAG = "TopAppInfoService"        fun getAppName(context: Context, packageName: String): String {            val pm = context.packageManager            var Name: String            try {                Name = pm.getApplicationLabel(pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA)).toString()            } catch (e: PackageManager.NameNotFoundException) {                Name = ""            }            return Name        }    }}
上面对Android5.0做了兼容,可以拿到App的包名和应用名。
剩下的就是在适当的时候启动服务了:
btnStart = (Button) this.findViewById(R.id.btnStart);        btnStart.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, TopAppInfoService.class);                startService(intent);            }        });        btnStop = (Button) this.findViewById(R.id.btnStop);        btnStop.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, TopAppInfoService.class);                stopService(intent);            }        });
在华为,小米和一加的真机上通过测试,请放心食用。
祝你生活愉快。




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则