Android动态代理实现修改App版本号
Posted 胖子爱你520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android动态代理实现修改App版本号相关的知识,希望对你有一定的参考价值。
应用场景
通过这个案例,我们可以了解一下动态代理技术,并且能够在不改变版本号的情况下,动态修改版本号进行升级功能的测试,主要实现原理是通过动态代理getPackageInfo()来mock数据。
一、创建PackageManagerHook代理类
public class PackageManagerHook
/**
* 越早hook越好,推荐在Application.attachBaseContext中调用
*/
public static void hook(final Context context)
try
//1、得到ActivityThread类
Class<?> activityThreadClz = Class.forName("android.app.ActivityThread");
Method currentActivityThread = activityThreadClz.getMethod("currentActivityThread");
//2、得到当前的ActivityThread对象
Object activityThread = currentActivityThread.invoke(null);
//3、得到PackageManager对象
Method getPackageManager = activityThreadClz.getMethod("getPackageManager");
final Object pkgManager = getPackageManager.invoke(activityThread);
Class<?> packageManagerClz = Class.forName("android.content.pm.IPackageManager");
//hook sPackageManager
Field packageManagerField = activityThreadClz.getDeclaredField("sPackageManager");
packageManagerField.setAccessible(true);
//动态代理
packageManagerField.set(activityThread, Proxy.newProxyInstance(context.getClassLoader(),
new Class[] packageManagerClz , new InvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Object result = method.invoke(pkgManager,args);
if ("getPackageInfo".equals(method.getName()))
PackageInfo pkgInfo = (PackageInfo) result;
//修改App的版本信息
pkgInfo.versionCode = 520;
pkgInfo.versionName = "version:5.2.0";
return result;
));
catch (ClassNotFoundException e)
e.printStackTrace();
catch (NoSuchMethodException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InvocationTargetException e)
e.printStackTrace();
catch (NoSuchFieldException e)
e.printStackTrace();
二、创建ProxyApplication
public class ProxyApplication extends Application
@Override
protected void attachBaseContext(Context base)
super.attachBaseContext(base);
PackageManagerHook.hook(this);
三、在AndroidManifest.xml设置
<application
android:name=".ProxyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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>
</application>
四、创建布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#222222"
android:textSize="18dp" />
</RelativeLayout>
五、在Activity中取值
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.text);
PackageManager manager = this.getPackageManager();
try
PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
textView.setText(info.versionName + "," + info.versionCode);
catch (PackageManager.NameNotFoundException e)
e.printStackTrace();
六、运行结果
小结
通过上述步骤,我们可以通过动态代理技术,修改App的版本号和版本名,重点理解一下PackageManagerHook中的代码,祝大家学习愉快~
以上是关于Android动态代理实现修改App版本号的主要内容,如果未能解决你的问题,请参考以下文章