鹅厂高工三面:Android获取进程名函数,如何优化到极致?

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

Application.getProcessName()方法直接返回当前进程名。这不就是我们想要的API吗!

但是这个方法只有在android9【也就是aip28】之后的系统才能调用。

public class ProcessUtil {

/**

  • 通过Application新的API获取进程名,无需反射,无需IPC,效率最高。
    */
    public static String getCurrentProcessNameByApplication() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    return Application.getProcessName();
    }
    return null;
    }
    }

android9以前的系统怎么办呢?

android9以前的系统怎么办呢?

android9以前的系统怎么办呢?

方法二:ActivityThread.currentProcessName() 方法

于是大叔好奇,看了看Application.getProcessName()的源码,他是如何实现的?

public class Application extends ContextWrapper implements ComponentCallbacks2 {
public static String getProcessName() {
return ActivityThread.currentProcessName();
}
}

我们发现了ActivityThread.currentProcessName()这个方法。

于是大叔继续翻了下源码:

/**

  • {@hide}
    */
    public final class ActivityThread extends ClientTransactionHandler {

public static String currentProcessName() {
//…
}
}

奥利给,ActivityThread.currentProcessName()方法居然是public static的。

奥利给,ActivityThread.currentProcessName()方法居然是public static的。

奥利给,ActivityThread.currentProcessName()方法居然是public static的。

但是,马上就发现:

ActivityThread类是hide的,app无法直接调用。

ActivityThread类是hide的,app无法直接调用。

ActivityThread类是hide的,app无法直接调用。

于是大叔继续翻源码,看看这个方法是什么时候新增的。

大叔发现这个方法在android4.3.1上就已经有了这个方法了。

在android4.0.4上没有找到currentProcessName()方法。

那么意味着,我们是不是可以反射调用 ActivityThread.currentProcessName() ?

答案当然是可以。

于是我们在ProcessUtil工具类中实现了这个方法:

public class ProcessUtil {

/**

  • 通过反射ActivityThread获取进程名,避免了ipc
    */
    public static String getCurrentProcessNameByActivityThread() {
    String processName = null;
    try {
    final Method declaredMethod = Class.forName(“android.app.ActivityThread”, false, Application.class.getClassLoader())
    .getDeclaredMethod(“currentProcessName”, (Class<?>[]) new Class[0]);
    declaredMethod.setAccessible(true);
    final Object invoke = declaredMethod.invoke(null, new Object[0]);
    if (invoke instanceof String) {
    processName = (String) invoke;
    }
    } catch (Throwable e) {
    }
    return processName;
    }
    }

四、将三种方法结合得到一个更优方案

于是我们将三个方法结合。

  1. 我们优先通过 Application.getProcessName() 方法获取进程名。
  2. 如果获取失败,我们再反射ActivityThread.currentProcessName()获取进程名
  3. 如果失败,我们才通过常规方法ActivityManager来获取进程名

如下代码:

public class ProcessUtil {
private static String currentProcessName;

/**

  • @return 当前进程名
    */
    @Nullable
    public static String getCurrentProcessName(@NonNull Context context) {
    if (!TextUtils.isEmpty(currentProcessName)) {
    return currentProcessName;
    }

//1)通过Application的API获取当前进程名
currentProcessName = getCurrentProcessNameByApplication();
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
}

//2)通过反射ActivityThread获取当前进程名
currentProcessName = getCurrentProcessNameByActivityThread();
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
}

//3)通过ActivityManager获取当前进程名
currentProcessName = getCurrentProcessNameByActivityManager(context);

return currentProcessName;
}

/**

  • 通过Application新的API获取进程名,无需反射,无需IPC,效率最高。
    */
    public static String getCurrentProcessNameByApplication() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    return Application.getProcessName();
    }
    return null;
    }

/**

  • 通过反射ActivityThread获取进程名,避免了ipc
    */
    public static String getCurrentProcessNameByActivityThread() {
    String processName = null;
    try {
    final Method declaredMethod = Class.forName(“android.app.ActivityThread”, false, Application.class.getClassLoader())
    .getDeclaredMethod(“currentProcessName”, (Class<?>[]) new Class[0]);
    declaredMethod.setAccessible(true);
    final Object invoke = declaredMethod.invoke(null, new Object[0]);
    if (invoke instanceof String) {
    processName = (String) invoke;
    }
    } catch (Throwable e) {
    e.printStackTrace();
    }
    return processName;
    }

/**

  • 通过ActivityManager 获取进程名,需要IPC通信
    */
    public static String getCurrentProcessNameByActivityManager(@NonNull Context context) {
    if (context == null) {
    return null;
    }
    int pid = Process.myPid();
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    if (am != null) {
    List<ActivityManager.RunningAppProcessInfo> runningAppList = am.getRunningAppProcesses();
    if (runningAppList != null) {
    for (ActivityManager.RunningAppProcessInfo processInfo : runningAppList) {
    if (processInfo.pid == pid) {
    return processInfo.processName;
    }
    }
    }
    }
    return null;
    }
    }

五、简单的测试下性能

大叔做了个简单的测试,测试下三种方法调用需要的时长:

模拟器上做的测试,模拟器配置如下:

测试代码如下:

private fun testGetCurrentProcessNameByApplication(){
val beginTime = SystemClock.elapsedRealtimeNanos()
ProcessUtil.getCurrentProcessNameByApplication()
Log.i(TG, “getCurrentProcessNameByApplication duration=${SystemClock.elapsedRealtimeNanos() - beginTime}”)
}

private fun testGetCurrentProcessNameByActivityThread(){
val beginTime = SystemClock.elapsedRealtimeNanos()
ProcessUtil.getCurrentProcessNameByActivityThread()
Log.i(TG, “getCurrentProcessNameByActivityThread duration=${SystemClock.elapsedRealtimeNanos() - beginTime}”)

最后

那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。

通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!

北京 Android 工程师「工资收入水平 」

今天重点内容是怎么去学,怎么提高自己的技术。

1.合理安排时间

2.找对好的系统的学习资料

3.有老师带,可以随时解决问题

4.有明确的学习路线

当然图中有什么需要补充的或者是需要改善的,可以在评论区写下来,一起交流学习。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

4461918)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-zoObyWNC-1713394461918)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值