寫個程式,‘監視’你的手機!
最近遇到這樣的一個需求,獲取使用者當前正在使用的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.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的包名和應用名。
剩下的就是在適當的時候啟動服務了:
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); } }); 複製程式碼
在華為,小米和一加的真機上通過測試,請放心食用。
祝你生活愉快。