如何实现不安装xpoedinstall激活xposed模块
前言
xpoedinstall及安裝器,它的作用有幾個:安裝xposed框架、激活xposed模塊、搜索模塊等等
如果我們已經安裝了xposed框架,或者說我們自己二次開發了這個框架,通過手動的方式安裝。然后需要使用我們自己的xposed模塊,這時xposedinstall的作用就只剩激活模塊了,那么我們是否可以擺脫它來激活模塊?
源碼
先來看看它如何激活模塊的
在它的源碼中有一個ModuleUtil類,其中
public void setModuleEnabled(String packageName, boolean enabled) {if (enabled)mPref.edit().putInt(packageName, 1).apply();elsemPref.edit().remove(packageName).apply(); }可以看到將激活的模塊的包名存到了sharepreference中,然后還有另外一個類
public synchronized void updateModulesList(boolean showToast) {try {Log.i(XposedApp.TAG, "updating modules.list");int installedXposedVersion = XposedApp.getInstalledXposedVersion();PrintWriter modulesList = new PrintWriter(MODULES_LIST_FILE);PrintWriter enabledModulesList = new PrintWriter(XposedApp.ENABLED_MODULES_LIST_FILE);List<InstalledModule> enabledModules = getEnabledModules();for (InstalledModule module : enabledModules) {if (module.minVersion > installedXposedVersion || module.minVersion < MIN_MODULE_VERSION)continue;modulesList.println(module.app.sourceDir);try {String installer = mPm.getInstallerPackageName(module.app.packageName);if (!PLAY_STORE_PACKAGE.equals(installer)) {enabledModulesList.println(module.app.packageName);}} catch (IllegalArgumentException ignored) {// In rare cases, the package might not be installed anymore at this point,// so the PackageManager can't return its installer package name.}}modulesList.close();enabledModulesList.close();FileUtils.setPermissions(MODULES_LIST_FILE, 00664, -1, -1);FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1);if (showToast)showToast(R.string.xposed_module_list_updated);} catch (IOException e) {Log.e(XposedApp.TAG, "cannot write " + MODULES_LIST_FILE, e);Toast.makeText(mApp, "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show();} }這里有一個getEnableModules函數,如下:
public List<InstalledModule> getEnabledModules() {LinkedList<InstalledModule> result = new LinkedList<InstalledModule>();for (String packageName : mPref.getAll().keySet()) {InstalledModule module = getModule(packageName);if (module != null)result.add(module);elsesetModuleEnabled(packageName, false);}return result; }可以看到這個函數正是從剛才sharepreference中讀取激活的模塊包名
然后回到updateModulesList中,可以看到將這些激活的模塊的sourceDir保存到MODULES_LIST_FILE這個文件中,即:
private static final String MODULES_LIST_FILE = XposedApp.BASE_DIR + "conf/modules.list";以上就是xposedinstaller激活模塊的流程,可以看到就是將要激活的模塊的apk地址保存到一個modules.list文件中。看來真正激活使用模塊是在xposedbridge中,在它的main函數中(XposedBridge類)
protected static void main(String[] args) {// Initialize the Xposed framework and modulestry {if (!hadInitErrors()) {initXResources();SELinuxHelper.initOnce();SELinuxHelper.initForProcess(null);runtime = getRuntime();XPOSED_BRIDGE_VERSION = getXposedVersion();if (isZygote) {XposedInit.hookResources();XposedInit.initForZygote();}XposedInit.loadModules();} else {Log.e(TAG, "Not initializing Xposed because of previous errors");}} catch (Throwable t) {Log.e(TAG, "Errors during Xposed initialization", t);disableHooks = true;}// Call the original startup codeif (isZygote) {ZygoteInit.main(args);} else {RuntimeInit.main(args);} }主要是XposedInit.loadModules()這句,這個函數的代碼:
static void loadModules() throws IOException {final String filename = BASE_DIR + "conf/modules.list";BaseService service = SELinuxHelper.getAppDataFileService();if (!service.checkFileExists(filename)) {Log.e(TAG, "Cannot load any modules because " + filename + " was not found");return;}ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER;ClassLoader parent;while ((parent = topClassLoader.getParent()) != null) {topClassLoader = parent;}InputStream stream = service.getFileInputStream(filename);BufferedReader apks = new BufferedReader(new InputStreamReader(stream));String apk;while ((apk = apks.readLine()) != null) {loadModule(apk, topClassLoader);}apks.close(); }這里可以看到從modules.list文件中讀取已激活模塊的apk地址,然后執行loadModule將其加載進來,loadModule中會有一些判斷,比如說是否有assets/xposed_init文件等等,如果都正常就會將這個apk的class加載進內存中,后續就會調用他們,實際上就是將模塊的代碼注入到xposedbridge中來使用。這部分代碼就不細說了。
(實際上,真正hook都是在xposedbridge中的,如果我們直接在這里寫hook代碼也是可以的,只是這樣就無法靈活修改了。所以我們將hook代碼寫在apk中,然后在這里將這些類加載進來,然后xposedbridge再調用它的hookLoadPackage之類的代碼就可以了)
結論
所以通過上面我們可以知道,我們完全可以拋開xposedinstaller,當我們安裝app并打開時,可以自己創建或修改modules.list文件,將自己app加進入就可以了。當然還要重啟手機,從上面可以看到,因為加載模塊的代碼是在main函數中執行的,所以只有重啟手機才會再次執行。
當然這個默認的modules.list我們可能需要root權限才能讀寫,但是如果我們自己二次開發xposed,可以在xposedbridge中將這個文件路徑改成sd卡下可以任意讀寫的路徑,這樣我們的app就可以隨意進行改寫了。
或者我們提前準好這個文件手動放到手機中,文件內容是一個未安裝的apk的路徑,比如/sdcard/123.apk,這樣不需要安裝應該就可以直接使用。這個我沒有測試,效果待驗證。
關注公眾號:BennuCTech,獲取更多干貨!
總結
以上是生活随笔為你收集整理的如何实现不安装xpoedinstall激活xposed模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现一个悬浮在软键盘上的输入栏
- 下一篇: 解决No version of NDK