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.