編寫微信聊天機器人7《聊天精靈WeChatGenius》:判斷Xposed是否安裝,以及模塊是否激活

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章