[Android]你不知道的Android程式化–程式資訊

Cang_Wang發表於2019-03-04

大家好,我係蒼王。

以下是我這個系列的相關文章,有興趣可以參考一下,可以給個喜歡或者關注我的文章。

[Android]如何做一個崩潰率少於千分之三噶應用app–章節列表

這裡是一個全新的系列–程式化

元件化模組化延伸後,還能到達程式化。

當你能活用元件化模組化,明白其中的關聯之後,再深入探究下去,就會走到程式這一步。

從基礎出發,我們說一下程式資訊,下面全部使用kotlin編寫的api。

獲取記憶體容量

    fun getTotalMemSize():Long{
        var size=0L
        //系統記憶體檔案
        val file = File("/proc/meminfo")
        try {
            val buffer = BufferedReader(InputStreamReader(FileInputStream(file)))
            var memInfo = buffer.readLine()
            val startIndex = memInfo.indexOf(":")
            val endIndex =memInfo.indexOf("k")
            memInfo = memInfo.substring(startIndex+1,endIndex).trim()
            size = memInfo.toLong()
            size *= 1024
            buffer.close()
        }catch (e:IOException){
            e.printStackTrace()
        }
        return size
    }
複製程式碼

獲取可用記憶體

    fun getAviableMemSize(context:Context):Long{
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        var mi = ActivityManager.MemoryInfo()
        am.getMemoryInfo(mi)
        return mi.availMem
    }
複製程式碼

獲取當前程式id

fun getCurrentProcessId():Int{
        return android.os.Process.myPid()
    }
複製程式碼

獲取當前程式名

 fun getCurrentProcessName():String{
        var processName = UNKNOWN_PROCESS_NAME
        try {
            val file = File("/proc/"+ getCurrentProcessId()+"/cmdline")
            val buffer = BufferedReader(FileReader(file))
            processName = buffer.readLine().trim()
            buffer.close()
        }catch (e:Exception){
            e.printStackTrace()
        }
        return processName
    }


    fun getCurrentProcessName():String{
        var processName = UNKNOWN_PROCESS_NAME
        try {
            val file = File("/proc/"+ getCurrentProcessId()+"/cmdline")
            val buffer = BufferedReader(FileReader(file))
            processName = buffer.readLine().trim()
            buffer.close()
        }catch (e:Exception){
            e.printStackTrace()
        }
        return processName
    }
複製程式碼

獲取程式名

    fun getCurrentProcessName(pid:Int):String{
        var processName = UNKNOWN_PROCESS_NAME
        try {
            val file = File("/proc/"+ pid+"/cmdline")
            val buffer = BufferedReader(FileReader(file))
            processName = buffer.readLine().trim()
            buffer.close()
        }catch (e:Exception){
            e.printStackTrace()
        }
        return processName
    }

    fun getProcessName(context:Context,pid:Int):String{
        var processName = getCurrentProcessName(pid)
        if (UNKNOWN_PROCESS_NAME .equals(processName)){
            val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val runningApps = am.runningAppProcesses
            if (runningApps!=null){
                for (info in runningApps){
                    if(info.pid == pid) return info.processName
                }
            }
        }
        return processName
    }
複製程式碼

使用命令獲取adb手機程式

連線電腦,使用adb shell連線手機。
然後使用ps可以檢視全部程式的資訊。
這裡請注意linux目錄中有個/proc的目錄,這裡記載執行的程式,如果沒有root手機取得最高許可權是無法檢視到程式資訊的。

[Android]你不知道的Android程式化–程式資訊

通過程式碼獲取全部的程式資訊

這裡需要使用ActivityManager 和PackageManager獲取執行程式資訊的列表
在5.0以前使用一下的方法來獲取

/**
     * 獲取所有程式資訊(5.0以前)
     */
    fun getTaskInfos(context:Context):List<TaskBean>?{
        val activityManager:ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val packageManager:PackageManager = context.packageManager
        var runList:List<ActivityManager.RunningAppProcessInfo> = activityManager.runningAppProcesses
        if(runList.isEmpty()) return null
        val list = ArrayList<TaskBean>()
        try {
            for (info in runList){
                val app =packageManager.getPackageInfo(info.processName,0).applicationInfo
                //過濾自己當前應用
                if (app ==null || context.packageName.equals(app.packageName)) continue

                val bean = TaskBean()
                bean.pid = info.pid
                bean.processName = info.processName  //程式名
                bean.pInfo = packageManager.getPackageInfo(bean.processName,0)  //包資訊
                bean.appName = app.loadLabel(packageManager).toString() //app名
                bean.drawable  = app.loadIcon(packageManager)    //app圖示
                bean.pakcageName = app.packageName  //包名
                //系統應用
                if((app.flags and ApplicationInfo.FLAG_SYSTEM) >0){
                    bean.isSystem = true
                }else{
                    bean.isUser = true
                }

                val memoryInfo = activityManager.getProcessMemoryInfo(IntArray(info.pid))
                val memsize:Double = memoryInfo[0].dalvikPrivateDirty/1024.0
                bean.memSize = memsize
                list.add(bean)

            }
        }catch (e:PackageManager.NameNotFoundException){
            e.printStackTrace()
        }
        return list
    }
複製程式碼

在Android5.0以後,使用以上的方法,只能獲取前臺執行的app所在程式的的資訊
Android5.0~7.0 可以使用AndroidProcessor開源庫獲取
其原理是讀取/proc/裡面程式號為數字的程式的資訊
7.0以後google限制了,app只能在/proc/讀取到個人的程式資訊。

通過UsageStatsManager獲取

UsageStatsManager是5.0 才開始有的,用於記錄應用的使用資訊, 入應用在某段時間內處於前臺和後臺的時間,最近一次啟動的時間等。
使用它之前需要在AndroidManifest中配置 “android.permission.PACKAGE_USAGE_STATS”的許可權,必須勾選安全的許可權配置才能開啟

/**
     * 獲取所有程式資訊(5.0以後)
     */
    fun getTaskInfosL(context:Context):List<TaskBean>?{
        val list = ArrayList<TaskBean>()
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            val packageManager:PackageManager = context.packageManager
            val usm = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
            val calendar = Calendar.getInstance()
           //結束時間
            val endTime = calendar.timeInMillis
            calendar.add(Calendar.YEAR, -1)
           //開始時間
            val startTime = calendar.timeInMillis
            val usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime)
            for(usage in usageStatsList){
                try {
                    val bean = TaskBean()
                    val app = packageManager.getPackageInfo(usage.packageName, 0).applicationInfo
                    bean.pakcageName = usage.packageName
                    bean.processName = app.processName
                    bean.pInfo = packageManager.getPackageInfo(bean.processName, 0)
                    bean.appName = app.loadLabel(packageManager).toString() //app名
                    bean.drawable = app.loadIcon(packageManager)    //app圖示
                    //系統應用
                    if ((app.flags and ApplicationInfo.FLAG_SYSTEM) > 0) {
                        bean.isSystem = true
                    } else {
                        bean.isUser = true
                    }
                    list.add(bean)
                }catch (e:Exception){
                    e.printStackTrace()
                }
            }
        }
        return list
}
複製程式碼

UsageStats 中無法獲取程式pid,usageStats只是記錄程式執行的記錄,所以這種方法沒辦法獲得佔用的記憶體資訊,適用於7.0 以上的系統。

開啟指定包名的App

    fun openSpecifiedApp(context:Context,packageName:String){
        val manager = context.packageManager
        val lauchIntentForPackage = manager.getLaunchIntentForPackage(packageName)
        context.startActivity(lauchIntentForPackage)
    }
複製程式碼

開啟指定包名的App應用資訊介面

fun showAppInfo(context: Context,packageName:String){
        val intent = Intent()
        intent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
        intent.data = Uri.parse("package:" + packageName)
        context.startActivity(intent)
    }
複製程式碼

當前app處於前臺還是後臺

需新增在AndroidManifest中新增<uses-permission android:name=”android.permission.GET_TASKS”/>的許可權

    fun isAppForground(context: Context,packageName:String):Boolean{
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        var task = am.getRunningTasks(1)
        if(!task.isEmpty()){
            val top = task.get(0).topActivity
            if (top.packageName.equals(context.packageName)){
                return true
            }
        }
        return false
    }
複製程式碼

元件化的群裡已經快滿員了,這是新開的程式化的新群。
Stay hugry ,stay foolish!

[Android]你不知道的Android程式化–程式資訊

Android程式化交流

相關文章