最近遇到這樣的一個需求,獲取用戶當前正在使用的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
祝你生活愉快。