引言:
第一次使用Xposed框架, 知道做怎么用, 就不知道怎么做,来看看
首先给机器安装框架app
开发框架模块需要导入jar
测试体验
总结
---------------------------------------------------------
一,首先给机器安装框架app
Xposed Installer,由于Android 5.0以上采用ART,而5.0以下默认采用Dalvik,
所以是有两个版本的Xposed,附上下载链接:
Android 4.0.3-4.4: repo.xposed.info/module/de.r…
Android 5.0以上:forum.xda-developers.com/showthread.…
笔者下载的是XposedInstaller_3.1.5.apk, app可以安装在机器上,打开如下图, 如果提示未激活就先安装, 安装需要机器系统已root, 安装重启机器就可以了
注: 机器可以是真机, 或者电脑上安装个模拟器 (笔者用的是夜神模拟器)
二, 开发框架模块需要导入jar
开发Xposed框架模块, 当然用Android Studio 工具开发了, 先建一个app项目,笔者项目名XposedDemo, 将下载的jar包复制到libs目录下, 然后,选择libs文件夹,鼠标右键选 Add to libs ...即可被引用. 如下图
接着,建一个类XposedHookUtil , 使用接口, 如下图,不报错就可以
public class XposedHookUtil implements IXposedHookLoadPackage {
public static final String PACKAGE_NAME = "com.example.xposeddemo";
public static final String CLASS_NAME_MAINACTIVITY = "com.example.xposeddemo.MainActivity";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
String packgageName = loadPackageParam.packageName;
//过滤包, 这么做,在当前的包下hook对就不会报错了
if (!PACKAGE_NAME.equals(packgageName)) {
if (packgageName.contains("com.example.xposeddemo")){
XposedHelpers.findAndHookMethod(CLASS_NAME_MAINACTIVITY,
loadPackageParam.classLoader, "getTTAd", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
//return null;
return "广告被拦截了";
}
});
//hook所有方法, 按需使用
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
ClassLoader cl = ((Context) param.args[0]).getClassLoader();
Class<?> clazz = null;
try{
clazz = cl.loadClass(CLASS_NAME_MAINACTIVITY);
}catch (Exception e){
Log.e("TAG >>>>>____1___>>>>>>", "find class is fail : msg:"+e.getMessage());
}
if (clazz != null){
XposedHelpers.findAndHookMethod(clazz, testMethod, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.e("TAG >>>>>___2____>>>>>>", testMethod+" method result : "+param.toString());
if (param.getResult() != null){
Set set = (Set) param.getResult();
Log.e("TAG >>>> return res", " ------------------ set size:"+set.size());
Iterator<Object> it = set.iterator();
int i = 1;
while (it.hasNext()){
Object o = it.next();
Log.e("TAG >>> ret listitem", (i++) +". next "+o.toString());
//反射获取对象中特定属性的值
Class clazz = o.getClass();
Field[] fields = clazz.getFields();//getDeclaredFields();
for (Field f : fields){
String cName = f.getName();
//boolean hasJsonProperty = f.isAnnotationPresent();
Object obj = f.get(o);
if (obj instanceof Long) {
Log.e("TAG >> listi", "attr name:"+cName+", long value:"+((long)obj));
} else if (obj instanceof String) {
Log.e("TAG >> listi", "attr name:"+cName+", String value:"+obj);
} else if (obj instanceof Integer) {
Log.e("TAG >> listi", "attr name:"+cName+", int value:"+((int)obj));
} else {
Log.e("TAG >> listi", "attr name:"+cName+", not know class of value");
}
}
}
}
super.afterHookedMethod(param);
}
});
}
Log.e("TAG >>>>>____1___>>>>>>", "method result : "+param.getResult());
super.afterHookedMethod(param);
}
});
Log.i("TAG >>>", "-END-");
}
}else{
Log.e("TAG E >>>", " 通过包"+packgageName);
}
}
}
还有MainActivity类, 贴上源码, 就不做解释了,还有页面布局,大致可以看出来
public class MainActivity extends AppCompatActivity {
private TextView tv_ad;
private Button btn_load_ad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_ad = findViewById(R.id.tv_ad);
btn_load_ad = findViewById(R.id.btn_load_ad);
btn_load_ad.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_ad.setText(getTTAd());
}
});
}
public String getTTAd(){
Log.e("+++++++>>>>>> TAG I", "MainActivity getTTAd()");
return "广告加载成功";
}
}接着,改下AndroidManifest.xml这个文件, 样子如下,只是添加了meta-data部分,这个等安装后, 信息xposeddescription是可以在Xposed框架app上的模块中看到
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xposeddemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="xposedmodule" android:value="true" />
<meta-data android:name="xposeddescription" android:value="test xposed module" />
<meta-data android:name="xposedminversion" android:value="54+" />
</application>
</manifest>接着,在文件夹asserts中创建一个文本文件名为xposed_init, 注意不能带.txt, 内容就是刚刚写好的XposedHookUtril类名,前面加上应用包名
com.example.xposeddemo.XposedHookUtil最后,打包安装前,确定一下, 需要改Module下的app的build.gradle文件,如下图
改动后内容是这样子的,就是其中compileOnly被替换了
dependencies {
compileOnly fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
compileOnly files('libs/api-82.jar')
}三,测试体验
每次修改模块app安装使用都需要重启机器, 选择 软重启 就可以, 这样就不会中断调试日志输出.
可被Xposed框架app检测到的模块, 如图:
顺利的话, 效果不错, 如图:
四,总结
笔者只是做个笔记总结, 不做多解释, 这里告一段落了, 如还有不明白的地方,建议看下笔者参考来源吧,
最后贴上参考文献来源:
- Xposed真的可以为所欲为 点我
- Xposed教程,含jar下载地址 点我
- Xposed框架的使用--简单入门 点我
- Xposed模块编写遇到的一些问题以及解决 点我
- 整理Android XposedHook使用问题 点我
- 反射获取对象中特定属性的值 点我
- Xposed使用教程 点我
- Xposed常用方法使用详解 点我