接上篇:使用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