Android最全hook Toast,全网最强之 Android “沙雕”操作,2024年最新考点面试

面试复习笔记:

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

// Empty

}

}

代码很简单,主要是通过serviceenqueueToast()enqueueTextToast()两种方式显示toast。

service是一个INotificationManager类型的对象,INotificationManager是一个接口,这就为动态代理提供了可能。

service是在每次show()时通过getService()获取,那就来看看getService():

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)

private static INotificationManager sService;

@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)

static private INotificationManager getService() {

if (sService != null) {

return sService;

}

sService = INotificationManager.Stub.asInterface(

ServiceManager.getService(Context.NOTIFICATION_SERVICE));

return sService;

}

getService()最终返回的是sService,是一个懒汉式单例,因此可以通过反射获取到其实例。

3,小结


sService是一个单例,可以反射获取到其实例。

sService实现了INotificationManager接口,因此可以动态代理。

因此可以通过Hook来干预Toast的展示。

三,撸码

====

理清了上面的过程,实现就很简单了,直接撸码:

1,获取sService的Field

Class toastClass = Toast.class;

Field sServiceField = toastClass.getDeclaredField(“sService”);

sServiceField.setAccessible(true);

2,动态代理替换

Object proxy = Proxy.newProxyInstance(Thread.class.getClassLoader(), new Class[]{INotificationManager.class}, new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

return null;

}

});

// 用代理对象给sService赋值

sServiceField.set(null, proxy);

3,获取sService原始对象

因为动态代理不能影响被代理对象的原有流程,因此需要在第二步的InvocationHandler()invoke()中需要执行原有的逻辑,这就需要获取sService的原始对象。

前面已经获取到了sService的Field,它是静态的,那直接通过sServiceField.get(null)获取不就可以了?然而并不能获取到,这是因为整个Hook操作是在应用初始化时,整个应用还没有执行过Toast.show()的操作,因此sService还没有初始化(因为它是一个懒汉单例)。

既然不能直接获取,那就通过反射调用一下:

Method getServiceMethod = toastClass.getDeclaredMethod(“getService”, null);

getServiceMethod.setAccessible(true);

Object service = getServiceMethod.invoke(null);

接着完善一下第二步代码:

Object proxy = Proxy.newProxyInstance(Thread.class.getClassLoader(), new Class[]{INotificationManager.class}, new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

return method.invoke(service, args);

}

});

到此,已经实现了对Toast的代理,Toast可以按照原始逻辑正常执行,但还没有加入额外逻辑。

4,添加Hook逻辑

InvocationHandlerinvoke()方法中添加额外逻辑:

Object proxy = Proxy.newProxyInstance(Thread.class.getClassLoader(), new Class[]{INotificationManager.class}, new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 判断enqueueToast()方法时执行操作

if (method.getName().equals(“enqueueToast”)) {

Log.e(“hook”, method.getName());

getContent(args[1]);

}

return method.invoke(service, args);

}

});

args数组的第二个是TN类型的对象,其中有一个LinearLayout类型的mNextView对象,mNextView中有一个TextView类型的childView,这个childView就是展示toast文本的那个TextView,可以直接获取其文本内容,也可以对其赋值,因此代码如下:

private static void getContent(Object arg) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {

// 获取TN的class

Class<?> tnClass = Class.forName(Toast.class.getName() + “$TN”);

// 获取mNextView的Field

Field mNextViewField = tnClass.getDeclaredField(“mNextView”);

mNextViewField.setAccessible(true);

// 获取mNextView实例

LinearLayout mNextView = (LinearLayout) mNextViewField.get(arg);

// 获取textview

TextView childView = (TextView) mNextView.getChildAt(0);

// 获取文本内容

CharSequence text = childView.getText();

// 替换文本并赋值

childView.setText(text.toString().replace(“HookToast:”, “”));

Log.e(“hook”, "content: " + childView.getText());

}

最后看一下效果:

最后

我的面试经验分享可能不会去罗列太多的具体题目,因为我依然认为面试经验中最宝贵的不是那一个个具体的题目或者具体的答案,而是结束面试时,那一刻你的感受以及多天之后你的回味~

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我整理了一些资料,需要的可以免费分享给大家

在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值