最近遇到这样的一个需求,获取用户当前正在使用的App。java
在Android5.0以前,使用下面的代码便可得到相关信息:android
//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应用使用数据统计服务。bash
使用UsageStatsManager应用使用数据统计服务须要用户手动受权。app
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
复制代码
同时须要在注册文件中注册权限ide
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
复制代码
咱们能够同下面的方法判断是否取得权限:oop
//检测用户是否对本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。post
import android.app.ActivityManager
import android.app.Service
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import android.widget.Toast
import java.util.concurrent.TimeUnit
class 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的包名和应用名。测试
剩下的就是在适当的时候启动服务了:ui
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);
}
});
复制代码
在华为,小米和一加的真机上经过测试,请放心食用。this
祝你生活愉快。