[Android]你不知道的Android进程化--进程信息
大家好,我系苍王。
以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。
[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手机取得最高权限是无法查看到进程信息的。
通过代码获取全部的进程信息
这里需要使用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进程化交流