I recently encountered a requirement to get the App the user is currently using.
Prior to Android5.0, use the following code to get the information:
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)
}
Copy the code
After 5.0, however, this approach will not work and you will need to use the Data statistics service using the UsageStatsManager application.
Using the Data statistics service with the UsageStatsManager application requires user manual authorization.
startActivityForResult(
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),MY_PERMISSIONS_REQUEST_PACKAGE_USAGE_STATS);
Copy the code
You also need to register the permissions in the registration file
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
Copy the code
We can use the following method to determine whether to obtain permission:
// Check whether the user has the "Apps with Usage Access" permission private BooleanhasPermission() {
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;
}
Copy the code
Once granted, a subsequent service can be started to listen for the App being used by the current user.
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(a) {
isRun = false
}
override fun run(a) {
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 and below
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 and above
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()
// Get application data within 60 seconds
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 = ""
// Get the last running app, that is, the current running 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/ / package name
}
if(! topActivity.isEmpty()) { (contextas TopAppInfoService).showToast(TopAppInfoService.getAppName(context, topActivity) + ":" + topActivity)
}
}
}
}
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onCreate(a) {
super.onCreate()
myThread = MyThread(this) myThread!! .start() Log.i(TAG,"Service is start.")}override fun onDestroy(a) {
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
}
}
}
Copy the code
Compatible with Android5.0, you can get the App package name and application name.
All that remains is to start the service at the appropriate time:
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); }});Copy the code
Pass the test on huawei, Xiaomi and OnePlus real phones, please feel free to eat.
Have a good life.