diff --git a/docs/api/public/YukiHookAPI.md b/docs/api/public/YukiHookAPI.md index af90b1f9..755ecd34 100644 --- a/docs/api/public/YukiHookAPI.md +++ b/docs/api/public/YukiHookAPI.md @@ -304,6 +304,26 @@ var isEnableHookModuleStatus: Boolean !> 关闭后你将不能再在模块环境中使用 `YukiHookAPI.Status` 中的功能。 +#### isEnableHookSharedPreferences *- field* + +```kotlin +var isEnableHookSharedPreferences: Boolean +``` + +**变更记录** + +`v1.0.93` `新增` + +**功能描述** + +> 是否启用 Hook `SharedPreferences`。 + +启用后将在模块启动时强制将 `SharedPreferences` 文件权限调整为 `Context.MODE_WORLD_READABLE` (0644)。 + +!> 这是一个可选的实验性功能,此功能默认不启用。 + +仅用于修复某些系统可能会出现在启用了 `New XSharedPreferences` 后依然出现文件权限错误问题,若你能正常使用 `YukiHookModulePrefs` 就不建议启用此功能。 + #### isEnableDataChannel *- field* ```kotlin diff --git a/docs/api/public/YukiHookModulePrefs.md b/docs/api/public/YukiHookModulePrefs.md index f44ef27a..d91bdbc4 100644 --- a/docs/api/public/YukiHookModulePrefs.md +++ b/docs/api/public/YukiHookModulePrefs.md @@ -20,6 +20,8 @@ class YukiHookModulePrefs private constructor(private var context: Context?) 详见 [New XSharedPreferences](https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module)。 +若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 [isEnableHookSharedPreferences](api/document?id=isenablehooksharedpreferences-field)。 + 未使用 LSPosed 环境请将你的模块 `API` 降至 `26` 以下,`YukiHookAPI` 将会尝试使用 `makeWorldReadable` 但仍有可能不成功。 太极请参阅 [文件权限/配置/XSharedPreference](https://taichi.cool/zh/doc/for-xposed-dev.html#文件权限-配置-xsharedpreference)。 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index d3c54293..f8152be1 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -31,6 +31,7 @@ package com.highcapable.yukihookapi import android.app.Application import android.content.Context +import android.content.SharedPreferences import android.content.res.Resources import com.highcapable.yukihookapi.YukiHookAPI.configs import com.highcapable.yukihookapi.YukiHookAPI.encase @@ -221,6 +222,17 @@ object YukiHookAPI { */ var isEnableHookModuleStatus = true + /** + * 是否启用 Hook [SharedPreferences] + * + * 启用后将在模块启动时强制将 [SharedPreferences] 文件权限调整为 [Context.MODE_WORLD_READABLE] (0644) + * + * - ❗这是一个可选的实验性功能 - 此功能默认不启用 + * + * - 仅用于修复某些系统可能会出现在启用了 New XSharedPreferences 后依然出现文件权限错误问题 - 若你能正常使用 [YukiHookModulePrefs] 就不建议启用此功能 + */ + var isEnableHookSharedPreferences = false + /** * 是否启用当前 Xposed 模块与宿主交互的 [YukiHookDataChannel] 功能 * diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt index 338181ae..69d075d8 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt @@ -40,8 +40,10 @@ import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.type.HookEntryType import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper +import com.highcapable.yukihookapi.hook.type.android.ContextImplClass import com.highcapable.yukihookapi.hook.xposed.bridge.dummy.YukiResources import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper +import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiMemberHook import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiMemberReplacement import com.highcapable.yukihookapi.hook.xposed.bridge.inject.YukiHookBridge_Injector import com.highcapable.yukihookapi.hook.xposed.bridge.status.YukiHookModuleStatus @@ -210,8 +212,13 @@ object YukiHookBridge { */ @YukiGenerateApi fun hookModuleAppStatus(loader: ClassLoader?, isHookResourcesStatus: Boolean = false) { - if (YukiHookAPI.Configs.isEnableHookModuleStatus.not()) return - classOf(loader).apply { + if (YukiHookAPI.Configs.isEnableHookSharedPreferences) + YukiHookHelper.hook(ContextImplClass.method { name = "setFilePermissionsFromMode" }, object : YukiMemberHook() { + override fun beforeHookedMember(wrapper: HookParamWrapper) { + if ((wrapper.args?.get(0) as? String?)?.endsWith(suffix = "preferences.xml") == true) wrapper.args?.set(1, 1) + } + }) + if (YukiHookAPI.Configs.isEnableHookModuleStatus) classOf(loader).apply { if (isHookResourcesStatus.not()) { YukiHookHelper.hook(method { name = YukiHookModuleStatus.IS_ACTIVE_METHOD_NAME }, object : YukiMemberReplacement() { override fun replaceHookedMember(wrapper: HookParamWrapper) = true