android获取进程pid的方法,Android中获取到进程名字的最优解

ff7de84be43f

Android_Banner.jpg

简介

在多进程开发的时候我们可能需要知道当前进程是主进程还是子进程,这是就需要我们取获取到当前所处进程的名字了。

以下是获取到进程名字的几种方式,以及区别和对比

获取方式

使用ActivityManager获取

该方式也是我们能查阅资料看见最多的实现方式

代码如下

object ProcessUtils {

/**

* 通过ActivityManager获取到进程名字

*/

fun getCurrentProcessName(context:Context):String?{

var myPid = Process.myPid()

var activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

var runningAppProcesses = activityManager.runningAppProcesses

if (!runningAppProcesses.isNullOrEmpty()){

runningAppProcesses.forEach {

if (it.pid == myPid){

return it.processName

}

}

}

return null

}

}

测试代码如下

class AppApplication : Application() {

init {

//初始化打印

//initLog()

ApplicationController.init(this, true)

}

override fun onCreate() {

super.onCreate()

initARouter()

ApplicationController.transformOnCreate()

if (ProcessUtils.getCurrentProcessName(this) == BuildConfig.APPLICATION_ID){

DQLog.d("init main application")

}

}

}

打印结果如下

2020-10-19 22:43:38.154 24073-24073/com.dashingqi.mvvmcomponent D/AppApplication: init main application

分析一下

// activityManager.runningAppProcesses ---> ActivityManager # getRunningAppProcess()

public List getRunningAppProcesses() {

try {

return getService().getRunningAppProcesses();

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

// 其中getService() ---> IActivityManager,而IActivityManager是一个AIDL文件,作为和ActivytMangerServie通信,也就是跨进程通信发生了。

所以经过以上分析,可以得出有跨进程通信,就会有响应的耗时

再者我们是通过获取到所以运行的进程,然后一个一个比对,这样循环调用也会有相应的性能损耗。

以上使用ActivityManager获取进程名称是属于常规操作了,下面使用下骚操作。

API28 新增方法 Application # getProcessName()

代码如下

/**

* AP28以上才能使用

* 直接获取到进程名称,不会有跨进程,反射的耗时操作

*/

fun getCurrentProcessNameOnP():String?{

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){

return Application.getProcessName()

}

return null

}

测试代码

override fun onCreate() {

super.onCreate()

initARouter()

ApplicationController.transformOnCreate()

var name = ProcessUtils.getCurrentProcessName(this)

Log.d(TAG,"name $name")

var pName = ProcessUtils.getCurrentProcessNameOnP()

Log.d(TAG,"pName === $pName")

if (ProcessUtils.getCurrentProcessName(this) == BuildConfig.APPLICATION_ID){

Log.d(TAG,"init main application")

}

}

打印结果如下

2020-10-19 23:03:31.400 26933-26933/com.dashingqi.mvvmcomponent D/AppApplication: pName === com.dashingqi.mvvmcomponent

分析一下

// Application # getProcessName() ----> ActivityThread.currentProcessName()

public static String currentProcessName() {

ActivityThread am = currentActivityThread();

return (am != null && am.mBoundApplication != null)

? am.mBoundApplication.processName : null;

}

//我们可以看到 currentProcessName() 是 public static

// 但是我们看到注解描述 ActivityThread 是@hide

//那么有没有其他的操作可以搞一下呢?

通过反射调用ActivityThread中的currentProcessName()

fun getCurrentProcessNameByAT(): String? {

var processName: String? = null

try {

val declaredMethod: Method = Class.forName("android.app.ActivityThread", false, Application::class.java.classLoader)

.getDeclaredMethod("currentProcessName")

declaredMethod.isAccessible = true

val invoke: Any = declaredMethod.invoke(null)

if (invoke is String) {

processName = invoke

}

} catch (e: Throwable) {

e.printStackTrace()

}

return processName

}

// 执行结果如下

// 2020-10-19 23:21:36.487 28594-28594/com.dashingqi.mvvmcomponent D/AppApplication: atName == com.dashingqi.mvvmcomponent

该方法是采用了反射调用了,并没有进行IPC通信,所以耗时通常不会比第一个要长

进行一下耗时的比较

测试代码

val nameStart = SystemClock.elapsedRealtimeNanos()

var name = ProcessUtils.getCurrentProcessName(this)

Log.d(TAG,"getCurrentProcessName cost == ${SystemClock.elapsedRealtimeNanos()-nameStart}")

val pNameStart = SystemClock.elapsedRealtimeNanos()

var pName = ProcessUtils.getCurrentProcessNameOnP()

Log.d(TAG,"getCurrentProcessNameOnP cost == ${SystemClock.elapsedRealtimeNanos() - pNameStart}")

val atNameStart = SystemClock.elapsedRealtimeNanos()

var atName = ProcessUtils.getCurrentProcessNameByAT()

Log.d(TAG,"getCurrentProcessNameByAT cost == ${SystemClock.elapsedRealtimeNanos()-atNameStart}")

运行结果

2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessName cost == 641875

2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessNameOnP cost == 28229

2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessNameByAT cost == 119792

总的说来,直接获取要好于反射的方式,放射的方式要好于IPC方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值