编写微信聊天机器人7《聊天精灵WeChatGenius》:判断Xposed是否安装,以及模块是否激活

版权声明:允许转载,请注明来源。 https://blog.csdn.net/weixin_42127613/article/details/81868440

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

猜你喜欢

转载自blog.csdn.net/weixin_42127613/article/details/81868440
今日推荐