接上篇:使用QMUI Android框架美化UI主界面。
链接:https://blog.csdn.net/weixin_42127613/article/details/81843771
我们的模块,是否在Xposed框架中激活,最好给予用户提示。因为Xposed框架的模块,需要先激活,才能使用。很多初次接触的用户,往往在安装模块后,就忘记激活。导致模块没有生效,功能无法使用。
我们在主界面中提示用户,模块是否已激活。同时,我们检测一下Xposed是否已安装。
完成此次修改后,需要新增和修改的文件如下图所示。绿色为新增,蓝色为修改。
1、新建AppInfo类,用作存储APP相关的配置信息,比如一些环境检测的数据,还包含有环境检测的方法。把AppInfo类作为一个单例,放到entity包中。最终代码如下
public final class AppInfo {
//Xposed是否安装
private boolean mIsXposedInstall;
private String mXposedVersionName;
//region 单例
//单例
private static volatile AppInfo mInstance = null;
private AppInfo() {
}
public static AppInfo getInstance() {
if (mInstance == null) {
synchronized (AppInfo.class) {
if (mInstance == null) {
mInstance = new AppInfo();
}
}
}
return mInstance;
}
//endregion
//检测设备环境
public void ValidateEnvironment(Context context) {
//判断Xposed是否安装
mXposedVersionName = AppUtils.getAppVersionName(context, AppUtils.PACKAGE_NAME_XPOSED);
mIsXposedInstall = !StringUtils.isEmpty(getXposedVersionName());
}
//获取Xposed模块是否激活
public boolean isXposedActive() {
return AppUtils.isModuleActive();
}
public boolean isXposedInstall() {
return mIsXposedInstall;
}
public void setXposedInstall(boolean xposedInstall) {
mIsXposedInstall = xposedInstall;
}
public String getXposedVersionName() {
return mXposedVersionName;
}
public void setXposedVersionName(String xposedVersionName) {
mXposedVersionName = xposedVersionName;
}
}
2、新建AppUtils类,用于APP操作的通用方法,包括检测安装包等方法。还包括是否激活的返回代码。最终代码如下:
public final class AppUtils {
public static final String PACKAGE_NAME_XPOSED = "de.robv.android.xposed.installer";
//获取APP的安装版本号。未安装,返回空字符串。
public static String getAppVersionName(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
for (PackageInfo packageInfo : packageInfos) {
if (packageInfo.packageName.equals(packageName)) {
return packageInfo.versionName;
}
}
return "";
}
//Xposed模块是否激活。默认返回false;激活后hook将其值改为true
public static boolean isModuleActive() {
return false;
}
}
3、新建StringUtils类,仅仅是判断字符串是否为null或空。最终代码如下:
public final class StringUtils {
public static boolean isEmpty(final CharSequence s) {
return s == null || s.length() == 0;
}
}
4、修改MainActivity主页面类。
加入QMUIGroupListView成员变量、初始化方法、以及环境调用检测。最终代码为:
public class MainActivity extends Activity {
@BindView(R.id.topbar) QMUITopBar mTopBar;
@BindView(R.id.groupListView) QMUIGroupListView mGroupListView;
private final String TAG = getClass().getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 沉浸式状态栏
QMUIStatusBarHelper.translucent(this);
View root = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
ButterKnife.bind(this, root);
//初始化状态栏
initTopBar();
//设置view
setContentView(root);
//检测环境
AppInfo.getInstance().ValidateEnvironment(this);
//初始化QMUIGroupListView
initMainContentView();
}
//初始化状态栏
private void initTopBar() {
mTopBar.setTitle(getResources().getString(R.string.activity_title_main));
}
//初始化QMUIGroupListView
private void initMainContentView() {
AppInfo appInfo = AppInfo.getInstance();
boolean boolResult;
String strResult = "";
//region Xposed框架状态
//Xposed版本
QMUICommonListItemView listItemXposed = mGroupListView.createItemView("Xposed版本");
boolResult = appInfo.isXposedInstall();
listItemXposed.setDetailText(boolResult ? "V" + appInfo.getXposedVersionName() : "未安装");
listItemXposed.setImageDrawable(getResources().getDrawable(boolResult ? R.drawable.qmui_icon_checkbox_checked : R.mipmap.icon_error));
//Xposed模块激活
QMUICommonListItemView listItemXposedActive = mGroupListView.createItemView("Xposed模块激活");
boolResult = appInfo.isXposedActive();
listItemXposedActive.setDetailText(boolResult ? "已激活" : "未激活");
listItemXposedActive.setImageDrawable(getResources().getDrawable(boolResult ? R.drawable.qmui_icon_checkbox_checked : R.mipmap.icon_error));
QMUIGroupListView.newSection(this)
.setTitle("Xposed框架状态")
.addItemView(listItemXposed, null)
.addItemView(listItemXposedActive, null)
.addTo(mGroupListView);
//endregion
}
}
现在编译、运行,看看界面效果。如下图所示。已经有了Xposed版本的安装检测,在主界面上给予显示。
最后,我们加入Xposed模块是否激活的判断。
此部分工作,要在MainXposed类中做。在handleLoadPackage方法在最前面,加入激活处理。hook到我们自己的APP,修改静态方法的返回值。如果是激活了,那么就能将这个返回值修改为true,否则就会按原方法,返回false。
//聊天精灵客户端包名称
private static final String WECHATGENIUS_PACKAGE_NAME = "net.dalu2048.wechatgenius";
//region hook模块是否激活
if (lpparam.packageName.equals(WECHATGENIUS_PACKAGE_NAME)) {
//hook客户端APP的是否激活返回值。替换为true。
Class<?> classAppUtils = XposedHelpers.findClassIfExists(WECHATGENIUS_PACKAGE_NAME + ".util.AppUtils", lpparam.classLoader);
if (classAppUtils != null) {
XposedHelpers.findAndHookMethod(classAppUtils,
"isModuleActive",
XC_MethodReplacement.returnConstant(true));
XposedBridge.log("成功hook住net.xxfeng.cc.util.AppUtils的isModuleActive方法。");
}
return;
}
//endregion
最终运行效果如下。顺利完成激活判断。
OK。到此,我们完成了Xposed模块的激活判断,以及UI显示。
代码已提交至GitHub:https://github.com/dalu2048/WeChatGenius
下节将加入更多判断,判断Android系统版本、微信版本、是否root。
下节文章链接:https://blog.csdn.net/weixin_42127613/article/details/81869354