mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-01 08:15:37 +08:00
Added new documentations files
This commit is contained in:
3
docs-source/.gitignore
vendored
Normal file
3
docs-source/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
src/.vuepress/.cache
|
||||
src/.vuepress/.temp
|
0
docs-source/.nojekyll
Normal file
0
docs-source/.nojekyll
Normal file
3
docs-source/.vscode/settings.json
vendored
Normal file
3
docs-source/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
15
docs-source/package.json
Normal file
15
docs-source/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "yukihookapi_docs",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@mr-hope/vuepress-plugin-copy-code": "^1.30.0",
|
||||
"@vuepress/plugin-prismjs": "^2.0.0-beta.51",
|
||||
"@vuepress/plugin-search": "^2.0.0-beta.51",
|
||||
"@vuepress/plugin-shiki": "^2.0.0-beta.51",
|
||||
"vuepress": "^2.0.0-beta.51"
|
||||
},
|
||||
"scripts": {
|
||||
"docs:dev": "vuepress dev src",
|
||||
"docs:build": "vuepress build src"
|
||||
}
|
||||
}
|
60
docs-source/src/.vuepress/config.ts
Normal file
60
docs-source/src/.vuepress/config.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { defaultTheme } from 'vuepress';
|
||||
import { shikiPlugin } from '@vuepress/plugin-shiki';
|
||||
import { searchPlugin } from '@vuepress/plugin-search';
|
||||
import { navBarItems, sideBarItems, configs } from './configs/template';
|
||||
|
||||
export default {
|
||||
dest: configs.dev.dest,
|
||||
port: configs.dev.port,
|
||||
base: configs.website.base,
|
||||
head: [['link', { rel: 'icon', href: configs.website.icon }]],
|
||||
title: configs.website.title,
|
||||
description: configs.website.locales['/en/'].description,
|
||||
locales: configs.website.locales,
|
||||
theme: defaultTheme({
|
||||
logo: configs.website.icon,
|
||||
repo: configs.github.repo,
|
||||
docsRepo: configs.github.repo,
|
||||
docsBranch: configs.github.branch,
|
||||
docsDir: configs.github.dir,
|
||||
editLinkPattern: ':repo/edit/:branch/:path',
|
||||
sidebar: sideBarItems,
|
||||
sidebarDepth: 2,
|
||||
locales: {
|
||||
'/en/': {
|
||||
navbar: navBarItems['/en/'],
|
||||
selectLanguageText: 'English (US)',
|
||||
selectLanguageName: 'English',
|
||||
editLinkText: 'Edit this page on Github',
|
||||
tip: 'Tips',
|
||||
warning: 'Notice',
|
||||
danger: 'Pay Attention',
|
||||
},
|
||||
'/zh-cn/': {
|
||||
navbar: navBarItems['/zh-cn/'],
|
||||
selectLanguageText: '简体中文 (CN)',
|
||||
selectLanguageName: '简体中文',
|
||||
editLinkText: '在 Github 上编辑此页',
|
||||
notFound: ['这里什么都没有', '我们怎么到这来了?', '这是一个 404 页面', '看起来我们进入了错误的链接'],
|
||||
backToHome: '回到首页',
|
||||
contributorsText: '贡献者',
|
||||
lastUpdatedText: '上次更新',
|
||||
tip: '小提示',
|
||||
warning: '注意',
|
||||
danger: '特别注意',
|
||||
openInNewWindow: '在新窗口中打开',
|
||||
toggleColorMode: '切换颜色模式'
|
||||
}
|
||||
},
|
||||
}),
|
||||
plugins: [
|
||||
shikiPlugin({ theme: 'github-dark-dimmed' }),
|
||||
searchPlugin({
|
||||
isSearchable: (page) => page.path !== '/',
|
||||
locales: {
|
||||
'/en/': { placeholder: 'Search' },
|
||||
'/zh-cn/': { placeholder: '搜索' }
|
||||
}
|
||||
})
|
||||
]
|
||||
};
|
271
docs-source/src/.vuepress/configs/template.ts
Normal file
271
docs-source/src/.vuepress/configs/template.ts
Normal file
@@ -0,0 +1,271 @@
|
||||
import { i18n } from './utils';
|
||||
|
||||
const baseApiPath = '/api/public/com/highcapable/yukihookapi/';
|
||||
|
||||
const navigationLinks = {
|
||||
start: [
|
||||
'/guide/home',
|
||||
'/guide/knowledge',
|
||||
'/guide/quick-start',
|
||||
'/guide/example',
|
||||
'/guide/move-to-new-api'
|
||||
],
|
||||
config: [
|
||||
'/config/api-example',
|
||||
'/config/api-exception',
|
||||
'/config/xposed-using',
|
||||
'/config/api-using',
|
||||
'/config/r8-proguard'
|
||||
],
|
||||
tools: '/tools/yukihookapi-projectbuilder',
|
||||
apiDocs: [
|
||||
'/api/home',
|
||||
'/api/public/',
|
||||
'/api/special-features/'
|
||||
],
|
||||
publicApi: [
|
||||
baseApiPath + 'YukiHookAPI',
|
||||
baseApiPath + 'hook/param/PackageParam',
|
||||
baseApiPath + 'hook/param/HookParam',
|
||||
baseApiPath + 'annotation/xposed/InjectYukiHookWithXposed',
|
||||
baseApiPath + 'hook/xposed/proxy/IYukiHookXposedInit',
|
||||
baseApiPath + 'hook/xposed/prefs/YukiHookModulePrefs',
|
||||
baseApiPath + 'hook/xposed/prefs/ui/ModulePreferenceFragment',
|
||||
baseApiPath + 'hook/xposed/prefs/data/PrefsData',
|
||||
baseApiPath + 'hook/xposed/channel/YukiHookDataChannel',
|
||||
baseApiPath + 'hook/xposed/channel/data/ChannelData',
|
||||
baseApiPath + 'hook/xposed/application/ModuleApplication',
|
||||
baseApiPath + 'hook/xposed/parasitic/activity/base/ModuleAppActivity',
|
||||
baseApiPath + 'hook/xposed/parasitic/activity/base/ModuleAppCompatActivity',
|
||||
baseApiPath + 'hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper',
|
||||
baseApiPath + 'hook/xposed/bridge/dummy/YukiModuleResources',
|
||||
baseApiPath + 'hook/xposed/bridge/dummy/YukiResources',
|
||||
baseApiPath + 'hook/xposed/bridge/dummy/YukiResForwarder',
|
||||
baseApiPath + 'hook/xposed/bridge/event/YukiXposedEvent',
|
||||
baseApiPath + 'hook/type/android/ComponentTypeFactory',
|
||||
baseApiPath + 'hook/type/android/GraphicsTypeFactory',
|
||||
baseApiPath + 'hook/type/android/ViewTypeFactory',
|
||||
baseApiPath + 'hook/type/java/VariableTypeFactory',
|
||||
baseApiPath + 'hook/type/defined/DefinedTypeFactory',
|
||||
baseApiPath + 'hook/log/LoggerFactory',
|
||||
baseApiPath + 'hook/factory/ReflectionFactory',
|
||||
baseApiPath + 'hook/factory/YukiHookFactory',
|
||||
baseApiPath + 'hook/entity/YukiBaseHooker',
|
||||
baseApiPath + 'hook/core/YukiMemberHookCreator',
|
||||
baseApiPath + 'hook/core/YukiResourcesHookCreator',
|
||||
baseApiPath + 'hook/core/finder/members/MethodFinder',
|
||||
baseApiPath + 'hook/core/finder/members/ConstructorFinder',
|
||||
baseApiPath + 'hook/core/finder/members/FieldFinder',
|
||||
baseApiPath + 'hook/core/finder/base/BaseFinder',
|
||||
baseApiPath + 'hook/core/finder/base/rules/CountRules',
|
||||
baseApiPath + 'hook/core/finder/base/rules/ModifierRules',
|
||||
baseApiPath + 'hook/core/finder/base/rules/NameRules',
|
||||
baseApiPath + 'hook/bean/HookClass',
|
||||
baseApiPath + 'hook/bean/VariousClass',
|
||||
baseApiPath + 'hook/bean/CurrentClass',
|
||||
baseApiPath + 'hook/bean/HookResources'
|
||||
],
|
||||
specialFeature: [
|
||||
'/api/special-features/reflection',
|
||||
'/api/special-features/logger',
|
||||
'/api/special-features/xposed-prefs',
|
||||
'/api/special-features/xposed-channel',
|
||||
'/api/special-features/host-lifecycle',
|
||||
'/api/special-features/host-inject'
|
||||
],
|
||||
about: [
|
||||
'/about/changelog',
|
||||
'/about/future',
|
||||
'/about/contacts',
|
||||
'/about/about'
|
||||
]
|
||||
};
|
||||
|
||||
export const configs = {
|
||||
dev: {
|
||||
dest: '../docs/',
|
||||
port: 9000
|
||||
},
|
||||
website: {
|
||||
base: '/YukiHookAPI/',
|
||||
icon: '/images/logo.png',
|
||||
title: 'Yuki Hook API',
|
||||
locales: {
|
||||
'/en/': {
|
||||
lang: 'en-US',
|
||||
description: 'An efficient Kotlin version of the Xposed Hook API'
|
||||
},
|
||||
'/zh-cn/': {
|
||||
lang: 'zh-CN',
|
||||
description: '一个使用 Kotlin 重构的轻量、高效、稳定的 Xposed Hook API'
|
||||
}
|
||||
}
|
||||
},
|
||||
github: {
|
||||
repo: 'https://github.com/fankes/YukiHookAPI',
|
||||
branch: 'master',
|
||||
dir: 'docs/src'
|
||||
}
|
||||
};
|
||||
|
||||
export const navBarItems = {
|
||||
'/en/': [{
|
||||
text: 'Navigation',
|
||||
children: [{
|
||||
text: 'Get Started',
|
||||
children: [
|
||||
{ text: 'Introduce', link: i18n.string(navigationLinks.start[0], 'en') },
|
||||
{ text: 'Basic Knowledge', link: i18n.string(navigationLinks.start[1], 'en') },
|
||||
{ text: 'Quick Start', link: i18n.string(navigationLinks.start[2], 'en') },
|
||||
{ text: 'Usage Example', link: i18n.string(navigationLinks.start[3], 'en') },
|
||||
{ text: 'Migrate from Xposed API', link: i18n.string(navigationLinks.start[4], 'en') }
|
||||
]
|
||||
}, {
|
||||
text: 'Configs',
|
||||
children: [
|
||||
{ text: 'API Basic Configs', link: i18n.string(navigationLinks.config[0], 'en') },
|
||||
{ text: 'API Exception Handling', link: i18n.string(navigationLinks.config[1], 'en') },
|
||||
{ text: 'Use as Xposed Module Configs', link: i18n.string(navigationLinks.config[2], 'en') },
|
||||
{ text: 'Use as Hook API Configs', link: i18n.string(navigationLinks.config[3], 'en') },
|
||||
{ text: 'R8 & Proguard Obfuscate', link: i18n.string(navigationLinks.config[4], 'en') }
|
||||
]
|
||||
}, {
|
||||
text: 'Tools',
|
||||
children: [
|
||||
{ text: 'YukiHookAPI Project Builder', link: i18n.string(navigationLinks.tools, 'en') }
|
||||
]
|
||||
}, {
|
||||
text: 'API Document',
|
||||
children: [{ text: 'Document Introduction', link: i18n.string(navigationLinks.apiDocs[0], 'en') }, {
|
||||
text: 'Public API',
|
||||
link: i18n.string(navigationLinks.publicApi[0], 'en'),
|
||||
activeMatch: i18n.string(navigationLinks.apiDocs[1], 'en')
|
||||
}, {
|
||||
text: 'Special Features',
|
||||
link: i18n.string(navigationLinks.specialFeature[0], 'en'),
|
||||
activeMatch: i18n.string(navigationLinks.apiDocs[2], 'en')
|
||||
}]
|
||||
}, {
|
||||
text: 'About',
|
||||
children: [
|
||||
{ text: 'Changelog', link: i18n.string(navigationLinks.about[0], 'en') },
|
||||
{ text: 'Looking for future', link: i18n.string(navigationLinks.about[1], 'en') },
|
||||
{ text: 'Contact Us', link: i18n.string(navigationLinks.about[2], 'en') },
|
||||
{ text: 'About this document', link: i18n.string(navigationLinks.about[3], 'en') }
|
||||
]
|
||||
}]
|
||||
}, {
|
||||
text: 'Contact Us',
|
||||
link: i18n.string(navigationLinks.about[2], 'en')
|
||||
}],
|
||||
'/zh-cn/': [{
|
||||
text: '导航',
|
||||
children: [{
|
||||
text: '入门',
|
||||
children: [
|
||||
{ text: '介绍', link: i18n.string(navigationLinks.start[0], 'zh-cn') },
|
||||
{ text: '基础知识', link: i18n.string(navigationLinks.start[1], 'zh-cn') },
|
||||
{ text: '快速开始', link: i18n.string(navigationLinks.start[2], 'zh-cn') },
|
||||
{ text: '用法示例', link: i18n.string(navigationLinks.start[3], 'zh-cn') },
|
||||
{ text: '从 Xposed API 迁移', link: i18n.string(navigationLinks.start[4], 'zh-cn') }
|
||||
]
|
||||
}, {
|
||||
text: '配置',
|
||||
children: [
|
||||
{ text: 'API 基本配置', link: i18n.string(navigationLinks.config[0], 'zh-cn') },
|
||||
{ text: 'API 异常处理', link: i18n.string(navigationLinks.config[1], 'zh-cn') },
|
||||
{ text: '作为 Xposed 模块使用的相关配置', link: i18n.string(navigationLinks.config[2], 'zh-cn') },
|
||||
{ text: '作为 Hook API 使用的相关配置', link: i18n.string(navigationLinks.config[3], 'zh-cn') },
|
||||
{ text: 'R8 与 Proguard 混淆', link: i18n.string(navigationLinks.config[4], 'zh-cn') }
|
||||
]
|
||||
}, {
|
||||
text: '工具',
|
||||
children: [
|
||||
{ text: 'YukiHookAPI 构建工具', link: i18n.string(navigationLinks.tools, 'zh-cn') }
|
||||
]
|
||||
}, {
|
||||
text: 'API 文档',
|
||||
children: [{ text: '文档介绍', link: i18n.string(navigationLinks.apiDocs[0], 'zh-cn') }, {
|
||||
text: 'Public API',
|
||||
link: i18n.string(navigationLinks.publicApi[0], 'zh-cn'),
|
||||
activeMatch: i18n.string(navigationLinks.apiDocs[1], 'zh-cn')
|
||||
}, {
|
||||
text: '特色功能',
|
||||
link: i18n.string(navigationLinks.specialFeature[0], 'zh-cn'),
|
||||
activeMatch: i18n.string(navigationLinks.apiDocs[2], 'zh-cn')
|
||||
}]
|
||||
}, {
|
||||
text: '关于',
|
||||
children: [
|
||||
{ text: '更新日志', link: i18n.string(navigationLinks.about[0], 'zh-cn') },
|
||||
{ text: '展望未来', link: i18n.string(navigationLinks.about[1], 'zh-cn') },
|
||||
{ text: '联系我们', link: i18n.string(navigationLinks.about[2], 'zh-cn') },
|
||||
{ text: '关于此文档', link: i18n.string(navigationLinks.about[3], 'zh-cn') }
|
||||
]
|
||||
}]
|
||||
}, {
|
||||
text: '联系我们',
|
||||
link: i18n.string(navigationLinks.about[2], 'zh-cn')
|
||||
}]
|
||||
};
|
||||
|
||||
export const sideBarItems = {
|
||||
'/en/': [{
|
||||
text: 'Get Started',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.start, 'en')
|
||||
}, {
|
||||
text: 'Configs',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.config, 'en')
|
||||
}, {
|
||||
text: 'Tools',
|
||||
collapsible: true,
|
||||
children: [i18n.string(navigationLinks.tools, 'en')]
|
||||
}, {
|
||||
text: 'API Document',
|
||||
collapsible: true,
|
||||
children: [i18n.string(navigationLinks.apiDocs[0], 'en'), {
|
||||
text: 'Public API' + i18n.space,
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.publicApi, 'en')
|
||||
}, {
|
||||
text: 'Special Features' + i18n.space,
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.specialFeature, 'en')
|
||||
}]
|
||||
}, {
|
||||
text: 'About',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.about, 'en')
|
||||
}],
|
||||
'/zh-cn/': [{
|
||||
text: '入门',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.start, 'zh-cn')
|
||||
}, {
|
||||
text: '配置',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.config, 'zh-cn')
|
||||
}, {
|
||||
text: '工具',
|
||||
collapsible: true,
|
||||
children: [i18n.string(navigationLinks.tools, 'zh-cn')]
|
||||
}, {
|
||||
text: 'API 文档',
|
||||
collapsible: true,
|
||||
children: [i18n.string(navigationLinks.apiDocs[0], 'zh-cn'), {
|
||||
text: 'Public API' + i18n.space,
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.publicApi, 'zh-cn')
|
||||
}, {
|
||||
text: '特色功能' + i18n.space,
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.specialFeature, 'zh-cn')
|
||||
}]
|
||||
}, {
|
||||
text: '关于',
|
||||
collapsible: true,
|
||||
children: i18n.array(navigationLinks.about, 'zh-cn')
|
||||
}]
|
||||
};
|
13
docs-source/src/.vuepress/configs/utils.ts
Normal file
13
docs-source/src/.vuepress/configs/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export const i18n = {
|
||||
space: ' ',
|
||||
string: (content: string, locale: string) => {
|
||||
return '/' + locale + content;
|
||||
},
|
||||
array: (contents: string[], locale: string) => {
|
||||
const newContents: string[] = [];
|
||||
contents.forEach((content) => {
|
||||
newContents.push(i18n.string(content, locale));
|
||||
});
|
||||
return newContents;
|
||||
}
|
||||
};
|
BIN
docs-source/src/.vuepress/public/images/logo.png
Normal file
BIN
docs-source/src/.vuepress/public/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 355 KiB |
Binary file not shown.
After Width: | Height: | Size: 667 KiB |
171
docs-source/src/.vuepress/styles/index.scss
Normal file
171
docs-source/src/.vuepress/styles/index.scss
Normal file
@@ -0,0 +1,171 @@
|
||||
$primary-color: rgb(237, 150, 73);
|
||||
$accent-color: rgb(244, 200, 161);
|
||||
$content-width: 965px;
|
||||
$scroll-bar-width: 8px;
|
||||
$scroll-bar-height: 6.5px;
|
||||
$scroll-bar-border-radius: 50px;
|
||||
$scroll-bar-track-color-code: rgb(86, 96, 110);
|
||||
$scroll-bar-thumb-hover-color-code: rgb(121, 135, 155);
|
||||
|
||||
:root {
|
||||
--c-brand: #{$primary-color};
|
||||
--c-brand-light: #{$accent-color};
|
||||
--content-width: #{$content-width};
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 3px 5px 3px 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.custom-container {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.language-text {
|
||||
::-webkit-scrollbar-track {
|
||||
background: #{$scroll-bar-track-color-code};
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #{$scroll-bar-thumb-hover-color-code};
|
||||
}
|
||||
}
|
||||
|
||||
.language-kotlin {
|
||||
::-webkit-scrollbar-track {
|
||||
background: #{$scroll-bar-track-color-code};
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #{$scroll-bar-thumb-hover-color-code};
|
||||
}
|
||||
}
|
||||
|
||||
.language-java {
|
||||
::-webkit-scrollbar-track {
|
||||
background: #{$scroll-bar-track-color-code};
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #{$scroll-bar-thumb-hover-color-code};
|
||||
}
|
||||
}
|
||||
|
||||
.language-groovy {
|
||||
::-webkit-scrollbar-track {
|
||||
background: #{$scroll-bar-track-color-code};
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #{$scroll-bar-thumb-hover-color-code};
|
||||
}
|
||||
}
|
||||
|
||||
.language-xml {
|
||||
::-webkit-scrollbar-track {
|
||||
background: #{$scroll-bar-track-color-code};
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #{$scroll-bar-thumb-hover-color-code};
|
||||
}
|
||||
}
|
||||
|
||||
.code-page {
|
||||
h1 {
|
||||
font-size: 24pt;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 18pt;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 15pt;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 9.6pt;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 8.4pt;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
color: rgb(142, 155, 168);
|
||||
}
|
||||
|
||||
.deprecated {
|
||||
color: rgb(142, 155, 168);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: #{$scroll-bar-width};
|
||||
height: #{$scroll-bar-height};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgb(234, 236, 239);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgb(189, 189, 189);
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgb(133, 133, 133);
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--c-brand: #{$primary-color};
|
||||
--c-brand-light: #{$accent-color};
|
||||
--content-width: #{$content-width};
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: #{$scroll-bar-width};
|
||||
height: #{$scroll-bar-height};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgb(41, 46, 53);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgb(65, 72, 83);
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgb(56, 62, 72);
|
||||
border-radius: #{$scroll-bar-border-radius};
|
||||
}
|
||||
}
|
33
docs-source/src/en/about/about.md
Normal file
33
docs-source/src/en/about/about.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# About this document
|
||||
|
||||
> This document is powered by [VuePress](https://v2.vuepress.vuejs.org/en).
|
||||
|
||||
## License
|
||||
|
||||
[The MIT License (MIT)](https://github.com/fankes/YukiHookAPI/blob/master/LICENSE)
|
||||
|
||||
```:no-line-numbers
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2019-2022 HighCapable
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
Copyright © 2019-2022 HighCapable
|
280
docs-source/src/en/about/changelog.md
Normal file
280
docs-source/src/en/about/changelog.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# Changelog
|
||||
|
||||
> The version update history of `YukiHookAPI` is recorded here.
|
||||
|
||||
::: danger
|
||||
|
||||
We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance.
|
||||
|
||||
:::
|
||||
|
||||
::: warning
|
||||
|
||||
To avoid translation time consumption, Changelog will use **Google Translation** from **Chinese** to **English**, please refer to the original text for actual reference.
|
||||
|
||||
Time zone of version release date: **UTC+8**
|
||||
|
||||
:::
|
||||
|
||||
### 1.0.92 | 2022.05.31  <Badge type="tip" text="latest" vertical="middle" />
|
||||
|
||||
- Fixed the naming method of callback in a large number of methods
|
||||
- Changed the solution to fix the problem that `YukiHookDataChannel` cannot call back the current `Activity` broadcast on devices lower than **Android 12**
|
||||
- The `InjectYukiHookWithXposed` annotation adds the `isUsingResourcesHook` function, now you can selectively disable the dependency interface that automatically generates `IXposedHookInitPackageResources`
|
||||
|
||||
### 1.0.91 | 2022.05.29  <Badge type="warning" text="stale" vertical="middle" />
|
||||
|
||||
- Fixed the `ClassLoader` error when the customized system of some devices is booted in the LSPosed environment, thanks to [Luckyzyx](https://github.com/luckyzyx) for the feedback
|
||||
- Fixed `YukiHookDataChannel` not being able to call back the current `Activity` broadcast on **ZUI** and systems below **Android 12**
|
||||
- Integrate the `YukiHookModuleStatus` function into `YukiHookAPI.Status`, rewrite a lot of methods, now you can judge the status information such as module activation in the module and the host in both directions
|
||||
|
||||
### 1.0.90 | 2022.05.27  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed `YukiHookDataChannel` crashing when the module sets the listener callback
|
||||
- Fixed `YukiHookDataChannel` still calling back when not in current `Activity`
|
||||
- Remove the default value of `YukiHookDataChannel` callback event, no callback
|
||||
- Removed `YukiHookModulePrefs` warning printed if XShare is unreadable
|
||||
- Added the `isXSharePrefsReadable` method in `YukiHookModulePrefs` to determine whether the current XShare is available
|
||||
|
||||
### 1.0.89 | 2022.05.26  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed the problem that `YukiHookDataChannel` cannot be repeatedly set to monitor, and added the function of repeating response in different `Activity` modules and automatically following `Activity` to destroy the monitor function
|
||||
- Added `YukiHookDataChannel` repeated listening use case description document
|
||||
- Add the `onAlreadyHooked` method to determine whether the current method is repeated Hook
|
||||
- Modify part of the logic of repeatedly adding HashMap, remove the `putIfAbsent` method, allow to override the addition
|
||||
- Fixed several possible bugs
|
||||
|
||||
### 1.0.88 | 2022.05.25  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fully decoupled from Xposed API
|
||||
- Added `android` type in `type`
|
||||
- Separate `YukiHookModuleStatus` from auto-generated code and add `isEnableHookModuleStatus` switch, it is up to you to enable or not
|
||||
- Internal closure processing for the constructors of a large number of classes in the API
|
||||
- Set `YukiHookModulePrefs` to run as a singleton to prevent repeated creation and waste of system resources
|
||||
- Fix the bug that Hook cannot be nested since version `1.0.80`, and optimize the related functions of nested Hook
|
||||
- Modify the Hooker storage scheme from HashSet to HashMap to prevent the problem of repeatedly adding Hookers
|
||||
- Modify the core implementation method of Hook, add duplicate checking to avoid repeating the Hook multiple callbacks to the `HookParam` method
|
||||
- `MethodFinder` and `FieldFinder` add the function of finding fuzzy methods and variable names, you can call `name { ... }` to set search conditions, and support regular expressions
|
||||
- Optimize and modify the way to get `appContext` to reduce the possibility of getting empty
|
||||
- Modify the print `TAG` of `logger` in the automatically generated code to default to your custom name, which is convenient for debugging
|
||||
- Optimize the `Hooker` implementation of `YukiHookBridge` to improve Hook performance
|
||||
- `PackageParam` adds the `onAppLifecycle` method, which can natively monitor the life cycle of the host and implement the registration system broadcast function
|
||||
- Added `YukiHookDataChannel` function to communicate using system out-of-order broadcast while the module and the host remain alive
|
||||
- `YukiHookDataChannel` adds the `checkingVersionEquals` method, which can be monitored to verify that the host has not updated the version mismatch problem after the module is updated
|
||||
- Added Java version example in the example code of `demo-module` for reference only
|
||||
|
||||
### 1.0.87 | 2022.05.10  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Added `refreshModuleAppResources` function to adapt Resources refresh when the language region, font size, resolution changes, etc.
|
||||
- Added `isEnableModuleAppResourcesCache` function, you can set whether to automatically cache the resources of the current module
|
||||
|
||||
### 1.0.86 | 2022.05.06  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed the problem of continuous error reporting during `initZygote` when Resources Hook is not supported, reproduced in **ZUI**/**LSPosed CI(1.8.3-6550)**
|
||||
- Optimize and handle exceptions for Resources Hook, only print errors and warnings if they are used and not supported
|
||||
|
||||
### 1.0.85 | 2022.05.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed a serious problem of not being able to hook the system framework, since `1.0.80`
|
||||
- Added in the debug log to distinguish the package name loaded by `initZygote` as `android-zygote`, `packageName` keeps `android` unchanged
|
||||
|
||||
### 1.0.83 | 2022.05.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed `YukiHookModuleStatus` reporting a lot of errors after `loadSystem`
|
||||
- Added `android` type in `type`
|
||||
- Updated example descriptions in help documentation
|
||||
|
||||
### 1.0.82 | 2022.05.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed a concept confusion error, distinguishing the relationship between `initZygote` and the system framework, there are problems with the previous comments and documentation, I am very sorry
|
||||
- `PackageParam` adds `loadSystem` method, no need to write `loadApp(name = "android")` to hook the system framework
|
||||
|
||||
### 1.0.81 | 2022.05.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fix the problem that the method and constructor that cannot be found in the Hook method body still output the error log after setting the condition using the `by` method
|
||||
- Added a global log to display the package name of the current Hook APP during the execution of the Hook, and fixed a problem with the printing style of the error log
|
||||
|
||||
### 1.0.80 | 2022.05.01  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- The `InjectYukiHookWithXposed` annotation adds the `entryClassName` function, which can customize the generated `xposed_init` entry class name
|
||||
- ~~`YukiHookXposedInitProxy`~~ renamed to `IYukiHookXposedInit`, the original interface name has been invalidated and will be deleted directly in subsequent versions
|
||||
- Added `initZygote` and Resources Hook functions to support Hook Layout
|
||||
- Added `onXposedEvent` method to listen to all events of native Xposed API
|
||||
- Perform `inline` processing on the `lambda` of the Hook function to avoid generating excessively broken anonymous classes and improve the running performance after compilation
|
||||
- Fix `PrefsData` compiled method body copy is too large
|
||||
- Added `XSharePreference` readability test, which will automatically print a warning log if it fails
|
||||
- `PackageParam` adds `appResources`, `moduleAppResources`, `moduleAppFilePath` functions
|
||||
- `loadApp` of `PackageParam` adds the function of not writing `name`, and all APPs are filtered by default
|
||||
- `PackageParam` adds the `loadZygote` method, which can directly hook the system framework
|
||||
- `PackageParam` added `resources().hook` function
|
||||
- Optimization method, construction method, variable search function, the error log that cannot be found will display the set query conditions first
|
||||
- Added `hasExtends` extension method to determine whether the current `Class` has an inheritance relationship
|
||||
- Added `isSupportResourcesHook` function to determine whether resource hooks are currently supported (Resources Hook)
|
||||
- `current` function adds `superClass` method to call superclass
|
||||
- New `superClass` query conditions for search methods, construction methods and variables, you can continue to search in the parent class
|
||||
- `YukiHookAPI` lots of methods are decoupled from Xposed API
|
||||
- Added native Hook priority function of Xposed API
|
||||
- Fix the problem that `isFirstApplication` may be inaccurate
|
||||
- Block the problem that MiuiCatcherPatch repeatedly calls the Hook entry method on the MIUI system
|
||||
- Optimize Hook entry calling method to avoid multiple calls due to Hook Framework issues
|
||||
- Fix the problem that Hook `ClassLoader` causes Hook to freeze, thanks to [WankkoRee](https://github.com/WankkoRee) for the feedback
|
||||
- Improve the performance after the `XC_Callback` interface is connected
|
||||
- Java `type` added `ClassLoader` type
|
||||
- Optimize the API help documentation, fix the problem that the page may be continuously cached
|
||||
|
||||
### 1.0.78 | 2022.04.18  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- `YukiHookModulePrefs` adds `isRunInNewXShareMode` method, which can be used to determine whether the module is currently in `New XSharePreference` mode
|
||||
- Fixed `YukiHookModulePrefs` working in `New XSharePreference` mode
|
||||
- Added `ModulePreferenceFragment`, now you can completely replace `PreferenceFragmentCompat` and start using the new functionality
|
||||
- Adapt the Sp data storage solution of `PreferenceFragmentCompat`, thanks to [mahoshojoHCG](https://github.com/mahoshojoHCG) for feedback
|
||||
- Update autohandlers and `Kotlin` dependencies to the latest version
|
||||
- Fixed some bugs in documentation and code comments
|
||||
|
||||
### 1.0.77 | 2022.04.15  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- `YukiHookModulePrefs` added `clear` method, thanks to [WankkoRee](https://github.com/WankkoRee) for the suggestion
|
||||
- `YukiHookModulePrefs` added `getStringSet`, `putStringSet`, `all` methods
|
||||
- Added `any` method to `args` of `HookParam`
|
||||
- Added `ModuleApplication`, which can be inherited in modules to achieve more functions
|
||||
- Connect all `findClass` functions to the Xposed API, and continue to use native `ClassLoader` in non-hosted environments
|
||||
- Fixed some possible bugs
|
||||
|
||||
### 1.0.75 | 2022.04.13  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Corrected the logic recognition part of the automatic handler, thanks to [ApeaSuperz](https://github.com/ApeaSuperz) contribution
|
||||
- Fixed an issue where the reference to a doc comment was not changed
|
||||
- `firstArgs` and `lastArgs` methods have been removed from `HookParam`, now you can use `args().first()` and `args().last()` instead of it
|
||||
- Removed default parameter `index = 0` in `args()` in `HookParam`, now you can use `args().first()` or `args(index = 0)` to replace it
|
||||
- The `result` function in `HookParam` adds generic matching, now you can use `result<T>` to match the known return value type of your target method
|
||||
- The `emptyParam` condition is added to the method and constructor query function, and the misunderstanding of the query condition that needs to be paid attention to in the document has been improved
|
||||
- Added `android` type in `type`
|
||||
|
||||
### 1.0.73 | 2022.04.10  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed some Chinese translation errors in documents, thanks to [WankkoRee](https://github.com/WankkoRee) for their contributions
|
||||
- Fix the problem that `XC_LoadPackage.LoadPackageParam` throws an exception when the content is empty in some cases, thanks to [Luckyzyx](https://github.com/luckyzyx) for the feedback
|
||||
- Fix some known bugs and improve Hook stability
|
||||
|
||||
### 1.0.72 | 2022.04.09  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Update API documentation to new address
|
||||
- Add `appContext` function to `PackageParam`
|
||||
- Fix some known bugs and improve Hook stability
|
||||
|
||||
### 1.0.71 | 2022.04.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed a serious issue that would stop the Hook from throwing an exception when VariousClass could not be matched
|
||||
|
||||
### 1.0.70 | 2022.04.04  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed `instanceClass` reporting an error after being called in a static instance
|
||||
- Add `isUseAppClassLoader` function in Hook process, thanks to [WankkoRee](https://github.com/WankkoRee) for feedback
|
||||
- Added the `withProcess` function, which can be hooked according to the currently specified process of the APP
|
||||
- Fixed critical logic errors in lookup methods, constructor classes and variables
|
||||
- Fixed the problem that the abnormal output cannot be ignored when the Hook target class does not exist
|
||||
- Fixed the problem that the Hook could not take effect due to the fast loading of the APP startup method in some cases
|
||||
- Fixed `allMethods` not throwing an exception when it is not hooked to a method, thanks to [WankkoRee](https://github.com/WankkoRee) for the feedback
|
||||
- Added Hook status monitoring function, thanks to [WankkoRee](https://github.com/WankkoRee) for the suggestion
|
||||
- Modify the way the Xposed entry is injected into the class, and redefine the definition domain of the API
|
||||
- Added obfuscated method and variable lookup function, you can use different types of filter `index` to locate the specified method and variable, thanks to [WankkoRee](https://github.com/WankkoRee) for the ideas provided
|
||||
- When looking for methods and variables, multiple types are allowed, such as the class name declared by `String` and `VariousClass`
|
||||
- Add a new `current` function, which can build a reflection method operation space for any class, and easily call and modify the methods and variables in it
|
||||
- Fixed a lot of bugs in the hook process, thanks to [WankkoRee](https://github.com/WankkoRee) for contributing to this project
|
||||
|
||||
### 1.0.69 | 2022.03.30  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Added and improved annotations for some method functions
|
||||
- Added more example Hook content in Demo
|
||||
- Fixed the issue that only the last one takes effect when `allMethods` is used multiple times in a Hook instance, thanks to [WankkoRee](https://github.com/WankkoRee) for the feedback
|
||||
|
||||
### 1.0.68 | 2022.03.29  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Added new use case and LSPosed scope in Demo
|
||||
- Added `Member` lookup cache and lookup cache configuration switches
|
||||
- Removed and modified `MethodFinder`, `FieldFinder` and `HookParam` related method calls
|
||||
- Add more `cast` types in `Finder` and support `cast` as array
|
||||
- Overall performance and stability improvements
|
||||
- Fix bugs that may exist in the previous version
|
||||
|
||||
### 1.0.67 | 2022.03.27  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Added three `modifiers` functions in `Finder`, which can filter `static`, `native`, `public`, `abstract` and many other description types
|
||||
- When searching for methods and constructors, the method parameter type can be blurred to a specified number for searching
|
||||
- Added `hasModifiers` extension for `Member`
|
||||
- Added `give` method in `MethodFinder` and `ConstructorFinder` to get primitive types
|
||||
- Added `PrefsData` template function in `YukiHookModulePrefs`
|
||||
- Completely refactored method, constructor and variable lookup scheme
|
||||
- Optimized code comments and fixed possible bugs
|
||||
|
||||
### 1.0.66 | 2022.03.25  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed a serious bug in `MethodFinder`
|
||||
- Added `args` call method in `hookParam`
|
||||
- Fix other possible problems and fix some class annotation problems
|
||||
|
||||
### 1.0.65 | 2022.03.25  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Republished version to fix the incorrect new version of the Maven repository due to cache issues
|
||||
- Added `MethodFinder` and `FieldFinder` new return value calling methods
|
||||
- Fix possible problems and fix possible problems during the use of Tai Chi
|
||||
- Fixed possible problems with auto-generated Xposed entry classes
|
||||
- Added `android` type and `java` type in `type`
|
||||
|
||||
### 1.0.6 | 2022.03.20  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed `YukiHookModulePrefs` being ignored every time after using `direct` once to ignore cache
|
||||
- Added new API, abolished the traditional usage of `isActive` to judge module activation
|
||||
- Fixed the issue of printing debug logs when using the API in a non-Xposed environment
|
||||
- Fixed log output issue and unintercepted exception issue when looking for `Field`
|
||||
- Decoupling Xposed API in `ReflectionUtils`
|
||||
- Added `YukiHookModuleStatus` method name confusion to reduce the size of module generation
|
||||
- The welcome message will no longer be printed when loading the module's own Hook
|
||||
- Fix some bugs that still exist in the previous version
|
||||
|
||||
### 1.0.55 | 2022.03.18  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed an annotation error
|
||||
- Temporarily fix a bug
|
||||
- Added a large number of `android` types in `type` and a small number of `java` types
|
||||
- Fix compatibility issues between new and old Kotlin APIs
|
||||
|
||||
### 1.0.5 | 2022.03.18  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed the problem that the welcome message was printed multiple times in the case of the old version of the LSPosed framework
|
||||
- Added `onInit` method to configure `YukiHookAPI`
|
||||
- Added `executorName` and `executorVersion` to get the name and version number of the current hook framework
|
||||
- Added `by` method to set the timing and condition of Hook
|
||||
- `YukiHookModulePrefs` adds a controllable key-value cache, which can dynamically update data when the host is running
|
||||
- Fixed some possible bugs
|
||||
|
||||
### 1.0.4 | 2022.03.06  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fix LSPosed cannot find `XposedBridge` after enabling "Only module classloader can use Xposed API" option in latest version
|
||||
- Added constant version name and version number for `YukiHookAPI`
|
||||
- Added `hasField` method and `isAllowPrintingLogs` configuration parameter
|
||||
- Added `isDebug` to enable the API to automatically print the welcome message to test whether the module is valid
|
||||
|
||||
### 1.0.3 | 2022.03.02  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fixed a potential exception not intercepted BUG
|
||||
- Added `ignoredError` function
|
||||
- Added `android` type in `type`
|
||||
- Added `ClassNotFound` function after listening to `hook`
|
||||
|
||||
### 1.0.2 | 2022.02.18  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- Fix the problem that the project path cannot be found under Windows
|
||||
- Remove part of reflection API, merge into `BaseFinder` for integration
|
||||
- Add a method to create Hook directly using string
|
||||
|
||||
### 1.0.1 | 2022.02.15  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- `RemedyPlan` adds `onFind` function
|
||||
- Integrate and modify some reflection API code
|
||||
- Added `java` type in `type`
|
||||
- Fixed the issue that ignored errors still output in the console
|
||||
|
||||
### 1.0 | 2022.02.14  <Badge type="danger" text="outdate" vertical="middle" />
|
||||
|
||||
- The first version is submitted to Maven
|
13
docs-source/src/en/about/contacts.md
Normal file
13
docs-source/src/en/about/contacts.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Contact Us
|
||||
|
||||
> If you have any questions in use, or have any constructive suggestions, you can contact us.
|
||||
|
||||
Join us [Click to join Telegram group](https://t.me/YukiHookAPI)
|
||||
|
||||
Find me on **Twitter** [@fankesyooni](https://twitter.com/fankesyooni)
|
||||
|
||||
## Help with maintenance
|
||||
|
||||
Thank you for choosing and using `YukiHookAPI`.
|
||||
|
||||
If you have code-related suggestions and requests, you can submit a Pull Request on Github.
|
43
docs-source/src/en/about/future.md
Normal file
43
docs-source/src/en/about/future.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Looking for future
|
||||
|
||||
> The future is bright and uncertain, let us look forward to the future development space of `YukiHookAPI`.
|
||||
|
||||
## Unresolved Issues
|
||||
|
||||
> Here are the unresolved issues with `YukiHookAPI`.
|
||||
|
||||
### YukiHookModulePrefs
|
||||
|
||||
Currently only supports LSPosed perfectly, other Xposed Framework need to downgrade the module target api.
|
||||
|
||||
TaiChi may not be supported at all, and TaiChi needs a lower target api to adapt on high-version systems.
|
||||
|
||||
Some Xposed Module developers currently choose the Hook target app self's SharedPreferences storage solution to solve the module settings sharing problem.
|
||||
|
||||
In the later period, the permissions of the Android system will become more and more strict, and `selinux` is a big problem currently facing, which needs to be discussed and studied.
|
||||
|
||||
## Future Plans
|
||||
|
||||
> Features that `YukiHookAPI` may add later are included here.
|
||||
|
||||
### Lite version supported for standalone use
|
||||
|
||||
::: tip To be discussed
|
||||
|
||||
At present, the API only supports binding to **xposed_init** through the automatic handler.
|
||||
|
||||
If you don't like the automatic handler, you must implement the module loading entry yourself.
|
||||
|
||||
In the future, the Lite version with only API functions will be launched according to the number of people required.
|
||||
|
||||
You can submit **issues** with us.
|
||||
|
||||
:::
|
||||
|
||||
We have provided the Xposed native API listening interface, you can find or view the implementation method of the Demo [here](../config/xposed-using#native-xposed-api-event).
|
||||
|
||||
### Support for more Hook Framework
|
||||
|
||||
As an API, currently only docking `XposedBridge` as a compatibility layer still has certain limitations.
|
||||
|
||||
Most `inline hook` do not have a `Java` compatibility layer, and the `Java` compatibility layer adaptation of `native hook` may be considered later.
|
55
docs-source/src/en/api/home.md
Normal file
55
docs-source/src/en/api/home.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
next:
|
||||
text: Public API
|
||||
link: /en/api/public/com/highcapable/yukihookapi/YukiHookAPI
|
||||
---
|
||||
|
||||
# Document Introduce
|
||||
|
||||
> The document here will synchronize the relevant usage of the latest API version, please keep `YukiHookAPI` as the latest version to use the latest version of the function.
|
||||
|
||||
## Function Description
|
||||
|
||||
> The function description mainly introduces the related usage and purpose of the current API.
|
||||
|
||||
## Function Example Description
|
||||
|
||||
> The function examples mainly show the basic usage examples of the current API for reference.
|
||||
|
||||
## Change Record Description
|
||||
|
||||
The function of the first version will be marked as `v<version>` `first`;
|
||||
|
||||
New function added later will be marked as `v<version>` `added`;
|
||||
|
||||
Later modified function will be appended as `v<version>` `modified`;
|
||||
|
||||
Later deprecated function will be marked as `v<version>` `deprecated` and strikethrough;
|
||||
|
||||
Later removed function will be marked as `v<version>` `removed` and strikethrough.
|
||||
|
||||
## Related Symbols Description
|
||||
|
||||
- *kt* Kotlin Static File
|
||||
|
||||
- *annotation* Annotation Class
|
||||
|
||||
- *interface* Interface Class
|
||||
|
||||
- *object* Class (Singleton)
|
||||
|
||||
- *class* Class
|
||||
|
||||
- *field* Field or `get` / `set` method or read-only `get` method
|
||||
|
||||
- *method* Method
|
||||
|
||||
- *enum* Enum constant
|
||||
|
||||
- *ext-field* Extension field (global)
|
||||
|
||||
- *ext-method* Extension method (global)
|
||||
|
||||
- *i-ext-field* Extension field (internal)
|
||||
|
||||
- *i-ext-method* Extension method (internal)
|
9
docs-source/src/en/api/special-features/host-inject.md
Normal file
9
docs-source/src/en/api/special-features/host-inject.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Host Resource Injection Extension *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
@@ -0,0 +1,9 @@
|
||||
# Host Lifecycle Extension *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/api/special-features/logger.md
Normal file
9
docs-source/src/en/api/special-features/logger.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Debug Logger *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/api/special-features/reflection.md
Normal file
9
docs-source/src/en/api/special-features/reflection.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Reflection Extensions *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
@@ -0,0 +1,9 @@
|
||||
# Xposed Module and Host Channel *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/api/special-features/xposed-prefs.md
Normal file
9
docs-source/src/en/api/special-features/xposed-prefs.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Xposed Module Data Storage *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/config/api-example.md
Normal file
9
docs-source/src/en/config/api-example.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# API Basic Configs *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/config/api-exception.md
Normal file
9
docs-source/src/en/config/api-exception.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# API Exception Handling *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/config/api-using.md
Normal file
9
docs-source/src/en/config/api-using.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Use as Hook API Configs *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
27
docs-source/src/en/config/r8-proguard.md
Normal file
27
docs-source/src/en/config/r8-proguard.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# R8 & Proguard Obfuscate
|
||||
|
||||
> In most scenarios, the Xposed Module can be compressed by native obfuscation.
|
||||
>
|
||||
> Here is the configuration method of obfuscation.
|
||||
|
||||
## R8
|
||||
|
||||
> If you are using `R8` then you don't need any special configuration for `YukiHookAPI`.
|
||||
|
||||
## Proguard
|
||||
|
||||
> ~~If you are still using `Proguard`, you need to do some rule configuration.~~
|
||||
|
||||
::: danger
|
||||
|
||||
Proguard rules have been deprecated, please don't use them anymore.
|
||||
|
||||
Since Android Gradle Plugin 4.2, the obfuscator with the latest version of the Android Jetpack default is **R8**, and you no longer need to consider obfuscation.
|
||||
|
||||
:::
|
||||
|
||||
To enable `R8` in any version, please add the following rules to the `gradle.properties` file, no configuration is required for Android Gradle Plugin 7.0 and above.
|
||||
|
||||
```groovy
|
||||
android.enableR8=true
|
||||
```
|
9
docs-source/src/en/config/xposed-using.md
Normal file
9
docs-source/src/en/config/xposed-using.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Use as Xposed Module Configs *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
9
docs-source/src/en/guide/example.md
Normal file
9
docs-source/src/en/guide/example.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Usage Example *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
186
docs-source/src/en/guide/home.md
Normal file
186
docs-source/src/en/guide/home.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# Introduce
|
||||
|
||||
> This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API.
|
||||
|
||||
## Background
|
||||
|
||||
This is an efficient Xposed Hook API rebuilt in `Kotlin`.
|
||||
|
||||
The name is taken from ["ももくり" heroine Yuki Kurihara](https://www.bilibili.com/bangumi/play/ss5016).
|
||||
|
||||
Formerly the Innocent Xposed API used in [Development Learning Project](https://github.com/fankes/TMore), now renamed and open sourced.
|
||||
|
||||
## Usage
|
||||
|
||||
`YukiHookAPI` is built entirely with `Kotlin` `lambda` syntax.
|
||||
|
||||
Abandoning the original less friendly `XposedHelpers`, you can use it to easily create Xposed Modules and easily implement custom Hook API.
|
||||
|
||||
## Language Requirement
|
||||
|
||||
Please use `Kotlin`, the framework part of the code composition is also compatible with `Java` but the implementation of the basic Hook scene **may not work at all**.
|
||||
|
||||
All demo code in this document will be described using `Kotlin`, if you don't know how to use `Kotlin` then you may not be able to use `YukiHookAPI`.
|
||||
|
||||
Part of the Java Demo code can be found [here](https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java), but not recommended.
|
||||
|
||||
## Source of Inspiration
|
||||
|
||||
Previously, when we built an Xposed Module, we first needed to create an `xposed_init` file under `assets`.
|
||||
|
||||
Then, manually fill in your own entry class name into the file and use `XposedHelpers` to implement our Hook logic.
|
||||
|
||||
Since `Kotlin` is the main Android development language, this API is really not very elegant to use.
|
||||
|
||||
Is there any **easy to use, light, elegant** solution?
|
||||
|
||||
With this idea, `YukiHookAPI` was born.
|
||||
|
||||
Now, we only need to write a small amount of code, and all the time and expense are handed over to automation.
|
||||
|
||||
With `Kotlin`'s elegant `lambda` writing and `YukiHookAPI`, you can make your Hook logic more beautiful and clear.
|
||||
|
||||
> The following example
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "sym_def_app_icon"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||
XResources.setSystemWideReplacement(
|
||||
"android", "mipmap", "sym_def_app_icon",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity::class.java.name,
|
||||
null, "onCreate",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
if (lpparam.packageName == "com.android.browser")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity::class.java.name,
|
||||
lpparam.classLoader, "onCreate",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
if (resparam.packageName == "com.android.browser")
|
||||
resparam.res.setReplacement(
|
||||
"com.android.browser", "mipmap", "ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
Yes, you read that right, just needing these codes can completely replace the Xposed API to achieve the same function.
|
||||
|
||||
Now, with the help of the efficient and powerful `YukiHookAPI`, you can implement a very simple Xposed Module.
|
||||
|
||||
## Suppored Hook Framework
|
||||
|
||||
The following are the `Hook Framework` and Xposed framework supported by `YukiHookAPI`.
|
||||
|
||||
| Hook Framework | ST | Description |
|
||||
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
|
||||
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | Stable use in multiple scenarios |
|
||||
| [LSPatch](https://github.com/LSPosed/LSPatch) | ⭕ | WIP after this project is improved |
|
||||
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ❎ | Maintenance has stopped, no longer recommended |
|
||||
| [Pine](https://github.com/canyie/pine) | ⭕ | Only available |
|
||||
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | Only available |
|
||||
| [Whale](https://github.com/asLody/whale) | ⭕ | Need [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
|
||||
| [YAHFA](https://github.com/PAGalaxyLab/YAHFA) | ❗ | Need to implement the Xposed API yourself |
|
||||
| [FastHook](https://github.com/turing-technician/FastHook) | ❗ | Need to implement the Xposed API yourself |
|
||||
| [Epic](https://github.com/tiann/epic) | ❗ | Need [Dexposed](https://github.com/alibaba/dexposed) by yourself |
|
||||
| [TaiChi](https://github.com/taichi-framework/TaiChi) | ⭕ | Only available for Xposed Module |
|
||||
| [Xposed](https://github.com/rovo89/Xposed) | ❎ | Not test, no longer recommended |
|
89
docs-source/src/en/guide/knowledge.md
Normal file
89
docs-source/src/en/guide/knowledge.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Basic Knowledge
|
||||
|
||||
> Here is a collection of Xposed-related introductions and the key points of knowledge that need to be grasped before start.
|
||||
>
|
||||
> Anyone who already knows can skip it.
|
||||
|
||||
The basic knowledge content <u>**not necessarily completely accurate**</u>, please read it according to your own opinion.
|
||||
|
||||
If you find **any errors in this page, please correct it and help us improve**.
|
||||
|
||||
## Related Introduction
|
||||
|
||||
> Here's an introduction to Xposed and how Hooks work.
|
||||
|
||||
### What is Xposed
|
||||
|
||||
> Xposed Framework (Xposed Framework) is a set of open source framework services that run in Android high-privilege mode. It can affect program operation (modify the system) without modifying the APK file. Based on it, many Powerful modules that operate simultaneously without conflicting functions.
|
||||
|
||||
The above content is copied from Baidu Encyclopedia.
|
||||
|
||||
### What can Xposed do
|
||||
|
||||
> The structure below describes the basic workings and principles of Xposed.
|
||||
|
||||
```:no-line-numbers
|
||||
Xposed Framework
|
||||
└── App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
We can achieve the ultimate goal of controlling its behavior by injecting the **Host (App)** when the **Host (App)** is running.
|
||||
|
||||
This mode of operation of Xposed is called **parasitism**. The Xposed Module follows the lifecycle of the host and completes its own life course within the lifecycle of the **Host**.
|
||||
|
||||
We can call the **Host**'s methods, fields, and constructors through reflection, and use the Hook operation provided by `XposedBridge` to dynamically insert our own code before and after the method to be executed by the **Host (App)**, or completely replace the target, or even intercept.
|
||||
|
||||
### Development Process
|
||||
|
||||
Today's Xposed Manager has been completely replaced by its derivative works, and the era of **SuperSU** has ended, and now, with **Magisk**, everything behind is possible again.
|
||||
|
||||
> Its development history can be roughly divided into **Xposed(Dalvik)** → **Xposed(ART)** → **Xposed(Magisk)** → **EdXposed(Riru)**/**LSPosed(Riru/ Zygisk)**
|
||||
|
||||
### Derivatives
|
||||
|
||||
> The structure below describes how and how the Xposed-like Hook Framework works.
|
||||
|
||||
```:no-line-numbers
|
||||
App's Environment
|
||||
└── Hook Framework
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
```
|
||||
|
||||
Through the operation principle of Xposed, many frameworks of the same type have been derived. As mobile devices in today's era are more and more difficult to obtain Root permissions or even flash, and when they are not just needed, some Root-free frameworks are also produced, such as **Tai Chi**.
|
||||
|
||||
These Hook Frameworks at the ART level can also complete the Hook process with the same principle as Xposed without using the Xposed API. The operating principle of Root-free is to modify the APK and inject the Hook process into the **Host**, and control it through external modules.
|
||||
|
||||
Another product is to use the existing functions of the Android operating environment to virtualize an environment that is completely the same as the current device system, and run App in it. This is the virtual App technology **VirtualApp**, which was later derived as **VirtualXposed** .
|
||||
|
||||
The Root-free frameworks mentioned above are **Tai Chi/Wuji**, **VirtualXposed/SandVXposed**.
|
||||
|
||||
### What YukiHookAPI does
|
||||
|
||||
Since Xposed appeared until now, apart from `XposedHelpers`, which is well known to developers, there is still no set of syntactic sugar for `Kotlin` and API with complete usage encapsulation.
|
||||
|
||||
The birth of this API framework is to hope that in the current era of Xposed, more capable Xposed Module developers can avoid detours and complete the entire development process more easily and simply.
|
||||
|
||||
In the future, `YukiHookAPI` will adapt to more third-party Hook Frameworks based on the goal of using the Xposed API, so as to improve the entire ecosystem and help more developers make Xposed Module development simpler and easier to understand.
|
||||
|
||||
## Let's Started
|
||||
|
||||
Before starting, you need to have the following basics to better use `YukiHookAPI`.
|
||||
|
||||
- Grasp and understand Android development and simple system operation principles
|
||||
|
||||
- To grasp and understand the internal structure of Android APK and simple decompilation knowledge, you can refer to [Jadx](https://github.com/skylot/jadx) and [ApkTool](https://github.com/iBotPeaches/Apktool)
|
||||
|
||||
- Grasp and proficient in using Java reflection, understand simple Smali syntax, understand Dex file structure, and use reverse analysis to locate method locations
|
||||
|
||||
- Grasp the basic native [Xposed API](https://api.xposed.info) usage, understand the operation principle of Xposed
|
||||
|
||||
- Grasp Kotlin language and learn to use **Kotlin lambda**
|
||||
|
||||
- Grasp and understand Kotlin and Java mixing, calling each other, and Java bytecode generated by Kotlin
|
259
docs-source/src/en/guide/move-to-new-api.md
Normal file
259
docs-source/src/en/guide/move-to-new-api.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Migrate from Xposed API
|
||||
|
||||
> If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to `YukiHookAPI`.
|
||||
|
||||
## Migrate Hook Entry Point
|
||||
|
||||
> Migrated from `XC_LoadPackage.LoadPackageParam` to `PackageParam`.
|
||||
|
||||
`YukiHookAPI` implements the `lambda` method body `this` usage for `PackageParam`, and the `PackageParam` object can be obtained globally in the `encase` method body.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
override fun onHook() = encase {
|
||||
// Get the package name of the current Hook
|
||||
packageName
|
||||
// Get the ApplicationInfo of the current Hook
|
||||
appInfo
|
||||
// Get the system context object
|
||||
systemContext
|
||||
// Get the host Application lifecycle
|
||||
appContext
|
||||
// Hook specified app
|
||||
loadApp(name = "com.demo.test") {
|
||||
// Class Hook
|
||||
findClass("com.demo.test.TestClass").hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(BooleanType)
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (fixed usage)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
// Get the package name of the current Hook
|
||||
lpparam.packageName
|
||||
// Get the ApplicationInfo of the current Hook
|
||||
lpparam.applicationInfo
|
||||
// Get the system context object
|
||||
// There is no ready-made calling method in the native Xposed API, you need to reflect ActivityThread to achieve it
|
||||
// Get the host Application lifecycle
|
||||
AndroidAppHelper.currentApplication()
|
||||
// Class Hook
|
||||
if(lpparam.packageName == "com.demo.test")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.demo.test.TestClass", lpparam.classLoader,
|
||||
"test", Boolean::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
// Get the package name of the current Hook
|
||||
resparam.packageName
|
||||
// Resources Hook
|
||||
resparam.res.setReplacement(
|
||||
"com.demo.test", "mipmap", "ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Migrate Hook Method Body
|
||||
|
||||
> Migrated from `XC_MethodHook.MethodHookParam` to `HookParam`.
|
||||
|
||||
### Before/After Hook
|
||||
|
||||
`YukiHookAPI` also implements the `lambda` method body `this` usage for `HookParam`, and the `HookParam` object can be obtained globally in the method bodies such as `beforeHook` and `afterHook`.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
afterHook {
|
||||
// Get the current Hook instance
|
||||
instance
|
||||
// Get the Class instance of the current Hook
|
||||
instanceClass
|
||||
// Get and cast the current Hook instance to the specified type T
|
||||
instance<T>()
|
||||
// Get the method parameter array
|
||||
args
|
||||
// Get the first T of the method parameter
|
||||
args().first().cast<T>()
|
||||
// Get the last bit of the method parameter T
|
||||
args().last().cast<T>()
|
||||
// Get any subscript T of the method parameter, here is an example of 2
|
||||
args(index = 2).cast<T>()
|
||||
// Set any subscript of the method parameter, here is an example of 2
|
||||
args(index = 2).set(...)
|
||||
// Get the return value
|
||||
result
|
||||
// Get the return value and cast to T
|
||||
result<T>()
|
||||
// Modify the content of the return value
|
||||
result = ...
|
||||
// Remove the content of the return value
|
||||
resultNull()
|
||||
// Throw an exception to the Hook app
|
||||
Throwable("Fatal").throwToApp()
|
||||
// Execute the original method without hook and call with the original method parameters, generics can be omitted
|
||||
callOriginal<Any?>()
|
||||
// Execute the original method without Hook and customize the method parameter call, the generic type can be omitted
|
||||
invokeOriginal<Any?>(...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// Get the current Hook instance
|
||||
param.thisObject
|
||||
// Get the Class instance of the current Hook
|
||||
param.thisObject.javaClass
|
||||
// Get and cast the current Hook instance to the specified type T
|
||||
param.thisObject as T
|
||||
// Get the method parameter array
|
||||
param.args
|
||||
// Get the first T of the method parameter
|
||||
param.args[0] as T
|
||||
// Get the last bit of the method parameter T
|
||||
param.args[param.args.lastIndex] as T
|
||||
// Get any subscript T of the method parameter, here is an example of 2
|
||||
param.args[2] as T
|
||||
// Set any subscript of the method parameter, here is an example of 2
|
||||
param.args[2] = ...
|
||||
// Get the return value
|
||||
param.result
|
||||
// Get the return value and cast to T
|
||||
param.result as T
|
||||
// Modify the content of the return value
|
||||
param.result = ...
|
||||
// Remove the content of the return value
|
||||
param.result = null
|
||||
// Throw an exception to the Hook app
|
||||
param.throwable = Throwable("Fatal")
|
||||
// Execute the original method without hooking
|
||||
XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
### Replace Hook
|
||||
|
||||
The `replaceHook` method is special, and the `YukiHookAPI` makes a variety of forms for it to choose from.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
/// A method with no return value void
|
||||
|
||||
replaceUnit {
|
||||
// Implement the replaced logic directly here
|
||||
}
|
||||
|
||||
/// A method with a return value
|
||||
|
||||
replaceAny {
|
||||
// Implement the replaced logic here
|
||||
// ...
|
||||
// Need to return the return value corresponding to the method, no need to write return, just put the parameter in the last digit
|
||||
// Assuming the return value of this method is an Int, we just need to ensure that the last bit is the return value we need
|
||||
0
|
||||
}
|
||||
|
||||
/// For some methods, we just need to replace their return value, then there are the following implementations
|
||||
/// It should be noted that the parameters passed in by the method of directly replacing the return value are fixed. If you want to dynamically replace the return value, please use the above replaceAny method body
|
||||
|
||||
// Replace with the return value you need
|
||||
replaceTo(...)
|
||||
// Replace with return value of type Boolean
|
||||
replaceToTrue()
|
||||
// Intercept return value
|
||||
intercept()
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
/// A method with no return value void
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Any? {
|
||||
// Implement the replaced logic directly here
|
||||
return null
|
||||
}
|
||||
|
||||
/// A method with a return value
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Int {
|
||||
// Implement the replaced logic here
|
||||
// ...
|
||||
// Assume the return value of this method is an Int
|
||||
return 0
|
||||
}
|
||||
|
||||
/// For some methods, we just need to replace their return value, then there are the following implementations
|
||||
|
||||
// Replace with the return value you need
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = ...
|
||||
// Replace with return value of type Boolean
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = true
|
||||
// Intercept return value
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = null
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Migrate Other Features
|
||||
|
||||
`YukiHookAPI` is a complete rewrite of the Xposed API, you can refer to [API Document](../api/home) and [Special Features](../api/special-features/reflection) to determine some functional Migration and use.
|
208
docs-source/src/en/guide/quick-start.md
Normal file
208
docs-source/src/en/guide/quick-start.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Quick Start
|
||||
|
||||
> Integrate `YukiHookAPI` into your project.
|
||||
|
||||
## Environment Requirements
|
||||
|
||||
- Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian)
|
||||
|
||||
- Android Studio 2021.1 and above
|
||||
|
||||
- IntelliJ IDEA 2021.1 and above
|
||||
|
||||
- Kotlin 1.7.0 and above
|
||||
|
||||
- Android Gradle Plugin 7.0 and above
|
||||
|
||||
- Gradle 7.0 and above
|
||||
|
||||
- JVM 11 and above (Since API `1.0.80`)
|
||||
|
||||
## Automatically build the project
|
||||
|
||||
`YukiHookAPI` provides an automated build tool that can help you quickly build an Android standard project template with Xposed Module dependencies, and use the built template to start the next step directly.
|
||||
|
||||
You can [click here](../tools/yukihookapi-projectbuilder) to check it out.
|
||||
|
||||
## Manually configure the project
|
||||
|
||||
If you don't want to use automated build tools, you can still manually configure project dependencies as follows.
|
||||
|
||||
### Create Project
|
||||
|
||||
Use `Android Studio` or `IntelliJ IDEA` to create a new Android project and select `Kotlin` in the `Language` column to automatically add basic dependencies.
|
||||
|
||||
### Integration Dependencies
|
||||
|
||||
Add dependencies to your project `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// ❗If your Plugin version is too low, be sure to add it as an Xposed Module, other cases are optional
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
maven { url "https://api.xposed.info/" }
|
||||
// MavenCentral has a 2-hour cache, if you cannot integrate the latest version, please add this address
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||
}
|
||||
```
|
||||
|
||||
Add `plugin` to your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
plugins {
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
id 'com.google.devtools.ksp' version '<ksp-version>'
|
||||
}
|
||||
```
|
||||
|
||||
Add dependencies to your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
// base dependencies
|
||||
implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
|
||||
}
|
||||
```
|
||||
|
||||
Please modify **<ksp-version>** to the latest version from [here](https://github.com/google/ksp/releases) **(Please choose your current corresponding Kotlin version)**.
|
||||
|
||||
Please modify **<yuki-version>** to the latest version [here](../about/changelog).
|
||||
|
||||
::: danger
|
||||
|
||||
The **api** of **YukiHookAPI** and the versions that **ksp-xposed** depend on must correspond one by one, otherwise a version mismatch error will occur.
|
||||
|
||||
:::
|
||||
|
||||
Modify the JVM version of `Kotlin` to 11 and above in your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
android {
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
Since API **1.0.80** version, the default JVM version is 11, and 1.8 and below are no longer supported.
|
||||
|
||||
:::
|
||||
|
||||
### Use as Xposed Module
|
||||
|
||||
Add the base code to your `AndroidManifest.xml`.
|
||||
|
||||
> The following example
|
||||
|
||||
```xml
|
||||
<!-- Set as Xposed Module -->
|
||||
<meta-data
|
||||
android:name="xposedmodule"
|
||||
android:value="true" />
|
||||
|
||||
<!-- set your module description -->
|
||||
<meta-data
|
||||
android:name="xposeddescription"
|
||||
android:value="Fill in your Xposed Module description" />
|
||||
|
||||
<!-- The minimum Xposed version number, if you are using EdXposed/LSPosed, the minimum recommended is 93 -->
|
||||
<meta-data
|
||||
android:name="xposedminversion"
|
||||
android:value="93" />
|
||||
|
||||
<!-- Optional: configure support for New XSharePrefs without adjusting xposedminversion to 93 -->
|
||||
<meta-data
|
||||
android:name="xposedsharedprefs"
|
||||
android:value="true"/>
|
||||
```
|
||||
|
||||
Create a Hook entry class in your project, inherit from `IYukiHookXposedInit` and add the annotation `@InjectYukiHookWithXposed`.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = YukiHookAPI.encase {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip Suggestion
|
||||
|
||||
You can inherit **Application** of your module app from **ModuleApplication** to achieve a complete user experience.
|
||||
|
||||
For more functions, please refer to [ModuleApplication](../api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication).
|
||||
|
||||
:::
|
||||
|
||||
Then, you can start writing Hook code.
|
||||
|
||||
For configuration details related to use as an Xposed Module, you can [click here](../config/xposed-using) to continue reading.
|
||||
|
||||
If you are currently using Xposed API, you can refer to [Migrating from Xposed API](../guide/move-to-new-api).
|
||||
|
||||
### Use as Hook API
|
||||
|
||||
#### Integration
|
||||
|
||||
Create your custom `Application`.
|
||||
|
||||
::: danger
|
||||
|
||||
Regardless of the **Hook Framework** you use, you need to add its docking Xposed dependency support.
|
||||
|
||||
If the target **Hook Framework** does not integrate Xposed API, you need to implement and connect **XposedBridge** by yourself.
|
||||
|
||||
:::
|
||||
|
||||
Add `YukiHookAPI.encase` method to `attachBaseContext`.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// Load Hook Framework
|
||||
//
|
||||
// Your code here.
|
||||
//
|
||||
// Load YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can start writing Hook code in much the same way you would use it as an Xposed Module.
|
||||
|
||||
For configuration details related to use as a Hook API, you can [click here](../config/api-using) to continue reading.
|
||||
|
||||
::: warning
|
||||
|
||||
**YukiHookModuleStatus**, **YukiHookModulePrefs**, **YukiHookDataChannel** and Resources Hook functionality will not work when using a custom Hook Framework instead of the full Xposed Module.
|
||||
|
||||
:::
|
56
docs-source/src/en/index.md
Normal file
56
docs-source/src/en/index.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
home: true
|
||||
title: Home
|
||||
heroImage: /images/logo.png
|
||||
actions:
|
||||
- text: Get Started
|
||||
link: /en/guide/home
|
||||
type: primary
|
||||
- text: Changelog
|
||||
link: /en/about/changelog
|
||||
type: secondary
|
||||
features:
|
||||
- title: Xposed Module Develop
|
||||
details: The automatic builder can help you quickly create an Xposed Module, automatic configure the entry class and xposed_init file.
|
||||
- title: Light and Elegant
|
||||
details: A powerful, elegant, beautiful API built with Kotlin lambda can help you quickly implement members search and methods hooks.
|
||||
- title: Debugging Efficient
|
||||
details: A rich debug log function, detailing the name of each hooked method, time-consuming to find the class can quickly debug and find errors.
|
||||
- title: Easy to transplant
|
||||
details: Native support for Xposed API usage, in any case, the supported Hook Framework with Xposed API can be quickly spliced with it.
|
||||
- title: Obfuscate Support
|
||||
details: The built Xposed Module simply supports R8, obfuscate will not destroy the hook entry point, and no other configuration is required under R8.
|
||||
- title: Quickly Started
|
||||
details: Simple and easy to use it now! Do not need complex configuration and full development experience, Integrate dependencies and enjoy yourself.
|
||||
footer: MIT License | Copyright (C) 2019-2022 HighCapable
|
||||
---
|
||||
|
||||
### All Hook process in one step, everything is simplified
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
41
docs-source/src/en/tools/yukihookapi-projectbuilder.md
Normal file
41
docs-source/src/en/tools/yukihookapi-projectbuilder.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# YukiHookAPI Project Builder
|
||||
|
||||
> This is an automatic building tool for Xposed Modules using `YukiHookAPI` as the core.
|
||||
>
|
||||
> Implementing automated search relies on quickly building an Android project template that includes a Xposed Module environment.
|
||||
|
||||
<img src="/images/yukihookapi-projectbuilder-en.png" width = "720"/>
|
||||
|
||||
## Get Project
|
||||
|
||||
This project is open source and free, and will be maintained continuously according to your usage.
|
||||
|
||||
The original version may have imperfections or bugs. We welcome to your feedback.
|
||||
|
||||
Project Address [YukiHookAPI-ProjectBuilder](https://github.com/fankes/YukiHookAPI-ProjectBuilder)。
|
||||
|
||||
If you want to download directly, you can [click here](https://github.com/fankes/YukiHookAPI-ProjectBuilder/releases) to go to the Release address.
|
||||
|
||||
## Usage
|
||||
|
||||
> Here contains the basic usage and function explanation.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
- The software use process requires your device connected to the Internet.
|
||||
|
||||
- After starting the software, simply configure the project you want to create, click the **button** in the lower right corner or select **Project > Run Build** from the menu bar to start the task.
|
||||
|
||||
- After waiting for the automatic dependency search to complete, you can configure the project dependencies. It is recommended to use the latest dependencies to ensure the stability of the project, and the build tools only support the latest dependencies.
|
||||
|
||||
- Select the folder where you need to create the project. After starting, the project will be created in the location you selected, and wait for the whole process to complete and the project will be created.
|
||||
|
||||
### Config Template
|
||||
|
||||
Config template is an extension function, you can select menu bar **Project > Config Template > New Template**.
|
||||
|
||||
And then, you can create a template with the current config, and you can re-create it from **Saved Template** next time Load the template to restore the current config.
|
||||
|
||||
### Multilingual Support
|
||||
|
||||
The software language follows the current system, and you can manually select the software interface language in the **Language** column of the menu bar.
|
17
docs-source/src/index.md
Normal file
17
docs-source/src/index.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
home: true
|
||||
navbar: false
|
||||
sidebar: false
|
||||
title: null
|
||||
heroAlt: null
|
||||
heroText: null
|
||||
tagline: Select a language
|
||||
actions:
|
||||
- text: English
|
||||
link: /en/
|
||||
type: secondary
|
||||
- text: 简体中文
|
||||
link: /zh-cn/
|
||||
type: secondary
|
||||
footer: MIT License | Copyright (C) 2019-2022 HighCapable
|
||||
---
|
33
docs-source/src/zh-cn/about/about.md
Normal file
33
docs-source/src/zh-cn/about/about.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# 关于此文档
|
||||
|
||||
> 此文档由 [VuePress](https://v2.vuepress.vuejs.org/zh) 强力驱动。
|
||||
|
||||
## License
|
||||
|
||||
[The MIT License (MIT)](https://github.com/fankes/YukiHookAPI/blob/master/LICENSE)
|
||||
|
||||
```:no-line-numbers
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2019-2022 HighCapable
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
版权所有 © 2019-2022 HighCapable
|
272
docs-source/src/zh-cn/about/changelog.md
Normal file
272
docs-source/src/zh-cn/about/changelog.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# 更新日志
|
||||
|
||||
> 这里记录了 `YukiHookAPI` 的版本更新历史。
|
||||
|
||||
::: danger
|
||||
|
||||
我们只会对最新的 API 版本进行维护,若你正在使用过时的 API 版本则代表你自愿放弃一切维护的可能性。
|
||||
|
||||
:::
|
||||
|
||||
### 1.0.92 | 2022.05.31  <Badge type="tip" text="最新" vertical="middle" />
|
||||
|
||||
- 修正了大量方法中 callback 的命名方法
|
||||
- 更换方案再次修复 `YukiHookDataChannel` 在低于 **Android 12** 的设备上不能回调当前 `Activity` 广播的问题
|
||||
- `InjectYukiHookWithXposed` 注解新增 `isUsingResourcesHook` 功能,现在你可以选择性关闭自动生成 `IXposedHookInitPackageResources` 的依赖接口了
|
||||
|
||||
### 1.0.91 | 2022.05.29  <Badge type="warning" text="过旧" vertical="middle" />
|
||||
|
||||
- 修复部分设备的定制系统在 LSPosed 环境下开机启动获取的 `ClassLoader` 错误的问题,感谢 [Luckyzyx](https://github.com/luckyzyx) 的反馈
|
||||
- 修复 `YukiHookDataChannel` 在 **ZUI** 以及低于 **Android 12** 的系统上不能回调当前 `Activity` 广播的问题
|
||||
- 整合 `YukiHookModuleStatus` 功能到 `YukiHookAPI.Status`,重写了大量方法,现在你可以在模块与宿主中双向判断模块激活等状态信息
|
||||
|
||||
### 1.0.90 | 2022.05.27  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `YukiHookDataChannel` 在模块设置监听回调时闪退的问题
|
||||
- 修复 `YukiHookDataChannel` 在非当前 `Activity` 情况下依然会回调的问题
|
||||
- 移除 `YukiHookDataChannel` 回调事件的默认值,没有即不回调
|
||||
- 移除 `YukiHookModulePrefs` 在 XShare 不可读的情况下打印的警告
|
||||
- 新增 `YukiHookModulePrefs` 中的 `isXSharePrefsReadable` 方法,可判断当前的 XShare 是否可用
|
||||
|
||||
### 1.0.89 | 2022.05.26  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `YukiHookDataChannel` 不能重复设置监听的问题,并加入在模块不同 `Activity` 中重复响应和自动跟随 `Activity` 销毁监听功能
|
||||
- 新增 `YukiHookDataChannel` 重复监听用例说明文档
|
||||
- 加入 `onAlreadyHooked` 方法,可判断当前方法是否被重复 Hook
|
||||
- 修改部分重复添加 HashMap 的逻辑,移除 `putIfAbsent` 方法,允许覆盖添加
|
||||
- 修复了几处可能的 BUG
|
||||
|
||||
### 1.0.88 | 2022.05.25  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 对 Xposed API 完全解耦合
|
||||
- 增加了 `type` 中的 `android` 类型
|
||||
- 将 `YukiHookModuleStatus` 从自动生成代码中分离,并加入 `isEnableHookModuleStatus` 的开关,由你决定是否启用
|
||||
- 对 API 大量类的构造方法进行了 internal 闭包处理
|
||||
- 将 `YukiHookModulePrefs` 设置为单例运行,防止重复创建浪费系统资源
|
||||
- 修复自 `1.0.80` 版本后无法嵌套 Hook 的 BUG,并优化嵌套 Hook 相关功能
|
||||
- 修改 Hooker 存储方案由 HashSet 到 HashMap,防止重复添加 Hooker 的问题
|
||||
- 修改 Hook 核心实现方法,加入查重,避免重复 Hook 多次回调 `HookParam` 方法
|
||||
- `MethodFinder` 与 `FieldFinder` 加入查找模糊方法、变量名称功能,可调用 `name { ... }` 来设置查找条件,支持正则
|
||||
- 优化并修改 `appContext` 的获取方式,降低会取到空的问题的可能性
|
||||
- 修改自动生成的代码中 `logger` 的打印 `TAG` 默认为你自定义的名称,方便进行调试
|
||||
- 优化 `YukiHookBridge` 的 `Hooker` 实现方式,提升 Hook 性能
|
||||
- `PackageParam` 增加 `onAppLifecycle` 方法,可原生监听宿主的生命周期以及实现注册系统广播功能
|
||||
- 新增 `YukiHookDataChannel` 功能,可在模块与宿主保持存活的情况下使用系统无序广播进行通讯
|
||||
- `YukiHookDataChannel` 增加 `checkingVersionEquals` 方法,可通过监听来验证模块更新后宿主并未更新版本不匹配问题
|
||||
- `demo-module` 的示例代码中新增 Java 版本的示例,仅供参考
|
||||
|
||||
### 1.0.87 | 2022.05.10  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 新增 `refreshModuleAppResources` 功能,以适配语言区域、字体大小、分辨率改变等情况下的 Resources 刷新
|
||||
- 新增 `isEnableModuleAppResourcesCache` 功能,可自行设置是否自动缓存当前模块的 Resources
|
||||
|
||||
### 1.0.86 | 2022.05.06  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复不支持 Resources Hook(资源钩子) 的情况下在 `initZygote` 时持续报错的问题,复现在 **ZUI**/**LSPosed CI(1.8.3-6550)**
|
||||
- 优化并对 Resources Hook 进行异常处理,只有被使用后不支持才会打印错误和警告
|
||||
|
||||
### 1.0.85 | 2022.05.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复无法 Hook 系统框架的严重问题,从 `1.0.80` 开始出现
|
||||
- 调试日志中新增区分 `initZygote` 装载的包名为 `android-zygote`,`packageName` 保持 `android` 不变
|
||||
|
||||
### 1.0.83 | 2022.05.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `YukiHookModuleStatus` 在 `loadSystem` 后大量报错的问题
|
||||
- 新增 `type` 中的 `android` 类型
|
||||
- 更新帮助文档的示例说明
|
||||
|
||||
### 1.0.82 | 2022.05.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复了一处概念混淆错误,区分 `initZygote` 与系统框架的关系,之前的注释和文档有问题,非常抱歉
|
||||
- `PackageParam` 新增 `loadSystem` 方法,不需要再写 `loadApp(name = "android")` 即可 Hook 系统框架
|
||||
|
||||
### 1.0.81 | 2022.05.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复使用 `by` 方法设置条件后 Hook 方法体内查找不到的方法、构造方法依然输出错误日志的问题
|
||||
- 在执行 Hook 过程中加入全局日志显示当前 Hook APP 的包名,并修复一处错误日志打印样式的问题
|
||||
|
||||
### 1.0.80 | 2022.05.01  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- `InjectYukiHookWithXposed` 注解新增 `entryClassName` 功能,可自定义生成的 `xposed_init` 入口类名
|
||||
- ~~`YukiHookXposedInitProxy`~~ 更名为 `IYukiHookXposedInit`,原接口名称已作废,将在后续版本中直接被删除
|
||||
- 新增 `initZygote` 与 Resources Hook 功能,支持 Hook Layout
|
||||
- 新增 `onXposedEvent` 方法,可监听原生 Xposed API 的全部事件
|
||||
- 对 Hook 功能的 `lambda` 进行 `inline` 处理,避免生成过碎的匿名类,提升编译后的运行性能
|
||||
- 修复 `PrefsData` 编译后的方法体复制过大的问题
|
||||
- 增加 `XSharePreference` 可读性测试,失败后会自动打印警告日志
|
||||
- `PackageParam` 新增 `appResources`、`moduleAppResources`、`moduleAppFilePath` 功能
|
||||
- `PackageParam` 的 `loadApp` 新增不写 `name` 功能,默认筛选全部 APP
|
||||
- `PackageParam` 新增 `loadZygote` 方法,可直接 Hook 系统框架
|
||||
- `PackageParam` 新增 `resources().hook` 功能
|
||||
- 优化方法、构造方法、变量查找功能,找不到的错误日志将优先显示已设置的查询条件
|
||||
- 增加 `hasExtends` 扩展方法,可判断当前 `Class` 是否有继承关系
|
||||
- 增加 `isSupportResourcesHook` 功能,判断当前是否支持资源钩子(Resources Hook)
|
||||
- `current` 功能新增 `superClass` 方法调用父类
|
||||
- 查找方法、构造方法、变量新增 `superClass` 查询条件,可继续在父类中查找
|
||||
- `YukiHookAPI` 大量方法与 Xposed API 解耦合
|
||||
- 新增 Xposed API 的原生 Hook 优先级功能
|
||||
- 修复 `isFirstApplication` 可能判断不准确的问题
|
||||
- 屏蔽 MIUI 系统上 MiuiCatcherPatch 重复调用 Hook 入口方法的问题
|
||||
- 优化 Hook 入口调用方法,避免因为 Hook Framework 问题导致多次调用
|
||||
- 修复 Hook `ClassLoader` 导致 Hook 卡死的问题,感谢 [WankkoRee](https://github.com/WankkoRee) 的反馈
|
||||
- 提升 `XC_Callback` 接口对接后的性能
|
||||
- Java `type` 新增 `ClassLoader` 类型
|
||||
- 优化 API 帮助文档,修复可能持续缓存页面的问题
|
||||
|
||||
### 1.0.78 | 2022.04.18  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- `YukiHookModulePrefs` 新增 `isRunInNewXShareMode` 方法,可用于判断模块当前是否处于 `New XSharePreference` 模式
|
||||
- 修复 `YukiHookModulePrefs` 在 `New XSharePreference` 模式下工作的部分问题
|
||||
- 新增 `ModulePreferenceFragment`,现在,你可以完全替换掉 `PreferenceFragmentCompat` 并开始使用新的功能
|
||||
- 适配 `PreferenceFragmentCompat` 的 Sp 数据存储解决方案,感谢 [mahoshojoHCG](https://github.com/mahoshojoHCG) 的反馈
|
||||
- 更新自动处理程序以及 `Kotlin` 依赖到最新版本
|
||||
- 修正部分文档和代码注释中的错误
|
||||
|
||||
### 1.0.77 | 2022.04.15  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- `YukiHookModulePrefs` 新增 `clear` 方法,感谢 [WankkoRee](https://github.com/WankkoRee) 的建议
|
||||
- `YukiHookModulePrefs` 新增 `getStringSet`、`putStringSet`、`all` 方法
|
||||
- `HookParam` 的 `args` 增加 `any` 方法
|
||||
- 新增 `ModuleApplication`,可在模块中继承此类实现更多功能
|
||||
- 对接全部的 `findClass` 功能到 Xposed API,在非宿主环境继续使用原生 `ClassLoader`
|
||||
- 修复了一些可能存在的 BUG
|
||||
|
||||
### 1.0.75 | 2022.04.13  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 更正了自动处理程序的逻辑识别部分,感谢 [ApeaSuperz](https://github.com/ApeaSuperz) 的贡献
|
||||
- 修正一处文档注释的引用未更改的问题
|
||||
- `HookParam` 中删除了 `firstArgs` 与 `lastArgs` 方法,现在你可以使用 `args().first()` 与 `args().last()` 来取代它
|
||||
- `HookParam` 中删除了 `args()` 中的默认参数 `index = 0`,现在你可以使用 `args().first()` 或 `args(index = 0)` 来取代它
|
||||
- `HookParam` 中 `result` 功能增加了泛型匹配,现在你可以使用 `result<T>` 来匹配你的目标方法已知返回值类型了
|
||||
- 方法、构造方法查询功能新增 `emptyParam` 条件,并完善了文档相关需要注意的查询条件误区
|
||||
- 增加了 `type` 中的 `android` 类型
|
||||
|
||||
### 1.0.73 | 2022.04.10
|
||||
|
||||
- 修正几处文档的中文翻译错误,感谢 [WankkoRee](https://github.com/WankkoRee) 的贡献
|
||||
- 修复在某些情况下 `XC_LoadPackage.LoadPackageParam` 内容为空抛出异常的问题,感谢 [Luckyzyx](https://github.com/luckyzyx) 的反馈
|
||||
- 修复一些已知的 BUG,提升 Hook 稳定性
|
||||
|
||||
### 1.0.72 | 2022.04.09  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 更新 API 文档到新的地址
|
||||
- `PackageParam` 中加入 `appContext` 功能
|
||||
- 修复一些已知的 BUG,提升 Hook 稳定性
|
||||
|
||||
### 1.0.71 | 2022.04.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 VariousClass 无法匹配时会停止 Hook 抛出异常的严重问题
|
||||
|
||||
### 1.0.70 | 2022.04.04  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `instanceClass` 在静态实例中调用后报错问题
|
||||
- 在 Hook 过程中加入 `isUseAppClassLoader` 功能,感谢 [WankkoRee](https://github.com/WankkoRee) 的反馈
|
||||
- 加入 `withProcess` 功能,可根据 APP 当前指定进程进行 Hook
|
||||
- 修复查找方法、构造类和变量的严重逻辑错误问题
|
||||
- 修复 Hook 目标类不存在的时候无法忽略异常输出的问题
|
||||
- 修复部分情况下 APP 启动方法装载过快导致 Hook 不能生效的问题
|
||||
- 修复 `allMethods` 未 Hook 到方法时不会抛出异常的问题,感谢 [WankkoRee](https://github.com/WankkoRee) 的反馈
|
||||
- 加入 Hook 状态监听功能,感谢 [WankkoRee](https://github.com/WankkoRee) 的建议
|
||||
- 修改 Xposed 入口注入类的方式,重新声明 API 的定义域
|
||||
- 加入混淆的方法以及变量的查找功能,可使用不同类型筛选 `index` 定位指定的方法和变量,感谢 [WankkoRee](https://github.com/WankkoRee) 提供的思路
|
||||
- 查找方法、变量时允许传入多种类型,例如 `String` 声明的类名和 `VariousClass`
|
||||
- 加入全新的 `current` 功能,可对任意的类构建一个反射方法操作空间,方便地调用和修改其中的方法和变量
|
||||
- 修复了 Hook 过程中的大量 BUG,感谢 [WankkoRee](https://github.com/WankkoRee) 对此项目所做出的贡献
|
||||
|
||||
### 1.0.69 | 2022.03.30  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 添加并改进一些方法功能的注释
|
||||
- 增加 Demo 中的更多示例 Hook 内容
|
||||
- 修复在一个 Hook 实例中,`allMethods` 多次使用时只有最后一个生效的问题,感谢 [WankkoRee](https://github.com/WankkoRee) 的反馈
|
||||
|
||||
### 1.0.68 | 2022.03.29  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 增加 Demo 中的新用例和 LSPosed 作用域
|
||||
- 增加 `Member` 查找缓存和查找缓存配置开关
|
||||
- 移除和修改 `MethodFinder`、`FieldFinder` 以及 `HookParam` 相关方法的调用
|
||||
- 增加更多 `Finder` 中的 `cast` 类型并支持 `cast` 为数组
|
||||
- 整体的性能和稳定性提升
|
||||
- 修复上一个版本可能存在的 BUG
|
||||
|
||||
### 1.0.67 | 2022.03.27  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 增加三个 `Finder` 中的 `modifiers` 功能,可筛选 `static`、`native`、`public`、`abstract` 等诸多描述类型
|
||||
- 增加方法和构造方法查找时可模糊方法参数类型为指定个数进行查找
|
||||
- 增加 `Member` 的 `hasModifiers` 扩展功能
|
||||
- 增加 `MethodFinder` 和 `ConstructorFinder` 中的 `give` 方法,可获得原始类型
|
||||
- 增加 `YukiHookModulePrefs` 中的 `PrefsData` 模板功能
|
||||
- 彻底对方法、构造方法及变量的查找方案进行重构
|
||||
- 优化代码注释,修复了可能产生的 BUG
|
||||
|
||||
### 1.0.66 | 2022.03.25  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `MethodFinder` 中的一个严重问题
|
||||
- 增加 `hookParam` 中的 `args` 调用方法
|
||||
- 修复其它可能存在的问题以及修复部分类的注释问题
|
||||
|
||||
### 1.0.65 | 2022.03.25  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 重新发布版本修复 Maven 仓库因为缓存问题新版本不正确的情况
|
||||
- 增加 `MethodFinder` 与 `FieldFinder` 新的返回值调用方法
|
||||
- 修复可能存在的问题,并修复太极使用过程中可能存在的问题
|
||||
- 修复自动生成 Xposed 入口类可能发生的问题
|
||||
- 增加了 `type` 中的 `android` 类型以及 `java` 类型
|
||||
|
||||
### 1.0.6 | 2022.03.20  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 `YukiHookModulePrefs` 在使用一次 `direct` 忽略缓存后每次都忽略的 BUG
|
||||
- 增加新的 API,作废了 `isActive` 判断模块激活的传统用法
|
||||
- 修复非 Xposed 环境使用 API 时打印调试日志的问题
|
||||
- 修复查找 `Field` 时的日志输出问题和未拦截的异常问题
|
||||
- 解耦合 `ReflectionUtils` 中的 Xposed API
|
||||
- 增加 `YukiHookModuleStatus` 方法名称的混淆,以精简模块生成的体积
|
||||
- 装载模块自身 Hook 时将不再打印欢迎信息
|
||||
- 修复上一个版本仍然存在的某些 BUG
|
||||
|
||||
### 1.0.55 | 2022.03.18  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修正一处注释错误
|
||||
- 临时修复一个 BUG
|
||||
- 增加了 `type` 中的大量 `android` 类型以及少量 `java` 类型
|
||||
- 修复新版与旧版 Kotlin APIs 的兼容性问题
|
||||
|
||||
### 1.0.5 | 2022.03.18  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复旧版本 LSPosed 框架情况下欢迎信息多次打印的问题
|
||||
- 添加 `onInit` 方法来配置 `YukiHookAPI`
|
||||
- 新增 `executorName` 和 `executorVersion` 来获取当前 Hook 框架的名称和版本号
|
||||
- 新增 `by` 方法来设置 Hook 的时机和条件
|
||||
- `YukiHookModulePrefs` 新增可控制的键值缓存,可在宿主运行时模块动态更新数据
|
||||
- 修复了一些可能存在的 BUG
|
||||
|
||||
### 1.0.4 | 2022.03.06  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 LSPosed 在最新版本中启用“只有模块classloader可以使用Xposed API”选项后找不到 `XposedBridge` 的问题
|
||||
- 添加 `YukiHookAPI` 的常量版本名称和版本号
|
||||
- 新增 `hasField` 方法以及 `isAllowPrintingLogs` 配置参数
|
||||
- 新增 `isDebug` 开启的情况下 API 将自动打印欢迎信息测试模块是否生效
|
||||
|
||||
### 1.0.3 | 2022.03.02  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复一个潜在性的异常未拦截 BUG
|
||||
- 增加 `ignoredError` 功能
|
||||
- 增加了 `type` 中的 `android` 类型
|
||||
- 增加监听 `hook` 后的 `ClassNotFound` 功能
|
||||
|
||||
### 1.0.2 | 2022.02.18  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 修复 Windows 下无法找到项目路径的问题
|
||||
- 移除部分反射 API,合并至 `BaseFinder` 进行整合
|
||||
- 增加直接使用字符串创建 Hook 的方法
|
||||
|
||||
### 1.0.1 | 2022.02.15  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- `RemedyPlan` 增加 `onFind` 功能
|
||||
- 整合并修改了部分反射 API 代码
|
||||
- 增加了 `type` 中的 `java` 类型
|
||||
- 修复忽略错误在控制台仍然输出的问题
|
||||
|
||||
### 1.0 | 2022.02.14  <Badge type="danger" text="过期" vertical="middle" />
|
||||
|
||||
- 首个版本提交至 Maven
|
11
docs-source/src/zh-cn/about/contacts.md
Normal file
11
docs-source/src/zh-cn/about/contacts.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# 联系我们
|
||||
|
||||
> 如在使用中有任何问题,或有任何建设性的建议,都可以联系我们。
|
||||
|
||||
加入我们 [点击加入 Telegram 群组](https://t.me/YukiHookAPI)
|
||||
|
||||
在 **酷安** 找到我 [@星夜不荟](http://www.coolapk.com/u/876977)
|
||||
|
||||
## 助力维护
|
||||
|
||||
感谢您选择并使用 `YukiHookAPI`,如有代码相关的建议和请求,可在 Github 提交 Pull Request。
|
37
docs-source/src/zh-cn/about/future.md
Normal file
37
docs-source/src/zh-cn/about/future.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 展望未来
|
||||
|
||||
> 未来是美好的,也是不确定的,让我们共同期待 `YukiHookAPI` 在未来的发展空间。
|
||||
|
||||
## 未解决的问题
|
||||
|
||||
> 这里收录了 `YukiHookAPI` 尚未解决的问题。
|
||||
|
||||
### YukiHookModulePrefs
|
||||
|
||||
目前仅限完美支持 LSPosed,其它 Xposed 框架需要降级模块 API。
|
||||
|
||||
可能完全不支持太极,太极在高版本系统上需要更低的 API 才能适配。
|
||||
|
||||
部分 Xposed 模块开发者目前选择 Hook 目标 APP 内置 Sp 存储方案解决模块设置共享问题。
|
||||
|
||||
后期 Android 系统的权限将越来越严格,`selinux` 就是目前面临的一个大问题,有待讨论和研究。
|
||||
|
||||
## 未来的计划
|
||||
|
||||
> 这里收录了 `YukiHookAPI` 可能会在后期添加的功能。
|
||||
|
||||
### 支持独立使用的 Lite 版本
|
||||
|
||||
::: tip 待讨论
|
||||
|
||||
目前 API 只支持通过自动处理程序绑定到 **xposed_init**,若您不喜欢自动处理程序,一定要自己实现模块装载入口,未来会按照需求人数推出仅有 API 功能的 Lite 版本,你可向我们提出 **issues**。
|
||||
|
||||
:::
|
||||
|
||||
API 已经提供了 Xposed 原生 API 监听接口,你可以 [在这里](../config/xposed-using#原生-xposed-api-事件) 找到或查看 Demo 的实现方法。
|
||||
|
||||
### 支持更多 Hook Framework
|
||||
|
||||
作为 API 来讲,目前仅仅对接 `XposedBridge` 作为兼容层,还是有一定的局限性。
|
||||
|
||||
大部分 `inline hook` 没有 `Java` 兼容层,后期可能会考虑 `native hook` 的 `Java` 兼容层适配。
|
55
docs-source/src/zh-cn/api/home.md
Normal file
55
docs-source/src/zh-cn/api/home.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
next:
|
||||
text: Public API
|
||||
link: /zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI
|
||||
---
|
||||
|
||||
# 文档介绍
|
||||
|
||||
> 这里的文档将同步最新 API 版本的相关用法,请保持 `YukiHookAPI` 为最新版本以使用最新版本的功能。
|
||||
|
||||
## 功能描述说明
|
||||
|
||||
> 功能描述主要介绍当前 API 的相关用法和用途。
|
||||
|
||||
## 功能示例说明
|
||||
|
||||
> 功能示例主要展示了当前 API 的基本用法示例,可供参考。
|
||||
|
||||
## 变更记录说明
|
||||
|
||||
首个版本的功能将标记为 `v<version>` `添加`;
|
||||
|
||||
后期新增加的功能将标记为 `v<version>` `新增`;
|
||||
|
||||
后期修改的功能将被追加为 `v<version>` `修改`;
|
||||
|
||||
后期被作废的功能将标记为 `v<version>` `作废` 并会标注删除线;
|
||||
|
||||
后期被删除的功能将标记为 `v<version>` `移除` 并会标注删除线。
|
||||
|
||||
## 相关符号说明
|
||||
|
||||
- *kt* Kotlin Static File
|
||||
|
||||
- *annotation* 注解
|
||||
|
||||
- *interface* 接口
|
||||
|
||||
- *object* 类 (单例)
|
||||
|
||||
- *class* 类
|
||||
|
||||
- *field* 变量或 `get`、`set` 方法或只读的 `get` 方法
|
||||
|
||||
- *method* 方法
|
||||
|
||||
- *enum* Enum 常量
|
||||
|
||||
- *ext-field* 扩展的变量 (全局)
|
||||
|
||||
- *ext-method* 扩展的方法 (全局)
|
||||
|
||||
- *i-ext-field* 扩展的变量 (调用域限制)
|
||||
|
||||
- *i-ext-method* 扩展的方法 (调用域限制)
|
@@ -0,0 +1,557 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiHookAPI <span class="symbol">- object</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
object YukiHookAPI
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是 `YukiHookAPI` 的 API 调用总类,Hook 相关功能的开始、Hook 相关功能的配置都在这里。
|
||||
|
||||
## API_VERSION_NAME <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
const val API_VERSION_NAME: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.4` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 `YukiHookAPI` 的版本。
|
||||
|
||||
## API_VERSION_CODE <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
const val API_VERSION_CODE: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.4` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 `YukiHookAPI` 的版本号。
|
||||
|
||||
<h2 class="deprecated">executorName - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `Status.executorName`
|
||||
|
||||
<h2 class="deprecated">executorVersion - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `Status.executorVersion`
|
||||
|
||||
## Status <span class="symbol">- object</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
object Status
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当前 `YukiHookAPI` 的状态。
|
||||
|
||||
### isXposedEnvironment <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isXposedEnvironment: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前是否为 (Xposed) 宿主环境。
|
||||
|
||||
### executorName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val executorName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 框架的名称。
|
||||
|
||||
无法获取会返回 `unknown`,`XposedBridge` 不存在会返回 `invalid`。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中需要启用 **Configs.isEnableHookModuleStatus**。
|
||||
|
||||
:::
|
||||
|
||||
### executorVersion <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val executorVersion: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 框架的版本。
|
||||
|
||||
无法获取会返回 `-1`。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中需要启用 **Configs.isEnableHookModuleStatus**。
|
||||
|
||||
:::
|
||||
|
||||
### isModuleActive <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isModuleActive: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 判断模块是否在 Xposed 或太极、无极中激活。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中你需要将 **Application** 继承于 **ModuleApplication**。
|
||||
|
||||
在模块环境中需要启用 **Configs.isEnableHookModuleStatus**。
|
||||
|
||||
在 (Xposed) 宿主环境中仅返回非 **isTaiChiModuleActive** 的激活状态。
|
||||
|
||||
:::
|
||||
|
||||
### isXposedModuleActive <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isXposedModuleActive: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅判断模块是否在 Xposed 中激活。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中需要启用 **Configs.isEnableHookModuleStatus**。
|
||||
|
||||
在 (Xposed) 宿主环境中始终返回 true。
|
||||
|
||||
:::
|
||||
|
||||
### isTaiChiModuleActive <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isTaiChiModuleActive: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅判断模块是否在太极、无极中激活。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中你需要将 **Application** 继承于 **ModuleApplication**。
|
||||
|
||||
在 (Xposed) 宿主环境中始终返回 false。
|
||||
|
||||
:::
|
||||
|
||||
### isSupportResourcesHook <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isSupportResourcesHook: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.91` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。
|
||||
|
||||
::: warning
|
||||
|
||||
在模块环境中需要启用 **Configs.isEnableHookModuleStatus**。
|
||||
|
||||
在 (Xposed) 宿主环境中可能会延迟等待事件回调后才会返回 true。
|
||||
|
||||
请注意你需要确保 **InjectYukiHookWithXposed.isUsingResourcesHook** 已启用,否则始终返回 false。
|
||||
|
||||
:::
|
||||
|
||||
## Configs <span class="symbol">- object</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
object Configs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对 API 相关功能的配置类。
|
||||
|
||||
### debugTag <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var debugTag: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 模块在调用 `logger` 时打印的日志 `TAG` 名称。
|
||||
|
||||
你可以方便地进行自定义,并可以在 `Logcat` 和 `XposedBridge.log` 中找到它们。
|
||||
|
||||
### isDebug <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isDebug: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用 DEBUG 模式。
|
||||
|
||||
默认为开启状态,开启后模块将会向 `Logcat` 和 `XposedBridge.log` 打印详细的 Hook 日志,关闭后仅会打印 `E` 级别的日志。
|
||||
|
||||
### isAllowPrintingLogs <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isAllowPrintingLogs: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.4` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用调试日志的输出功能。
|
||||
|
||||
::: warning
|
||||
|
||||
关闭后将会停用 **YukiHookAPI** 对全部日志的输出,但是不影响当你手动调用日志方法输出日志。
|
||||
|
||||
:::
|
||||
|
||||
### isEnableModulePrefsCache <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableModulePrefsCache: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用 `YukiHookModulePrefs` 的键值缓存功能。
|
||||
|
||||
为防止内存复用过高问题,此功能默认启用。
|
||||
|
||||
你可以手动在 `YukiHookModulePrefs` 中自由开启和关闭缓存功能以及清除缓存。
|
||||
|
||||
### isEnableModuleAppResourcesCache <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableModuleAppResourcesCache: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.87` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用当前 Xposed 模块自身 `Resources` 缓存功能。
|
||||
|
||||
为防止内存复用过高问题,此功能默认启用。
|
||||
|
||||
你可以手动调用 `PackageParam.refreshModuleAppResources` 来刷新缓存。
|
||||
|
||||
::: warning
|
||||
|
||||
关闭后每次使用 **PackageParam.moduleAppResources** 都会重新创建,可能会造成运行缓慢。
|
||||
|
||||
:::
|
||||
|
||||
### isEnableHookModuleStatus <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableHookModuleStatus: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用 Hook Xposed 模块激活等状态功能.
|
||||
|
||||
为原生支持 Xposed 模块激活状态检测,此功能默认启用。
|
||||
|
||||
::: warning
|
||||
|
||||
关闭后你将不能再在模块环境中使用 **YukiHookAPI.Status** 中的激活状态判断功能。
|
||||
|
||||
:::
|
||||
|
||||
### isEnableHookSharedPreferences <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableHookSharedPreferences: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用 Hook `SharedPreferences`。
|
||||
|
||||
启用后将在模块启动时强制将 `SharedPreferences` 文件权限调整为 `Context.MODE_WORLD_READABLE` (0664)。
|
||||
|
||||
::: warning
|
||||
|
||||
这是一个可选的实验性功能,此功能默认不启用。
|
||||
|
||||
仅用于修复某些系统可能会出现在启用了 **New XSharedPreferences** 后依然出现文件权限错误问题,若你能正常使用 **YukiHookModulePrefs** 就不建议启用此功能。
|
||||
|
||||
:::
|
||||
|
||||
### isEnableDataChannel <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableDataChannel: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用当前 Xposed 模块与宿主交互的 `YukiHookDataChannel` 功能。
|
||||
|
||||
请确保 Xposed 模块的 `Application` 继承于 `ModuleApplication` 才能有效。
|
||||
|
||||
此功能默认启用,关闭后将不会在功能初始化的时候装载 `YukiHookDataChannel`。
|
||||
|
||||
### isEnableMemberCache <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var isEnableMemberCache: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否启用 `Member` 缓存功能。
|
||||
|
||||
为防止 `Member` 复用过高造成的系统 GC 问题,此功能默认启用。
|
||||
|
||||
启用后会缓存已经找到的 `Method`、`Constructor`、`Field`。
|
||||
|
||||
缓存的 `Member` 都将处于 `MemberCacheStore` 的全局静态实例中。
|
||||
|
||||
推荐使用 `MethodFinder`、`ConstructorFinder`、`FieldFinder` 来获取 `Member`。
|
||||
|
||||
除非缓存的 `Member` 发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 `Member`,否则建议启用。
|
||||
|
||||
## configs <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun configs(initiate: Configs.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对 `Configs` 类实现了一个 `lambda` 方法体。
|
||||
|
||||
你可以轻松的调用它进行配置。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以在 `HookEntryClass` 的 `onInit` 方法中调用 `configs` 方法完成对 API 的功能配置,实时生效。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntryClass : IYukiHookXposedInit {
|
||||
|
||||
override fun onInit() {
|
||||
YukiHookAPI.configs {
|
||||
debugTag = "YukiHookAPI"
|
||||
isDebug = BuildConfig.DEBUG
|
||||
isAllowPrintingLogs = true
|
||||
isEnableModulePrefsCache = true
|
||||
isEnableModuleAppResourcesCache = true
|
||||
isEnableHookModuleStatus = true
|
||||
isEnableDataChannel = true
|
||||
isEnableMemberCache = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若觉得上面的写法不美观,你还可以写得更加简洁。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntryClass : IYukiHookXposedInit {
|
||||
|
||||
override fun onInit() = configs {
|
||||
debugTag = "YukiHookAPI"
|
||||
isDebug = BuildConfig.DEBUG
|
||||
isAllowPrintingLogs = true
|
||||
isEnableModulePrefsCache = true
|
||||
isEnableModuleAppResourcesCache = true
|
||||
isEnableHookModuleStatus = true
|
||||
isEnableDataChannel = true
|
||||
isEnableMemberCache = true
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你也可以不通过 `configs` 方法,直接进行配置。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntryClass : IYukiHookXposedInit {
|
||||
|
||||
override fun onInit() {
|
||||
YukiHookAPI.Configs.debugTag = "YukiHookAPI"
|
||||
YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG
|
||||
YukiHookAPI.Configs.isAllowPrintingLogs = true
|
||||
YukiHookAPI.Configs.isEnableModulePrefsCache = true
|
||||
YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true
|
||||
YukiHookAPI.Configs.isEnableHookModuleStatus = true
|
||||
YukiHookAPI.Configs.isEnableDataChannel = true
|
||||
YukiHookAPI.Configs.isEnableMemberCache = true
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## encase <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(vararg hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载 Hook 入口的核心方法。
|
||||
|
||||
**功能示例**
|
||||
|
||||
详情请参考
|
||||
|
||||
- [通过 lambda 创建](../../config/api-example#通过-lambda-创建)
|
||||
|
||||
- [通过自定义 Hooker 创建](../../config/api-example#通过自定义-hooker-创建)
|
||||
|
||||
- [作为 Hook API 使用需要注意的地方](../../config/api-example#作为-hook-api-使用需要注意的地方)
|
@@ -0,0 +1,34 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# InjectYukiHookWithXposed <span class="symbol">- annotation</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
annotation class InjectYukiHookWithXposed(
|
||||
val sourcePath: String,
|
||||
val modulePackageName: String,
|
||||
val entryClassName: String,
|
||||
val isUsingResourcesHook: Boolean
|
||||
)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
新增 `entryClassName` 参数
|
||||
|
||||
`v1.0.92` `修改`
|
||||
|
||||
新增 `isUsingResourcesHook` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 标识 `YukiHookAPI` 注入 Xposed 入口的类注解。
|
||||
|
||||
**功能示例**
|
||||
|
||||
详情请参考 [InjectYukiHookWithXposed 注解](../../config/xposed-using#injectyukihookwithxposed-注解)。
|
@@ -0,0 +1,161 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# CurrentClass <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
调整了构造方法的参数名称
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当前实例的类操作对象。
|
||||
|
||||
## name <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val name: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 `classSet` 的 `Class.getName`。
|
||||
|
||||
## simpleName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val simpleName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 `classSet` 的 `Class.getSimpleName`。
|
||||
|
||||
## superClass <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun superClass(): SuperClass
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 调用父类实例。
|
||||
|
||||
## field <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 调用当前实例中的变量。
|
||||
|
||||
## method <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 调用当前实例中的方法。
|
||||
|
||||
## SuperClass <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class SuperClass internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当前类的父类实例的类操作对象。
|
||||
|
||||
### name <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val name: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 `classSet` 中父类的 `Class.getName`。
|
||||
|
||||
### simpleName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val simpleName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 `classSet` 中父类的 `Class.getSimpleName`。
|
||||
|
||||
### field <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 调用父类实例中的变量。
|
||||
|
||||
### method <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 调用父类实例中的方法。
|
@@ -0,0 +1,23 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# HookClass <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建一个当前 Hook 的 `Class` 接管类。
|
||||
|
||||
`instance` 为实例,`name` 为实例完整包名,`throwable` 为找不到实例的时候抛出的异常。
|
@@ -0,0 +1,20 @@
|
||||
---
|
||||
next:
|
||||
text: 特色功能
|
||||
link: /zh-cn/api/special-features/reflection
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# HookResources <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class HookResources internal constructor(var instance: YukiResources?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建一个当前 Hook 的 `YukiResources` 接管类。
|
@@ -0,0 +1,33 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# VariousClass <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class VariousClass(vararg var name: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个不确定性 `Class` 类名装载器,通过 `name` 装载 `Class` 名称数组。
|
||||
|
||||
## get <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun get(loader: ClassLoader? = null): Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取匹配的实体类。
|
||||
|
||||
使用当前 `loader` 装载目标 `Class`。
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,609 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiResourcesHookCreator <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
修正拼写错误的 **Creater** 命名到 **Creator**
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `YukiHookAPI` 的 `Resources` 核心 Hook 实现类。
|
||||
|
||||
## injectResource <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 注入要 Hook 的 Resources。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以注入任意 Resources,使用 `injectResource` 即可创建一个 `Hook` 对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
你还可以自定义 `tag`,方便你在调试的时候能够区分你的 `Hook` 对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource(tag = "KuriharaYuki") {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## ResourcesHookCreator <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class ResourcesHookCreator internal constructor(private val tag: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
移除 `packageName`
|
||||
|
||||
修正拼写错误的 **Creater** 命名到 **Creator**
|
||||
|
||||
**功能描述**
|
||||
|
||||
> Hook 核心功能实现类。
|
||||
|
||||
查找和处理需要 Hook 的 Resources。
|
||||
|
||||
### resourceId <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var resourceId: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 直接设置需要替换的 Resources Id。
|
||||
|
||||
::: warning
|
||||
|
||||
不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 **conditions** 方法。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以直接设置并指定目标 Hook APP 的 Resources Id。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
resourceId = 0x7f060001.toInt()
|
||||
replaceTo(...)
|
||||
}
|
||||
```
|
||||
|
||||
### conditions <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun conditions(initiate: ConditionFinder.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 查找条件。
|
||||
|
||||
若你设置了 `resourceId` 则此方法将不会被使用。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可参考 [ConditionFinder](#conditionfinder-class) 查看详细用法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "test_string"
|
||||
string()
|
||||
}
|
||||
replaceTo(...)
|
||||
}
|
||||
```
|
||||
|
||||
### replaceTo <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun replaceTo(any: Any)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 替换指定 Resources 为指定的值。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以替换找到的 Resources 为你想要的值,可以是 `String`、`Drawable` 等。
|
||||
|
||||
比如我们要替换一个找到的字符串 Resources。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "test_string"
|
||||
string()
|
||||
}
|
||||
replaceTo("replace string")
|
||||
}
|
||||
```
|
||||
|
||||
或是替换为一个 `Drawable`,你无需对目标 Resources 实现 `fwd` 方法或 `DrawableLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "test_drawable"
|
||||
drawable()
|
||||
}
|
||||
replaceTo(ColorDrawable(Color.RED))
|
||||
}
|
||||
```
|
||||
|
||||
### replaceToTrue <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun replaceToTrue()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 替换指定 Resources 为 `true`。
|
||||
|
||||
::: danger
|
||||
|
||||
确保目标替换 Resources 的类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
### replaceToFalse <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun replaceToFalse()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 替换指定 Resources 为 `false`。
|
||||
|
||||
::: danger
|
||||
|
||||
确保目标替换 Resources 的类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
### replaceToModuleResource <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun replaceToModuleResource(resId: Int)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 替换为当前 Xposed 模块的 Resources。
|
||||
|
||||
你可以直接使用模块的 `R.string.xxx`、`R.mipmap.xxx`、`R.drawable.xxx` 替换 Hook APP 的 Resources。
|
||||
|
||||
**功能示例**
|
||||
|
||||
使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。
|
||||
|
||||
这个过程你无需对目标 Resources 实现 `fwd` 方法。
|
||||
|
||||
比如我们要替换一个字符串。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "test_string"
|
||||
string()
|
||||
}
|
||||
replaceToModuleResource(R.string.module_string)
|
||||
}
|
||||
```
|
||||
|
||||
还可以替换一些复杂的 Resources,比如 `xml` 创建的 `drawable`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "test_drawable"
|
||||
drawable()
|
||||
}
|
||||
replaceToModuleResource(R.drawable.module_drawable)
|
||||
}
|
||||
```
|
||||
|
||||
### injectAsLayout <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 作为装载的布局注入。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以直接注入一个布局监听并修改它的内部 `View`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "activity_main"
|
||||
layout()
|
||||
}
|
||||
injectAsLayout {
|
||||
findViewByIdentifier<View>(name = "test_view")?.isVisible = false
|
||||
findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你还可以通过 `currentView` 拿到 `Context`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "activity_main"
|
||||
layout()
|
||||
}
|
||||
injectAsLayout {
|
||||
Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ConditionFinder <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class ConditionFinder internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> Resources 查找条件实现类。
|
||||
|
||||
#### name <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var name: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 名称。
|
||||
|
||||
#### anim <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun anim()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为动画。
|
||||
|
||||
#### animator <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun animator()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为属性动画。
|
||||
|
||||
#### bool <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun bool()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为布朗(Boolean)。
|
||||
|
||||
#### color <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun color()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为颜色(Color)。
|
||||
|
||||
#### dimen <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun dimen()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为尺寸(Dimention)。
|
||||
|
||||
#### drawable <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun drawable()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为 Drawable。
|
||||
|
||||
#### integer <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun integer()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为整型(Integer)。
|
||||
|
||||
#### layout <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun layout()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为布局(Layout)。
|
||||
|
||||
#### plurals <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun plurals()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为 Plurals。
|
||||
|
||||
#### string <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun string()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为字符串(String)。
|
||||
|
||||
#### xml <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun xml()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为 Xml。
|
||||
|
||||
#### mipmap <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun mipmap()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为位图(Mipmap)。
|
||||
|
||||
#### array <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun array()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 Resources 类型为数组(Array)。
|
||||
|
||||
### Result <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Result internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听全部 Hook 结果实现类,可在这里处理失败事件监听。
|
||||
|
||||
#### result <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun result(initiate: Result.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建监听事件方法体。
|
||||
|
||||
#### by <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun by(condition: () -> Boolean): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。
|
||||
|
||||
### onHookingFailure <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onHookingFailure(result: (Throwable) -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 Hook 过程发生错误的回调方法。
|
||||
|
||||
### ignoredHookingFailure <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun ignoredHookingFailure(): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 忽略 Hook 过程出现的错误。
|
@@ -0,0 +1,123 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# BaseFinder <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
abstract class BaseFinder
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
分离原始命名 `BaseFinder` 中的部分方法与参数到 `MemberBaseFinder`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是 `Class` 与 `Member` 查找类功能的基本类实现。
|
||||
|
||||
## BaseFinder.IndexTypeCondition <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 字节码下标筛选实现类。
|
||||
|
||||
### index <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun index(num: Int)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置下标。
|
||||
|
||||
若 `index` 小于零则为倒序,此时可以使用 `IndexTypeConditionSort.reverse` 方法实现。
|
||||
|
||||
可使用 `IndexTypeConditionSort.first` 和 `IndexTypeConditionSort.last` 设置首位和末位筛选条件。
|
||||
|
||||
### index <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun index(): IndexTypeConditionSort
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到下标。
|
||||
|
||||
### IndexTypeConditionSort <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class IndexTypeConditionSort internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 字节码下标排序实现类。
|
||||
|
||||
#### first <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun first()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置满足条件的第一个。
|
||||
|
||||
#### last <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun last()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置满足条件的最后一个。
|
||||
|
||||
#### reverse <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun reverse(num: Int)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置倒序下标。
|
@@ -0,0 +1,75 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# CountRules <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class CountRules private constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个模糊 `Class`、`Member` 数组 (下标) 个数条件实现类。
|
||||
|
||||
可对 R8 混淆后的 `Class`、`Member` 进行更加详细的定位。
|
||||
|
||||
## Int.isZero <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Int.isZero(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否为 0。
|
||||
|
||||
## Int.moreThan <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Int.moreThan(count: Int): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 大于 `count`。
|
||||
|
||||
## Int.lessThan <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Int.lessThan(count: Int): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 小于 `count`。
|
||||
|
||||
## Int.inInterval <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Int.inInterval(countRange: IntRange): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 在 `countRange` 区间 A ≤ this ≤ B。
|
@@ -0,0 +1,263 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModifierRules <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class ModifierRules private constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `Class` 的描述符判断
|
||||
|
||||
作为 lambda 整体判断条件使用
|
||||
|
||||
移动到 base 包名
|
||||
|
||||
私有化构造方法
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个 `Class`、`Member` 描述符条件实现类。
|
||||
|
||||
可对 R8 混淆后的 `Class`、`Member` 进行更加详细的定位。
|
||||
|
||||
## isPublic <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isPublic: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `public`。
|
||||
|
||||
## isPrivate <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isPrivate: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `private`。
|
||||
|
||||
## isProtected <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isProtected: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `protected`。
|
||||
|
||||
## isStatic <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isStatic: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `static`。
|
||||
|
||||
对于任意的静态 `Class`、`Member` 可添加此描述进行确定。
|
||||
|
||||
::: warning
|
||||
|
||||
Kotlin → Jvm 后的 **object** 类中的方法并不是静态的。
|
||||
|
||||
:::
|
||||
|
||||
## isFinal <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isFinal: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `final`。
|
||||
|
||||
::: warning
|
||||
|
||||
Kotlin → Jvm 后没有 **open** 符号标识的 **Class**、**Member** 和没有任何关联的 **Class**、**Member** 都将为 **final**。
|
||||
|
||||
:::
|
||||
|
||||
## isSynchronized <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isSynchronized: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `synchronized`。
|
||||
|
||||
## isVolatile <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isVolatile: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 类型是否包含 `volatile`。
|
||||
|
||||
## isTransient <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isTransient: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 类型是否包含 `transient`。
|
||||
|
||||
## isNative <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isNative: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Method` 类型是否包含 `native`。
|
||||
|
||||
对于任意 JNI 对接的 `Method` 可添加此描述进行确定。
|
||||
|
||||
## isInterface <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isInterface: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class` 类型是否包含 `interface`。
|
||||
|
||||
## isAbstract <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isAbstract: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `abstract`。
|
||||
|
||||
对于任意的抽象 `Class`、`Member` 可添加此描述进行确定。
|
||||
|
||||
## isStrict <span class="symbol">- i-ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isStrict: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Class`、`Member` 类型是否包含 `strictfp`。
|
@@ -0,0 +1,159 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# NameRules <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class NameRules private constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
`NameConditions` 更名为 `NameRules`
|
||||
|
||||
作为 lambda 整体判断条件使用
|
||||
|
||||
移动到 base 包名
|
||||
|
||||
私有化构造方法
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个模糊 `Class`、`Member` 名称条件实现类。
|
||||
|
||||
可对 R8 混淆后的 `Class`、`Member` 进行更加详细的定位。
|
||||
|
||||
## String.isSynthetic <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isSynthetic(index: Int): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否为匿名类的主类调用对象。
|
||||
|
||||
## String.isOnlySymbols <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlySymbols(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有符号。
|
||||
|
||||
## String.isOnlyLetters <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlyLetters(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有字母。
|
||||
|
||||
## String.isOnlyNumbers <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlyNumbers(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有数字。
|
||||
|
||||
## String.isOnlyLettersNumbers <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlyLettersNumbers(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有字母或数字。
|
||||
|
||||
## String.isOnlyLowercase <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlyLowercase(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有小写字母。
|
||||
|
||||
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
|
||||
|
||||
## String.isOnlyUppercase <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.isOnlyUppercase(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
统一合并到扩展方法并改名
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 是否只有大写字母。
|
||||
|
||||
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
|
@@ -0,0 +1,756 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ConstructorFinder <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.2` `修改`
|
||||
|
||||
合并到 `BaseFinder`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `MemberBaseFinder`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Constructor` 查找类。
|
||||
|
||||
可通过指定类型查找指定 `Constructor` 或一组 `Constructor`。
|
||||
|
||||
## paramCount <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var paramCount: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 参数个数。
|
||||
|
||||
你可以不使用 `param` 指定参数类型而是仅使用此变量指定参数个数。
|
||||
|
||||
若参数个数小于零则忽略并使用 `param`。
|
||||
|
||||
## modifiers <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `ModifierConditions`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 标识符筛选条件。
|
||||
|
||||
可不设置筛选条件,默认模糊查找并取第一个匹配的 `Constructor`。
|
||||
|
||||
::: danger
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## emptyParam <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun emptyParam(): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 空参数、无参数。
|
||||
|
||||
## param <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun param(vararg paramType: Any): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 参数。
|
||||
|
||||
如果同时使用了 `paramCount` 则 `paramType` 的数量必须与 `paramCount` 完全匹配。
|
||||
|
||||
如果 `Constructor` 中存在一些无意义又很长的类型,你可以使用 [VagueType](../../../type/defined/DefinedTypeFactory#vaguetype-field) 来替代它。
|
||||
|
||||
::: danger
|
||||
|
||||
无参 **Constructor** 请使用 **emptyParam** 设置查询条件。
|
||||
|
||||
有参 **Constructor** 必须使用此方法设定参数或使用 **paramCount** 指定个数。
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## paramCount <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun paramCount(num: Int): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 参数个数。
|
||||
|
||||
你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数。
|
||||
|
||||
若参数个数小于零则忽略并使用 `param`。
|
||||
|
||||
::: danger
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## paramCount <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun paramCount(numRange: IntRange): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 参数个数范围。
|
||||
|
||||
你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数范围。
|
||||
|
||||
::: danger
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## paramCount <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun paramCount(conditions: CountConditions): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Constructor` 参数个数条件。
|
||||
|
||||
你可以不使用 `param` 指定参数类型而是仅使用此方法指定参数个数条件。
|
||||
|
||||
::: danger
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## superClass <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun superClass(isOnlySuperClass: Boolean)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置在 `classSet` 的所有父类中查找当前 `Constructor`。
|
||||
|
||||
::: warning
|
||||
|
||||
若当前 **classSet** 的父类较多可能会耗时,API 会自动循环到父类继承是 **Any** 前的最后一个类。
|
||||
|
||||
:::
|
||||
|
||||
## RemedyPlan <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class RemedyPlan internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Constructor` 重查找实现类,可累计失败次数直到查找成功。
|
||||
|
||||
### constructor <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun constructor(initiate: ConstructorConditions)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建需要重新查找的 `Constructor`。
|
||||
|
||||
你可以添加多个备选 `Constructor`,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
|
||||
|
||||
### Result <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Result internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.1` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `RemedyPlan` 结果实现类。
|
||||
|
||||
#### onFind <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.1` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
`initiate` 参数 `Constructor` 变为 `HashSet<Constructor>`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当在 `RemedyPlan` 中找到结果时。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以方便地对重查找的 `Constructor` 实现 `onFind` 方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.onFind {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## Process <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Constructor` 查找结果处理类,为 `hookInstance` 提供。
|
||||
|
||||
### result <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun result(initiate: Process.() -> Unit): Process
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建监听结果事件方法体。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用 `lambda` 形式创建 `Result` 类。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.result {
|
||||
all()
|
||||
remedys {}
|
||||
onNoSuchConstructor {}
|
||||
}
|
||||
```
|
||||
|
||||
### all <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun all(): Process
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置全部查询条件匹配的多个 `Constructor` 实例结果到 `hookInstance`。
|
||||
|
||||
### remedys <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建 `Constructor` 重查找功能。
|
||||
|
||||
**功能示例**
|
||||
|
||||
当你遇到一种 `Constructor` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchConstructor` 捕获异常二次查找 `Constructor`。
|
||||
|
||||
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.remedys {
|
||||
constructor {
|
||||
// Your code here.
|
||||
}
|
||||
constructor {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### onNoSuchConstructor <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听找不到 `Constructor` 时。
|
||||
|
||||
只会返回第一次的错误信息,不会返回 `RemedyPlan` 的错误信息。
|
||||
|
||||
## Result <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
继承到接口 `BaseResult`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Constructor` 查找结果实现类。
|
||||
|
||||
### result <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun result(initiate: Result.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建监听结果事件方法体。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用 `lambda` 形式创建 `Result` 类。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.result {
|
||||
get().call()
|
||||
all()
|
||||
remedys {}
|
||||
onNoSuchConstructor {}
|
||||
}
|
||||
```
|
||||
|
||||
### get <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun get(): Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Constructor` 实例处理类。
|
||||
|
||||
若有多个 `Constructor` 结果只会返回第一个。
|
||||
|
||||
::: danger
|
||||
|
||||
若你设置了 **remedys** 请使用 **wait** 回调结果方法。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以通过获得方法所在实例来执行构造方法创建新的实例对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.get().call()
|
||||
```
|
||||
|
||||
你可以 `cast` 构造方法为指定类型的实例对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.get().newInstance<TestClass>()
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
若构造方法含有参数则后方参数必填。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.get().newInstance<TestClass>("param1", "param2")
|
||||
```
|
||||
|
||||
### all <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun all(): ArrayList<Instance>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Constructor` 实例处理类数组。
|
||||
|
||||
返回全部查询条件匹配的多个 `Constructor` 实例结果。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以通过此方法来获得当前条件结果中匹配的全部 `Constructor`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.all().forEach { instance ->
|
||||
instance.call(...)
|
||||
}
|
||||
```
|
||||
|
||||
### give <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun give(): Constructor<*>?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到 `Constructor` 本身。
|
||||
|
||||
若有多个 `Constructor` 结果只会返回第一个。
|
||||
|
||||
在查询条件找不到任何结果的时候将返回 `null`。
|
||||
|
||||
### giveAll <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun giveAll(): HashSet<Constructor<*>>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到 `Constructor` 本身数组。
|
||||
|
||||
返回全部查询条件匹配的多个 `Constructor` 实例。
|
||||
|
||||
在查询条件找不到任何结果的时候将返回空的 `HashSet`。
|
||||
|
||||
### wait <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun wait(initiate: Instance.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Constructor` 实例处理类,配合 `RemedyPlan` 使用。
|
||||
|
||||
若有多个 `Constructor` 结果只会返回第一个。
|
||||
|
||||
::: danger
|
||||
|
||||
若你设置了 **remedys** 必须使用此方法才能获得结果。
|
||||
|
||||
若你没有设置 **remedys** 此方法将不会被回调。
|
||||
|
||||
:::
|
||||
|
||||
### waitAll <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Constructor` 实例处理类数组,配合 `RemedyPlan` 使用。
|
||||
|
||||
返回全部查询条件匹配的多个 `Constructor` 实例结果。
|
||||
|
||||
::: danger
|
||||
|
||||
若你设置了 **remedys** 必须使用此方法才能获得结果。
|
||||
|
||||
若你没有设置 **remedys** 此方法将不会被回调。
|
||||
|
||||
:::
|
||||
|
||||
### remedys <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建 `Constructor` 重查找功能。
|
||||
|
||||
**功能示例**
|
||||
|
||||
当你遇到一种 `Constructor` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchConstructor` 捕获异常二次查找 `Constructor`。
|
||||
|
||||
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
constructor {
|
||||
// Your code here.
|
||||
}.remedys {
|
||||
constructor {
|
||||
// Your code here.
|
||||
}
|
||||
constructor {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### onNoSuchConstructor <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听找不到 `Constructor` 时。
|
||||
|
||||
只会返回第一次的错误信息,不会返回 `RemedyPlan` 的错误信息。
|
||||
|
||||
### ignored <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun ignored(): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 忽略异常并停止打印任何错误日志。
|
||||
|
||||
若 `isNotIgnoredHookingFailure` 为 `false` 则自动忽略。
|
||||
|
||||
::: warning
|
||||
|
||||
此时若要监听异常结果,你需要手动实现 **onNoSuchConstructor** 方法。
|
||||
|
||||
:::
|
||||
|
||||
<h3 class="deprecated">ignoredError - method</h3>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.3` `新增`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转移到新方法 `ignored()`
|
||||
|
||||
### Instance <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Instance internal constructor(private val constructor: Constructor<*>?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `constructor` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Constructor` 实例处理类。
|
||||
|
||||
#### call <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun call(vararg param: Any?): Any?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 执行 `Constructor` 创建目标实例,不指定目标实例类型。
|
||||
|
||||
#### newInstance <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> newInstance(vararg param: Any?): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 执行 `Constructor` 创建目标实例 ,指定 `T` 目标实例类型。
|
@@ -0,0 +1,919 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# FieldFinder <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.2` `修改`
|
||||
|
||||
合并到 `BaseFinder`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `MemberBaseFinder`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 查找类。
|
||||
|
||||
可通过指定类型查找指定 `Field` 或一组 `Field`。
|
||||
|
||||
<h2 class="deprecated">classSet - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.2` `移除`
|
||||
|
||||
## name <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var name: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.70` `修改`
|
||||
|
||||
允许不填写名称
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 名称。
|
||||
|
||||
::: danger
|
||||
|
||||
若不填写名称则必须存在一个其它条件。
|
||||
|
||||
:::
|
||||
|
||||
## type <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var type: Any?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 类型。
|
||||
|
||||
可不填写类型。
|
||||
|
||||
## modifiers <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `ModifierConditions`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 标识符筛选条件。
|
||||
|
||||
可不设置筛选条件。
|
||||
|
||||
::: danger
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## order <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun order(): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 顺序筛选字节码的下标。
|
||||
|
||||
## name <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun name(value: String): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 名称。
|
||||
|
||||
::: danger
|
||||
|
||||
若不填写名称则必须存在一个其它条件。
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## name <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun name(conditions: NameConditions): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `NameConditions`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 名称条件。
|
||||
|
||||
::: danger
|
||||
|
||||
若不填写名称则必须存在一个其它条件。
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## type <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun type(value: Any): IndexTypeCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 `Field` 类型。
|
||||
|
||||
::: danger
|
||||
|
||||
可不填写类型。
|
||||
|
||||
存在多个 **IndexTypeCondition** 时除了 **order** 只会生效最后一个。
|
||||
|
||||
:::
|
||||
|
||||
## superClass <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun superClass(isOnlySuperClass: Boolean)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置在 `classSet` 的所有父类中查找当前 `Field`。
|
||||
|
||||
::: warning
|
||||
|
||||
若当前 **classSet** 的父类较多可能会耗时,API 会自动循环到父类继承是 **Any** 前的最后一个类。
|
||||
|
||||
:::
|
||||
|
||||
## RemedyPlan <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class RemedyPlan internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 重查找实现类,可累计失败次数直到查找成功。
|
||||
|
||||
### field <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun field(initiate: FieldConditions): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建需要重新查找的 `Field`。
|
||||
|
||||
你可以添加多个备选 `Field`,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
|
||||
|
||||
### Result <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Result internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `RemedyPlan` 结果实现类。
|
||||
|
||||
#### onFind <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onFind(initiate: HashSet<Field>.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当在 `RemedyPlan` 中找到结果时。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以方便地对重查找的 `Field` 实现 `onFind` 方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.onFind {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## Result <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
继承到接口 `BaseResult`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 查找结果实现类。
|
||||
|
||||
### result <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun result(initiate: Result.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建监听结果事件方法体。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用 `lambda` 形式创建 `Result` 类。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.result {
|
||||
get(instance).set("something")
|
||||
get(instance).string()
|
||||
get(instance).cast<CustomClass>()
|
||||
get().boolean()
|
||||
all(instance)
|
||||
give()
|
||||
giveAll()
|
||||
onNoSuchField {}
|
||||
}
|
||||
```
|
||||
|
||||
### get <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun get(instance: Any?): Instance
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Field` 实例处理类。
|
||||
|
||||
若有多个 `Field` 结果只会返回第一个。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松地得到 `Field` 的实例以及使用它进行设置实例。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.get(instance).set("something")
|
||||
```
|
||||
|
||||
如果你取到的是静态 `Field`,可以不需要设置实例。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.get().set("something")
|
||||
```
|
||||
|
||||
### all <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun all(instance: Any?): ArrayList<Instance>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Field` 实例处理类数组。
|
||||
|
||||
返回全部查询条件匹配的多个 `Field` 实例结果。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以通过此方法来获得当前条件结果中匹配的全部 `Field`,其 `Field` 所在实例用法与 `get` 相同。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.all(instance).forEach { instance ->
|
||||
instance.self
|
||||
}
|
||||
```
|
||||
|
||||
### give <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun give(): Field?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到 `Field` 本身。
|
||||
|
||||
若有多个 Field 结果只会返回第一个。
|
||||
|
||||
在查询条件找不到任何结果的时候将返回 `null`。
|
||||
|
||||
### giveAll <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun giveAll(): HashSet<Field>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到 `Field` 本身数组。
|
||||
|
||||
返回全部查询条件匹配的多个 `Field` 实例。
|
||||
|
||||
在查询条件找不到任何结果的时候将返回空的 `HashSet`。
|
||||
|
||||
### wait <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun wait(instance: Any?, initiate: Instance.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Field` 实例处理类,配合 `RemedyPlan` 使用。
|
||||
|
||||
若有多个 `Field` 结果只会返回第一个。
|
||||
|
||||
::: danger
|
||||
|
||||
若你设置了 **remedys** 必须使用此方法才能获得结果。
|
||||
|
||||
若你没有设置 **remedys** 此方法将不会被回调。
|
||||
|
||||
:::
|
||||
|
||||
### waitAll <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得 `Field` 实例处理类数组,配合 `RemedyPlan` 使用。
|
||||
|
||||
返回全部查询条件匹配的多个 `Field` 实例结果。
|
||||
|
||||
::: danger
|
||||
|
||||
若你设置了 **remedys** 必须使用此方法才能获得结果。
|
||||
|
||||
若你没有设置 **remedys** 此方法将不会被回调。
|
||||
|
||||
:::
|
||||
|
||||
### remedys <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建 `Field` 重查找功能。
|
||||
|
||||
**功能示例**
|
||||
|
||||
当你遇到一种 `Field` 可能存在不同形式的存在时,可以使用 `RemedyPlan` 重新查找它,而没有必要使用 `onNoSuchField` 捕获异常二次查找 `Field`。
|
||||
|
||||
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
field {
|
||||
// Your code here.
|
||||
}.remedys {
|
||||
field {
|
||||
// Your code here.
|
||||
}
|
||||
field {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### onNoSuchField <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onNoSuchField(result: (Throwable) -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听找不到 `Field` 时。
|
||||
|
||||
### ignored <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun ignored(): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 忽略异常并停止打印任何错误日志。
|
||||
|
||||
若 `isNotIgnoredHookingFailure` 为 `false` 则自动忽略。
|
||||
|
||||
::: warning
|
||||
|
||||
此时若要监听异常结果,你需要手动实现 **onNoSuchField** 方法。
|
||||
|
||||
:::
|
||||
|
||||
<h3 class="deprecated">ignoredError - method</h3>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.3` `新增`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转移到新方法 `ignored()`
|
||||
|
||||
### Instance <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `field` 参数
|
||||
|
||||
不再对外公开 `self` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `Field` 实例变量处理类。
|
||||
|
||||
<h4 class="deprecated">self - field</h4>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `移除`
|
||||
|
||||
请直接使用 `any` 方法得到 `Field` 自身的实例化对象
|
||||
|
||||
#### current <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun current(ignored: Boolean): CurrentClass?
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 `Field` 自身 `self` 实例的类操作对象 `CurrentClass`。
|
||||
|
||||
#### cast <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> cast(): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`of`~~ 为 `cast`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` 实例。
|
||||
|
||||
#### byte <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun byte(): Byte?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Byte 实例。
|
||||
|
||||
#### int <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun int(): Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofInt`~~ 为 `int`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Int 实例。
|
||||
|
||||
#### long <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun long(): Long
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofLong`~~ 为 `long`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Long 实例。
|
||||
|
||||
#### short <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun short(): Short
|
||||
```
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofShort`~~ 为 `short`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Short 实例。
|
||||
|
||||
#### double <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun double(): Double
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofDouble`~~ 为 `double`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Double 实例。
|
||||
|
||||
#### float <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun float(): Float
|
||||
```
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofFloat`~~ 为 `float`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Float 实例。
|
||||
|
||||
#### string <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun string(): String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofString`~~ 为 `string`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` String 实例。
|
||||
|
||||
#### char <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun char(): Char
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Char 实例。
|
||||
|
||||
#### boolean <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun boolean(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofBoolean`~~ 为 `boolean`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Boolean 实例。
|
||||
|
||||
#### any <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun any(): Any?
|
||||
```
|
||||
**变更记录**
|
||||
|
||||
`v1.0.65` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofAny`~~ 为 `any`
|
||||
|
||||
移动方法到 `Instance`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Any 实例。
|
||||
|
||||
#### array <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> array(): Array<T>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` Array 实例。
|
||||
|
||||
#### list <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> list(): List<T>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到当前 `Field` List 实例。
|
||||
|
||||
#### set <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun set(any: Any?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 `Field` 实例。
|
||||
|
||||
#### setTrue <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setTrue()
|
||||
```
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 `Field` 实例为 `true`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保实例对象类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
#### setFalse <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setFalse()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 `Field` 实例为 `false`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保实例对象类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
#### setNull <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setNull()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 `Field` 实例为 `null`。
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiBaseHooker <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
abstract class YukiBaseHooker : PackageParam()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `YukiHookAPI` 的子类 Hooker 实现。
|
||||
|
||||
## onHook <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onHook()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 子类 Hook 开始。
|
@@ -0,0 +1,661 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ReflectionFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是自定义 `Member` 和 `Class` 相关功能的查找匹配以及 `invoke` 的封装类。
|
||||
|
||||
## MembersType <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
enum class MembersType
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 定义一个 `Class` 中的 `Member` 类型
|
||||
|
||||
### ALL <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
ALL
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 全部 `Method` 与 `Constructor`。
|
||||
|
||||
### METHOD <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
METHOD
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 全部 `Method`。
|
||||
|
||||
### CONSTRUCTOR <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
CONSTRUCTOR
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 全部 `Constructor`。
|
||||
|
||||
## ClassLoader.onLoadClass <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 `ClassLoader` 的 `ClassLoader.loadClass` 方法装载。
|
||||
|
||||
::: danger
|
||||
|
||||
只有当前 **ClassLoader** 有主动使用 **ClassLoader.loadClass** 事件时才能被捕获。
|
||||
|
||||
这是一个实验性功能,一般情况下不会用到此方法,不保证不会发生错误。
|
||||
|
||||
只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
针对一些使用特定 `ClassLoader` 装载 `Class` 的宿主应用,你可以使用此方法来监听 `Class` 加载情况。
|
||||
|
||||
::: warning
|
||||
|
||||
为了防止发生问题,你需要<u>**得到一个存在的 ClassLoader 实例**</u>来使用此功能。
|
||||
|
||||
:::
|
||||
|
||||
比如我们在 `PackageParam` 中使用 `appClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
appClassLoader.onLoadClass { clazz ->
|
||||
// 得到 clazz 即加载对象
|
||||
clazz... // 这里进行你需要的操作
|
||||
}
|
||||
```
|
||||
|
||||
或使用你得到的存在的 `ClassLoader` 实例,可以通过 Hook 获取。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
customClassLoader?.onLoadClass { clazz ->
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
在判断到这个 `Class` 被装载成功时,开始执行你的 Hook 功能。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
customClassLoader?.onLoadClass { clazz ->
|
||||
if(clazz.name == /** 你需要的 Class 名称 */) {
|
||||
clazz.hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<h2 class="deprecated">hookClass - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `移除`
|
||||
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
<h2 class="deprecated">normalClass - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `移除`
|
||||
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
<h2 class="deprecated">hasClass - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `移除`
|
||||
|
||||
请直接使用 `hasClass()` 无参方法
|
||||
|
||||
## Class.hasExtends <span class="symbol">- ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val Class<*>.hasExtends: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当前 `Class` 是否有继承关系,父类是 `Any` 将被认为没有继承关系。
|
||||
|
||||
<h2 class="deprecated">classOf - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转到 `toClass(...)` 方法
|
||||
|
||||
## String.toClass <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.toClass(loader: ClassLoader?): Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过字符串类名转换为 `loader` 中的实体类。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以直接填写你要查找的目标 `Class`,必须在默认 `ClassLoader` 下存在。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
```
|
||||
|
||||
你还可以自定义 `Class` 所在的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
"com.example.demo.DemoClass".toClass(customClassLoader)
|
||||
```
|
||||
|
||||
## classOf <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过 `T` 得到其 `Class` 实例并转换为实体类。
|
||||
|
||||
**功能示例**
|
||||
|
||||
我们要获取一个 `Class` 在 `Kotlin` 下不通过反射时应该这样做。
|
||||
|
||||
> 示例如下
|
||||
>
|
||||
```kotlin
|
||||
DemoClass::class.java
|
||||
```
|
||||
|
||||
现在,你可以直接 `cast` 一个实例并获取它的 `Class` 对象,必须在当前 `ClassLoader` 下存在。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
classOf<DemoClass>()
|
||||
```
|
||||
|
||||
若目标存在的 `Class` 为 `stub`,通过这种方式,你还可以自定义 `Class` 所在的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
classOf<DemoClass>(customClassLoader)
|
||||
```
|
||||
|
||||
## String.hasClass <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.hasClass(loader: ClassLoader?): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
支持直接使用空参数方法使用默认 `ClassLoader` 进行判断
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过字符串类名使用指定的 `ClassLoader` 查找是否存在。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 `Class.forName`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if("com.example.demo.DemoClass".hasClass()) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
填入方法中的 `loader` 参数可判断指定的 `ClassLoader` 中的 `Class` 是否存在。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## Class.hasField <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.4` `新增`
|
||||
|
||||
`v1.0.67` `修改`
|
||||
|
||||
合并到 `FieldFinder`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找变量是否存在。
|
||||
|
||||
## Class.hasMethod <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
新增 `returnType` 参数
|
||||
|
||||
`v1.0.67` `修改`
|
||||
|
||||
合并到 `MethodFinder`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找方法是否存在。
|
||||
|
||||
## Class.hasConstructor <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
`v1.0.67` `修改`
|
||||
|
||||
合并到 `ConstructorFinder`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找构造方法是否存在。
|
||||
|
||||
## Member.hasModifiers <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
合并到 `ModifierConditions`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查询 `Member` 中匹配的描述符。
|
||||
|
||||
## Class.hasModifiers <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查询 `Class` 中匹配的描述符。
|
||||
|
||||
<h2 class="deprecated">obtainStaticFieldAny - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `移除`
|
||||
|
||||
<h2 class="deprecated">obtainFieldAny - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `移除`
|
||||
|
||||
<h2 class="deprecated">modifyStaticField - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `移除`
|
||||
|
||||
<h2 class="deprecated">modifyField - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `移除`
|
||||
|
||||
## Class.field <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.2` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找并得到变量。
|
||||
|
||||
## Class.method <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
~~`obtainMethod`~~ 更名为 `method`
|
||||
|
||||
新增 `returnType` 参数
|
||||
|
||||
`v1.0.2` `修改`
|
||||
|
||||
合并到 `MethodFinder` 方法体
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找并得到方法。
|
||||
|
||||
## Class.constructor <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
~~`obtainConstructor`~~ 更名为 `constructor`
|
||||
|
||||
`v1.0.2` `修改`
|
||||
|
||||
合并到 `ConstructorFinder` 方法体
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找并得到构造方法。
|
||||
|
||||
<h2 class="deprecated">callStatic - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
~~`invokeStatic`~~ 更名为 `callStatic`
|
||||
|
||||
`v1.0.2` `移除`
|
||||
|
||||
<h2 class="deprecated">call - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
~~`invokeAny`~~ 更名为 `call`
|
||||
|
||||
`v1.0.2` `移除`
|
||||
|
||||
## Any.current <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
新增 `ignored` 参数,可以忽略在 `CurrentClass` 中出现的异常
|
||||
|
||||
新增不使用 `current { ... }` 调用域直接使用 `current()` 得到实例的类操作对象
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前实例的类操作对象。
|
||||
|
||||
<h2 class="deprecated">Class.buildOfAny - ext-method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转移到 `buildOf` 方法
|
||||
|
||||
## Class.buildOf <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): Any?
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <T> Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
加入无泛型方法 `buildOf`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过构造方法创建新实例,指定类型 `T` 或任意类型 `Any`。
|
||||
|
||||
## Class.allMethods <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 遍历当前类中的所有方法。
|
||||
|
||||
## Class.allConstructors <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 遍历当前类中的所有构造方法。
|
||||
|
||||
## Class.allFields <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 遍历当前类中的所有变量。
|
@@ -0,0 +1,241 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiHookFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
合并到 `IYukiHookXposedInit`,将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是 `YukiHookAPI` 相关 `lambda` 方法的封装类以及部分 API 用法。
|
||||
|
||||
## IYukiHookXposedInit.configs <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.1` `新增`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
合并到 `IYukiHookXposedInit`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 在 `IYukiHookXposedInit` 中配置 `Configs`。
|
||||
|
||||
## IYukiHookXposedInit.encase <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
合并到 `IYukiHookXposedInit`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 在 `IYukiHookXposedInit` 中调用 `YukiHookAPI`。
|
||||
|
||||
## Context.modulePrefs <span class="symbol">- ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val Context.modulePrefs: YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取模块的存取对象。
|
||||
|
||||
## Context.modulePrefs <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Context.modulePrefs(name: String): YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取模块的存取对象,可设置 `name` 为自定义 Sp 存储名称。
|
||||
|
||||
## Context.dataChannel <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取模块的数据通讯桥命名空间对象。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在模块环境使用此功能,其它环境下使用将不起作用。
|
||||
|
||||
:::
|
||||
|
||||
## Context.processName <span class="symbol">- ext-field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val Context.processName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前进程名称。
|
||||
|
||||
## Context+Resources.injectModuleAppResources <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Context.injectModuleAppResources()
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Resources.injectModuleAppResources()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 Hook APP (宿主) `Context` 或 `Resources` 注入当前 Xposed 模块的资源。
|
||||
|
||||
注入成功后,你就可以直接使用例如 `ImageView.setImageResource` 或 `Resources.getString` 装载当前 Xposed 模块的资源 ID。
|
||||
|
||||
注入的资源作用域仅限当前 `Context` 或 `Resources`,你需要在每个用到宿主 `Context` 或 `Resources` 的地方重复调用此方法进行注入才能使用。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。
|
||||
|
||||
:::
|
||||
|
||||
## Context.registerModuleAppActivities <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Context.registerModuleAppActivities(proxy: Any?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 Hook APP (宿主) 注册当前 Xposed 模块的 `Activity`。
|
||||
|
||||
注册成功后,你就可以直接使用 `Context.startActivity` 来启动未在宿主中注册的 `Activity`。
|
||||
|
||||
使用此方法会在未注册的 `Activity` 在 Hook APP (宿主) 中启动时自动调用 `injectModuleAppResources` 注入当前 Xposed 模块的资源。
|
||||
|
||||
你要将需要在宿主启动的 `Activity` 继承于 `ModuleAppActivity` 或 `ModuleAppCompatActivity`。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。
|
||||
|
||||
:::
|
||||
|
||||
## Context.applyModuleTheme <span class="symbol">- ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 生成一个 `ContextThemeWrapper` 代理以应用当前 Xposed 模块的主题资源。
|
||||
|
||||
在 Hook APP (宿主) 中使用此方法会自动调用 `injectModuleAppResources` 注入当前 Xposed 模块的资源。
|
||||
|
||||
如果在 Hook APP (宿主) 中使用此方法发生 `ClassCastException`,请手动设置 `configuration`。
|
||||
|
||||
<h2 class="deprecated">isSupportResourcesHook - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `YukiHookAPI.Status.isSupportResourcesHook`
|
||||
|
||||
<h2 class="deprecated">isModuleActive - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.6` `新增`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `YukiHookAPI.Status.isModuleActive`
|
||||
|
||||
<h2 class="deprecated">isXposedModuleActive - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.6` `新增`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `YukiHookAPI.Status.isXposedModuleActive`
|
||||
|
||||
<h2 class="deprecated">isTaiChiModuleActive - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.91` `移除`
|
||||
|
||||
请转移到 `YukiHookAPI.Status.isTaiChiModuleActive`
|
||||
|
||||
<h1 class="deprecated">YukiHookModuleStatus - class</h1>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.91` `作废`
|
||||
|
||||
请转移到 `YukiHookAPI.Status`
|
@@ -0,0 +1,179 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# LoggerFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是 `YukiHookAPI` 的日志封装类,可实现同时向 `Logcat` 和 `XposedBridge.log` 打印日志的功能。
|
||||
|
||||
## LoggerType <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
enum class LoggerType
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 需要打印的日志类型。
|
||||
|
||||
决定于模块与 (Xposed) 宿主环境使用的打印方式。
|
||||
|
||||
### LOGD <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
LOGD
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅使用 `android.util.Log`。
|
||||
|
||||
### XPOSEDBRIDGE <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
XPOSEDBRIDGE
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅使用 `XposedBridge.log`。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在 (Xposed) 宿主环境中使用,模块环境将不生效。
|
||||
|
||||
:::
|
||||
|
||||
### SCOPE <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
SCOPE
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 分区使用。
|
||||
|
||||
(Xposed) 宿主环境仅使用 `XPOSEDBRIDGE`。
|
||||
|
||||
模块环境仅使用 `LOGD`。
|
||||
|
||||
### BOTH <span class="symbol">- enum</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
BOTH
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 同时使用。
|
||||
|
||||
(Xposed) 宿主环境使用 `LOGD` 与 `XPOSEDBRIDGE`。
|
||||
|
||||
模块环境仅使用 `LOGD`。
|
||||
|
||||
## loggerD <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loggerD(tag: String, msg: String, type: LoggerType)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `type` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 `Logcat` 和 `XposedBridge` 打印日志,级别 `D`。
|
||||
|
||||
`tag` 的默认参数为 `YukiHookAPI.Configs.debugTag`,你可以进行自定义。
|
||||
|
||||
## loggerI <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loggerI(tag: String, msg: String, type: LoggerType)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `type` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 `Logcat` 和 `XposedBridge` 打印日志,级别 `I`。
|
||||
|
||||
`tag` 的默认参数为 `YukiHookAPI.Configs.debugTag`,你可以进行自定义。
|
||||
|
||||
## loggerW <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loggerW(tag: String, msg: String, type: LoggerType)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `type` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 `Logcat` 和 `XposedBridge` 打印日志,级别 `W`。
|
||||
|
||||
`tag` 的默认参数为 `YukiHookAPI.Configs.debugTag`,你可以进行自定义。
|
||||
|
||||
## loggerE <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `type` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 `Logcat` 和 `XposedBridge` 打印日志,级别 `E`,可携带 `e` 异常信息,将打印异常堆栈。
|
||||
|
||||
`tag` 的默认参数为 `YukiHookAPI.Configs.debugTag`,你可以进行自定义。
|
@@ -0,0 +1,878 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# HookParam <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
移动 `HookParamWrapper` 到 `YukiHookCallback.Param`
|
||||
|
||||
修正拼写错误的 **creater** 命名到 **creator**
|
||||
|
||||
**功能描述**
|
||||
|
||||
> Hook 方法、构造方法的目标对象实现类。
|
||||
|
||||
## args <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val args: Array<Any?>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
在 `v1.0` 添加
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象 `member` 或 `constructor` 的参数对象数组。
|
||||
|
||||
这里的数组每项类型默认为 `Any`,你可以使用 `args` 方法来实现 `ArgsModifyer.cast` 功能。
|
||||
|
||||
<h2 class="deprecated">firstArgs - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.75` `移除`
|
||||
|
||||
请使用 `args(index = 0)` 或 `args().first()`
|
||||
|
||||
<h2 class="deprecated">lastArgs - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.75` `移除`
|
||||
|
||||
请使用 `args().last()`
|
||||
|
||||
## instance <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val instance: Any
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 实例的对象。
|
||||
|
||||
::: danger
|
||||
|
||||
如果你当前 Hook 的对象是一个静态,那么它将不存在实例的对象。
|
||||
|
||||
:::
|
||||
|
||||
## instanceClass <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val instanceClass: Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 实例的类对象。
|
||||
|
||||
## member <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val member: Member
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `Member`。
|
||||
|
||||
在不确定 `Member` 类型为 `Method` 或 `Constructor` 时可以使用此方法。
|
||||
|
||||
## method <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val method: Method
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的方法。
|
||||
|
||||
## constructor <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val constructor: Constructor
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的构造方法。
|
||||
|
||||
## result <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
var result: Any?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取、设置当前 Hook 对象的 `method` 或 `constructor` 的返回值。
|
||||
|
||||
## hasThrowable <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val hasThrowable: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 判断是否存在设置过的方法调用抛出异常。
|
||||
|
||||
## throwable <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val throwable: Throwable?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取设置的方法调用抛出异常。
|
||||
|
||||
## Throwable.throwToApp <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun Throwable.throwToApp()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 向 Hook APP 抛出异常。
|
||||
|
||||
使用 `hasThrowable` 判断当前是否存在被抛出的异常。
|
||||
|
||||
使用 `throwable` 获取当前设置的方法调用抛出异常。
|
||||
|
||||
仅会在回调方法的 `MemberHookCreator.beforeHook` or `MemberHookCreator.afterHook` 中生效。
|
||||
|
||||
::: danger
|
||||
|
||||
设置后会同时执行 **resultNull** 方法并将异常抛出给当前 Hook APP。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
Hook 过程中的异常仅会作用于 (Xposed) 宿主环境,目标 Hook APP 不会受到影响。
|
||||
|
||||
若想将异常抛给 Hook APP,可以直接使用如下方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
beforeHook {
|
||||
RuntimeException("Test Exception").throwToApp()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
向 Hook APP 抛出异常<u>**会对其暴露被 Hook 的事实**</u>,是不安全的,容易被检测,请按实际场景合理使用。
|
||||
|
||||
:::
|
||||
|
||||
## result <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> result(): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `method` 或 `constructor` 的返回值 `T`。
|
||||
|
||||
<h2 class="deprecated">firstArg - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.75` `移除`
|
||||
|
||||
<h2 class="deprecated">lastArgs - method</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.75` `移除`
|
||||
|
||||
## instance <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> instance(): T
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 实例的对象 `T`。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以通过 `instance` 方法轻松使用泛型 `cast` 为目标对象的类型。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
instance<Activity>().finish()
|
||||
```
|
||||
|
||||
## args <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun args(): ArgsIndexCondition
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `method` or `constructor` 的参数数组下标实例化类。
|
||||
|
||||
## args <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun args(index: Int): ArgsModifyer
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.75` `修改`
|
||||
|
||||
默认值 `index = 0` 移动到新的使用方法 `args().first()`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `method` 或 `constructor` 的参数实例化对象类。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以通过 `args` 方法修改当前 Hook 实例的方法、构造方法的参数内容。
|
||||
|
||||
你可以直接使用 `set` 方法设置 `param` 为你的目标实例,接受 `Any` 类型。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保 **param** 类型为你的目标实例类型。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args(index = 0).set("modify the value")
|
||||
```
|
||||
|
||||
你可以这样直接设置第一位 `param` 的值。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args().first().set("modify the value")
|
||||
```
|
||||
|
||||
你还可以直接设置最后一位 `param` 的值。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args().last().set("modify the value")
|
||||
```
|
||||
|
||||
你还可以使用 `setNull` 方法设置 `param` 为空。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args(index = 1).setNull()
|
||||
```
|
||||
|
||||
你还可以使用 `setTrue` 方法设置 `param` 为 `true`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保 **param** 类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args(index = 1).setTrue()
|
||||
```
|
||||
|
||||
你还可以使用 `setFalse` 方法设置 `param` 为 `false`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保 **param** 类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
args(index = 1).setFalse()
|
||||
```
|
||||
|
||||
## callOriginal <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun callOriginal(): Any?
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> callOriginal(): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 执行原始 `Member`。
|
||||
|
||||
调用自身未进行 Hook 的原始 `Member` 并调用原始参数执行。
|
||||
|
||||
**功能实例**
|
||||
|
||||
此方法可以 `invoke` 原始未经 Hook 的 `Member` 对象,取决于原始 `Member` 的参数。
|
||||
|
||||
调用自身原始的方法不会再经过当前 `beforeHook`、`afterHook` 以及 `replaceUnit`、`replaceAny`。
|
||||
|
||||
比如我们 Hook 的这个方法被这样调用 `test("test value")`,使用此方法会调用其中的 `"test value"` 作为参数。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(StringType)
|
||||
returnType = StringType
|
||||
}
|
||||
afterHook {
|
||||
// <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参
|
||||
callOriginal()
|
||||
// <方案2> 使用泛型,已知方法执行结果参数类型进行 cast
|
||||
// 假设返回值为 String,失败会返回 null,调用将使用原方法传入的 args 自动传参
|
||||
val value = callOriginal<String>()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## invokeOriginal <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun invokeOriginal(vararg args: Any?): Any?
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> invokeOriginal(vararg args: Any?): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
不再需要使用 `member.invokeOriginal` 进行调用
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 执行原始 `Member`。
|
||||
|
||||
调用自身未进行 Hook 的原始 `Member` 并自定义 `args` 执行。
|
||||
|
||||
**功能实例**
|
||||
|
||||
此方法可以 `invoke` 原始未经 Hook 的 `Member` 对象,可自定义需要调用的参数内容。
|
||||
|
||||
调用自身原始的方法不会再经过当前 `beforeHook`、`afterHook` 以及 `replaceUnit`、`replaceAny`。
|
||||
|
||||
比如我们 Hook 的这个方法被这样调用 `test("test value")`,使用此方法可自定义其中的 `args` 作为参数。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(StringType)
|
||||
returnType = StringType
|
||||
}
|
||||
afterHook {
|
||||
// <方案1> 不使用泛型,不获取方法执行结果
|
||||
invokeOriginal("test value")
|
||||
// <方案2> 使用泛型,已知方法执行结果参数类型进行 cast,假设返回值为 String,失败会返回 null
|
||||
val value = invokeOriginal<String>("test value")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## resultTrue <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun resultTrue()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 Hook 对象方法的 `result` 返回值为 `true`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保 **result** 类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
## resultFalse <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun resultFalse()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 Hook 对象方法的 `result` 返回值为 `false`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保 **result** 类型为 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
## resultNull <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun resultNull()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
::: warning
|
||||
|
||||
此方法将强制设置 Hook 对象方法的 **result** 为 **null**。
|
||||
|
||||
:::
|
||||
|
||||
## ArgsIndexCondition <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class ArgsIndexCondition internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对方法参数的数组下标进行实例化类。
|
||||
|
||||
### first <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun first(): ArgsModifyer
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `method` or `constructor` 的参数数组第一位。
|
||||
|
||||
### last <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun last(): ArgsModifyer
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.75` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook 对象的 `method` or `constructor` 的参数数组最后一位。
|
||||
|
||||
## ArgsModifyer <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class ArgsModifyer internal constructor(private val index: Int)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对方法参数的修改进行实例化类。
|
||||
|
||||
### cast <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> cast(): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`of`~~ 为 `cast`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 `T`。
|
||||
|
||||
### byte <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun byte(): Byte?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Byte。
|
||||
|
||||
### int <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun int(): Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofInt`~~ 为 `int`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Int。
|
||||
|
||||
### long <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun long(): Long
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofLong`~~ 为 `long`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Long。
|
||||
|
||||
### short <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun short(): Short
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofShort`~~ 为 `short`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Short。
|
||||
|
||||
### double <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun double(): Double
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofDouble`~~ 为 `double`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Double。
|
||||
|
||||
### float <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun float(): Float
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofFloat`~~ 为 `float`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Float。
|
||||
|
||||
### string <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun string(): String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofString`~~ 为 `string`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 String。
|
||||
|
||||
### char <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun char(): Char
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Char。
|
||||
|
||||
### boolean <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun boolean(): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.66` `新增`
|
||||
|
||||
`v1.0.68` `修改`
|
||||
|
||||
修改 ~~`ofBoolean`~~ 为 `boolean`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Boolean。
|
||||
|
||||
### any <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun any(): Any?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Any。
|
||||
|
||||
### array <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> array(): Array<T>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 Array。
|
||||
|
||||
### list <span class="symbol">- method</span>
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> list(): List<T>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.68` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到方法参数的实例对象 List。
|
||||
|
||||
### set <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> set(any: T?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置方法参数的实例对象。
|
||||
|
||||
### setNull <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setNull()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置方法参数的实例对象为 `null`。
|
||||
|
||||
### setTrue <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setTrue()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置方法参数的实例对象为 `true`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保目标对象的类型是 **Boolean**。
|
||||
|
||||
:::
|
||||
|
||||
### setFalse <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun setFalse()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置方法参数的实例对象为 `false`。
|
||||
|
||||
::: danger
|
||||
|
||||
请确保目标对象的类型是 **Boolean**。
|
||||
|
||||
:::
|
@@ -0,0 +1,938 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# PackageParam <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载 Hook 的目标 APP 入口对象实现类。
|
||||
|
||||
## appClassLoader <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appClassLoader:ClassLoader
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的 `ClassLoader`。
|
||||
|
||||
## appInfo <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appInfo: ApplicationInfo
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的 `ApplicationInfo`。
|
||||
|
||||
## appUserId <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appUserId: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的用户 ID。
|
||||
|
||||
机主为 `0`,应用双开 (分身) 或工作资料因系统环境不同 ID 也各不相同。
|
||||
|
||||
## appContext <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appContext: Application?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.72` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
加入可空类型 (空安全)
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的 `Application`。
|
||||
|
||||
::: danger
|
||||
|
||||
首次装载可能是空的,请延迟一段时间再获取或使用 **onAppLifecycle** 监听来完成。
|
||||
|
||||
:::
|
||||
|
||||
## appResources <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appResources:Resources?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
加入可空类型 (空安全)
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的 Resources。
|
||||
|
||||
::: danger
|
||||
|
||||
你只能在 **HookResources.hook** 方法体内或 **appContext** 装载完毕时进行调用。
|
||||
|
||||
:::
|
||||
|
||||
## systemContext <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val systemContext: Context
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前系统框架的 `Context`。
|
||||
|
||||
## processName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val processName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的进程名称。
|
||||
|
||||
## packageName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val packageName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的包名。
|
||||
|
||||
## isFirstApplication <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isFirstApplication: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 是否为第一个 `Application`。
|
||||
|
||||
## mainProcessName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val mainProcessName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Hook APP 的主进程名称。
|
||||
|
||||
其对应的就是 `packageName`。
|
||||
|
||||
## moduleAppFilePath <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val moduleAppFilePath: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Xposed 模块自身 APK 文件路径。
|
||||
|
||||
::: danger
|
||||
|
||||
作为 Hook API 装载时无法使用,会获取到空字符串。
|
||||
|
||||
:::
|
||||
|
||||
## moduleAppResources <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val moduleAppResources: YukiModuleResources
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前 Xposed 模块自身 `Resources`。
|
||||
|
||||
::: danger
|
||||
|
||||
作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。
|
||||
|
||||
:::
|
||||
|
||||
## prefs <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val prefs: YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前使用的存取数据对象缓存实例。
|
||||
|
||||
::: danger
|
||||
|
||||
作为 Hook API 装载时无法使用,会抛出异常。
|
||||
|
||||
:::
|
||||
|
||||
## prefs <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun prefs(name: String): YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前使用的存取数据对象缓存实例。
|
||||
|
||||
你可以通过 `name` 来自定义 Sp 存储的名称。
|
||||
|
||||
::: danger
|
||||
|
||||
作为 Hook API 装载时无法使用,会抛出异常。
|
||||
|
||||
:::
|
||||
|
||||
## dataChannel <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val dataChannel: YukiHookDataChannel.NameSpace
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前使用的数据通讯桥命名空间对象。
|
||||
|
||||
::: danger
|
||||
|
||||
作为 Hook API 装载时无法使用,会抛出异常。
|
||||
|
||||
:::
|
||||
|
||||
## resources <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun resources(): HookResources
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 Hook APP 的 `YukiResources` 对象。
|
||||
|
||||
请调用 `HookResources.hook` 方法开始 Hook。
|
||||
|
||||
## refreshModuleAppResources <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun refreshModuleAppResources()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.87` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 刷新当前 Xposed 模块自身 `Resources`。
|
||||
|
||||
## onAppLifecycle <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 生命周期装载事件。
|
||||
|
||||
::: warning
|
||||
|
||||
在 **loadZygote** 中不会被装载,仅会在 **loadSystem**、**loadApp** 中装载。
|
||||
|
||||
作为 Hook API 装载时请使用原生的 **Application** 实现生命周期监听。
|
||||
|
||||
:::
|
||||
|
||||
## loadApp <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loadApp(name: String, hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载并 Hook 指定包名的 APP。
|
||||
|
||||
`name` 为 APP 的包名,后方的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||
|
||||
装载并 Hook 指定、全部包名的 APP。
|
||||
|
||||
若要装载 APP Zygote 事件,请使用 `loadZygote`。
|
||||
|
||||
若要 Hook 系统框架,请使用 `loadSystem`。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用 `loadApp` 的 `lambda` 方法体形式或直接装载一个 Hooker。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 使用 lambda
|
||||
loadApp(name = "com.example.test") {
|
||||
// Your code here.
|
||||
}
|
||||
// 使用 Hooker
|
||||
loadApp(name = "com.example.test", CustomHooker)
|
||||
```
|
||||
|
||||
若不指定 `name` 参数,则此方法体默认会过滤当前系统中全部可被 Hook 的 APP。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 使用 lambda
|
||||
loadApp {
|
||||
// Your code here.
|
||||
}
|
||||
// 使用 Hooker
|
||||
loadApp(hooker = CustomHooker)
|
||||
```
|
||||
|
||||
## loadZygote <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun loadZygote(initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loadZygote(hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载 APP Zygote 事件。
|
||||
|
||||
方法中的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||
|
||||
## loadSystem <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun loadSystem(initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loadSystem(hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.82` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载并 Hook 系统框架。
|
||||
|
||||
方法中的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||
|
||||
## withProcess <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun withProcess(name: String, hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.70` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载并 Hook APP 的指定进程。
|
||||
|
||||
`name` 为 APP 的进程名称,后方的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||
|
||||
## loadHooker <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun loadHooker(hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载 Hook 子类。
|
||||
|
||||
你可以填入 `hooker` 在 Hooker 中继续装载 Hooker。
|
||||
|
||||
<h2 class="deprecated">String+VariousClass.clazz - i-ext-field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转移到 `toClass(...)` 方法
|
||||
|
||||
<h2 class="deprecated">String.hasClass - i-ext-field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
请转移到 `hasClass(...)` 方法
|
||||
|
||||
## String+VariousClass.toClass <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.toClass(loader: ClassLoader?): Class<*>
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun VariousClass.toClass(loader: ClassLoader?): Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过字符串类名、`VariousClass` 转换为 `loader` 中的实体类。
|
||||
|
||||
默认使用当前 `appClassLoader` 装载目标 `Class`。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松地将 `String` 类型的 `Class` 包名转为 `Class` 实例。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
```
|
||||
|
||||
你还可以向 `loader` 参数传入你自定义的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
"com.example.demo.DemoClass".toClass(customClassLoader)
|
||||
```
|
||||
|
||||
你还可以创建一个 `VariousClass`,并转换为实体类。
|
||||
|
||||
`VariousClass` 会枚举所有设置的 `Class` 并最终获得第一个存在的 `Class`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
|
||||
```
|
||||
|
||||
同样地,你还可以向 `loader` 参数传入你自定义的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
|
||||
```
|
||||
|
||||
## String.hasClass <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun String.hasClass(loader: ClassLoader?): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过字符串类名查找是否存在。
|
||||
|
||||
默认使用当前 `appClassLoader` 装载目标 `Class`。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松的使用此方法判断字符串中的类是否存在。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if("com.example.demo.DemoClass".hasClass()) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
你还可以自定义其中的 `loader` 参数,默认为 `appClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## findClass <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun findClass(name: String, loader: ClassLoader?): HookClass
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
移除了 ~~`findClass(various: VariousClass)`~~ 方法
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
新增 `loader` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过完整包名+名称查找需要被 Hook 的 `Class`。
|
||||
|
||||
::: warning
|
||||
|
||||
使用此方法会得到一个 **HookClass** 仅用于 Hook,若想查找 **Class** 请使用 [toClass](#string-variousclass-toclass-i-ext-method) 功能。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用三种方式查找你需要 Hook 的目标 `Class`。
|
||||
|
||||
你可以直接将被查找的 `Class` 完整包名+名称填入 `name` 中。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass(name = "com.example.demo.DemoClass")
|
||||
```
|
||||
|
||||
若你不确定多个版本的 `Class` 以及不同名称,你可以将多个完整包名+名称填入 `name` 中。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
|
||||
```
|
||||
|
||||
你还可以创建一个 `VariousClass`,将 `Class` 的完整包名+名称填入 `VariousClass` 的 `name` 中并填入 `various` 参数中。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
|
||||
```
|
||||
|
||||
若你当前需要查找的 `Class` 不属于 `appClassLoader`,你可以使用 `loader` 参数指定你要装载的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
|
||||
findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
|
||||
```
|
||||
|
||||
同样地,在不确定多个版本的 `Class` 以及不同名称时,也可以使用 `loader` 参数指定你要装载的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
|
||||
findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
|
||||
```
|
||||
|
||||
## String+Class+VariousClass+HookClass.hook <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun String.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun Class<*>.hook(isForceUseAbsolute: Boolean, initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun VariousClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun HookClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.1` `修改`
|
||||
|
||||
新增 `VariousClass` 的直接调用 `hook` 方法
|
||||
|
||||
`v1.0.2` `修改`
|
||||
|
||||
新增 `String` 的直接调用 `hook` 方法
|
||||
|
||||
`v1.0.3` `修改`
|
||||
|
||||
新增 `YukiMemberHookCreator.Result` 返回值
|
||||
|
||||
`v1.0.70` `修改`
|
||||
|
||||
新增 `isUseAppClassLoader` 参数
|
||||
|
||||
`v1.0.80` `修改`
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.1.0` `修改`
|
||||
|
||||
移除了 ~~`isUseAppClassLoader`~~ 参数
|
||||
|
||||
添加了 `isForceUseAbsolute` 参数到 `Class.hook` 方法
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一切 Hook 的入口创建方法,Hook 方法、构造方法。
|
||||
|
||||
**功能示例**
|
||||
|
||||
如你所见,Hook 方法体的创建可使用 4 种方式。
|
||||
|
||||
通过字符串类名得到 `HookClass` 实例进行创建。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"com.example.demo.DemoClass".hook {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
```
|
||||
通过 `findClass` 得到 `HookClass` 实例进行创建。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass(name = "com.example.demo.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
使用 `stub` 或直接拿到 `Class` 实例进行创建。
|
||||
|
||||
默认情况下 API 会将 `Class` 实例转换为类名并绑定到 `appClassLoader`,若失败,则会使用原始 `Class` 实例直接进行 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
Stub::class.java.hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
若当前 `Class` 不在 `appClassLoader` 且自动匹配无法找到该 `Class`,请启用 `isForceUseAbsolute`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
YourClass::class.java.hook(isForceUseAbsolute = true) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
使用 `VariousClass` 实例进行创建。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
或者直接使用可变字符串数组进行创建。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## HookResources.hook <span class="symbol">- i-ext-method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> Hook APP 的 Resources。
|
||||
|
||||
::: danger
|
||||
|
||||
请注意你需要确保当前 Hook Framework 支持且 **InjectYukiHookWithXposed.isUsingResourcesHook** 已启用。
|
||||
|
||||
:::
|
||||
|
||||
**功能示例**
|
||||
|
||||
Resources Hook 为固定用法,获取 `resources` 对象,然后调用 `hook` 方法开始 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
这是固定用法,为了防止发生问题,你不可手动实现任何 **HookResources** 实例执行 **hook** 调用。
|
||||
|
||||
:::
|
||||
|
||||
将 Resources 的 Hook 设置为这样是为了与 `findClass(...).hook` 做到统一,使得调用起来逻辑不会混乱。
|
||||
|
||||
## AppLifecycle <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class AppLifecycle internal constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 当前 Hook APP 的生命周期实例处理类。
|
||||
|
||||
### attachBaseContext <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.attachBaseContext`。
|
||||
|
||||
### onCreate <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onCreate(initiate: Application.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.onCreate`。
|
||||
|
||||
### onTerminate <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onTerminate(initiate: Application.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.onTerminate`。
|
||||
|
||||
### onLowMemory <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onLowMemory(initiate: Application.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.onLowMemory`。
|
||||
|
||||
### onTrimMemory <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.onTrimMemory`。
|
||||
|
||||
### onConfigurationChanged <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听当前 Hook APP 装载 `Application.onConfigurationChanged`。
|
||||
|
||||
### registerReceiver <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 注册系统广播监听。
|
@@ -0,0 +1,15 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ComponentTypeFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个预置 Hook 类型的常量类,主要为 `Android` 相关组件的 `Class` 内容,跟随版本更新会逐一进行增加。
|
||||
|
||||
详情可 [点击这里](https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt) 进行查看。
|
@@ -0,0 +1,15 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# GraphicsTypeFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个预置 Hook 类型的常量类,主要为 `Android` 相关 `Graphics` 的 `Class` 内容,跟随版本更新会逐一进行增加。
|
||||
|
||||
详情可 [点击这里](https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.kt) 进行查看。
|
@@ -0,0 +1,15 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ViewTypeFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个预置 Hook 类型的常量类,主要为 `Android` 相关 `Widget` 的 `Class` 内容,跟随版本更新会逐一进行增加。
|
||||
|
||||
详情可 [点击这里](https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.kt) 进行查看。
|
@@ -0,0 +1,27 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# DefinedTypeFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。
|
||||
|
||||
## VagueType <span class="symbol">- field</span>
|
||||
|
||||
```kotlin
|
||||
val VagueType: Class<*>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 得到模糊类型。
|
@@ -0,0 +1,15 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# VariableTypeFactory <span class="symbol">- kt</span>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一个预置 Hook 类型的常量类,主要为 `Java` 相关基本变量类型的 `Class` 内容,跟随版本更新会逐一进行增加。
|
||||
|
||||
详情可 [点击这里](https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt) 进行查看。
|
@@ -0,0 +1,84 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModuleApplication <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
open class ModuleApplication: Application()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是对使用 `YukiHookAPI` Xposed 模块实现中的一个扩展功能。
|
||||
|
||||
在你的 Xposed 模块的 `Application` 中继承此类。
|
||||
|
||||
或在 `AndroidManifest.xml` 的 `application` 标签中指定此类。
|
||||
|
||||
目前可实现功能如下
|
||||
|
||||
- 全局共享模块中静态的 `appContext`
|
||||
|
||||
- 在模块与宿主中装载 `YukiHookAPI.Config` 以确保 `YukiHookAPI.Configs.debugTag` 不需要重复定义
|
||||
|
||||
- 在模块与宿主中使用 `YukiHookDataChannel` 进行通讯
|
||||
|
||||
- 在模块中使用系统隐藏 API,核心技术引用了开源项目 [FreeReflection](https://github.com/tiann/FreeReflection)
|
||||
|
||||
- 在模块中使用 `YukiHookAPI.Status.isTaiChiModuleActive` 判断太极、无极激活状态
|
||||
|
||||
**功能示例**
|
||||
|
||||
将此类继承到你的自定义 `Application` 上。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
package com.demo
|
||||
|
||||
class MyApplication: ModuleApplication() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在 `AndroidManifest.xml` 的 `application` 标签中指定自定义的 `Application`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```xml
|
||||
<application
|
||||
android:name="com.demo.MyApplication"
|
||||
...>
|
||||
```
|
||||
|
||||
如果你不需要自定义 `Application` 可以直接将 `ModuleApplication` 设置到 `AndroidManifest.xml` 的 `application` 标签中。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```xml
|
||||
<application
|
||||
android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
|
||||
...>
|
||||
```
|
||||
|
||||
## appContext <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val appContext: ModuleApplication
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取全局静态 `Application` 实例。
|
@@ -0,0 +1,33 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiModuleResources <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对接 `XModuleResources` 的中间层实例。
|
||||
|
||||
## fwd <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun fwd(resId: Int): YukiResForwarder
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对接 `XModuleResources.fwd` 方法。
|
||||
|
||||
创建 `YukiResForwarder` 与 `XResForwarder` 实例。
|
@@ -0,0 +1,55 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiResForwarder <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对接 `XResForwarder` 的中间层实例。
|
||||
|
||||
<h2 class="deprecated">instance - field</h2>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
`v1.1.0` `作废`
|
||||
|
||||
不再对外公开 `instance` 参数
|
||||
|
||||
## id <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val id: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 APP 的 Resources Id。
|
||||
|
||||
## resources <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val resources: Resources
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获得当前 APP 的 Resources。
|
@@ -0,0 +1,81 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiResources <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiResources private constructor(private val baseInstance: XResources) : Resources
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对接 `XResources` 的中间层实例。
|
||||
|
||||
## LayoutInflatedParam <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 装载 Hook APP 的目标布局 Resources 实现类。
|
||||
|
||||
### variantName <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val variantName: String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前被 Hook 的布局装载目录名称。
|
||||
|
||||
例如:`layout`、`layout-land`、`layout-sw600dp`。
|
||||
|
||||
### currentView <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val currentView: View
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取当前被 Hook 的布局实例。
|
||||
|
||||
### findViewByIdentifier <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T : View> findViewByIdentifier(name: String): T?
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 使用 Identifier 查找 Hook APP 指定 Id 的 `View`。
|
||||
|
||||
扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 `View`。
|
@@ -0,0 +1,73 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiXposedEvent <span class="symbol">- object</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
object YukiXposedEvent
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 实现对原生 Xposed API 的装载事件监听。
|
||||
|
||||
## events <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun events(initiate: YukiXposedEvent.() -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对 `YukiXposedEvent` 创建一个方法体。
|
||||
|
||||
## onInitZygote <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onInitZygote(result: (StartupParam) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 initZygote 事件监听。
|
||||
|
||||
## onHandleLoadPackage <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 handleLoadPackage 事件监听。
|
||||
|
||||
## onHandleInitPackageResources <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置 handleInitPackageResources 事件监听。
|
@@ -0,0 +1,153 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiHookDataChannel <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiHookDataChannel private constructor()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 实现 Xposed 模块的数据通讯桥。
|
||||
|
||||
通过模块与宿主相互注册 `BroadcastReceiver` 来实现数据的交互。
|
||||
|
||||
模块需要将 `Application` 继承于 `ModuleApplication` 来实现此功能。
|
||||
|
||||
::: danger
|
||||
|
||||
模块与宿主需要保持存活状态,否则无法建立通讯。
|
||||
|
||||
:::
|
||||
|
||||
## NameSpace <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inner class NameSpace internal constructor(private val context: Context?, private val packageName: String, private val isSecure: Boolean)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.0.90` `修改`
|
||||
|
||||
新增 `isSecure` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> `YukiHookDataChannel` 命名空间。
|
||||
|
||||
### with <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun with(initiate: NameSpace.() -> Unit): NameSpace
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建一个调用空间。
|
||||
|
||||
### put <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> put(key: String, value: T)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> put(data: ChannelData<T>, value: T?)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun put(vararg data: ChannelData<*>)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 发送键值数据。
|
||||
|
||||
### put <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun put(key: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅发送键值监听,使用默认值 `VALUE_WAIT_FOR_LISTENER` 发送键值数据。
|
||||
|
||||
### wait <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> wait(key: String, result: (value: T) -> Unit)
|
||||
```
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun <T> wait(data: ChannelData<T>, result: (value: T) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
`v1.0.90` `修改`
|
||||
|
||||
移除默认值 `value`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取键值数据。
|
||||
|
||||
### wait <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun wait(key: String, callback: () -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 仅获取监听结果,不获取键值数据。
|
||||
|
||||
::: danger
|
||||
|
||||
仅限使用 **VALUE_WAIT_FOR_LISTENER** 发送的监听才能被接收。
|
||||
|
||||
:::
|
||||
|
||||
### checkingVersionEquals <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun checkingVersionEquals(result: (Boolean) -> Unit)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取模块与宿主的版本是否匹配。
|
||||
|
||||
通过此方法可原生判断 Xposed 模块更新后宿主并未重新装载造成两者不匹配的情况。
|
@@ -0,0 +1,68 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ChannelData <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
data class ChannelData<T>(var key: String, var value: T?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.88` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 数据通讯桥键值构造类。
|
||||
|
||||
这个类是对 `YukiHookDataChannel` 的一个扩展用法。
|
||||
|
||||
**功能示例**
|
||||
|
||||
建立一个模板类定义模块与宿主需要发送的键值数据。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
object DataConst {
|
||||
|
||||
val TEST_KV_DATA_1 = ChannelData("test_data_1", "defalut value")
|
||||
val TEST_KV_DATA_2 = ChannelData("test_data_2", 0)
|
||||
}
|
||||
```
|
||||
|
||||
键值数据定义后,你就可以方便地在模块和宿主中调用所需要发送的数据。
|
||||
|
||||
> 模块示例如下
|
||||
|
||||
```kotlin
|
||||
// 从指定包名的宿主获取
|
||||
dataChannel(packageName = "com.example.demo").wait(DataConst.TEST_KV_DATA_1) { value ->
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给指定包名的宿主 - 未填写 value 时将使用模板提供的默认值
|
||||
dataChannel(packageName = "com.example.demo").put(DataConst.TEST_KV_DATA_1, value = "sending value")
|
||||
```
|
||||
|
||||
> 宿主示例如下
|
||||
|
||||
```kotlin
|
||||
// 从模块获取
|
||||
dataChannel.wait(DataConst.TEST_KV_DATA_1) { value ->
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给模块 - 未填写 value 时将使用模板提供的默认值
|
||||
dataChannel.put(DataConst.TEST_KV_DATA_1, value = "sending value")
|
||||
```
|
||||
|
||||
你依然可以不使用模板定义的默认值,随时修改你的默认值。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 获取 - 此时 value 取到的默认值将会是 2 - 并不是模板提供的 0
|
||||
dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
|
||||
// Your code here.
|
||||
}
|
||||
```
|
@@ -0,0 +1,21 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModuleAppActivity <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
open class ModuleAppActivity : Activity()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 代理 `Activity`。
|
||||
|
||||
继承于此类的 `Activity` 可以同时在宿主与模块中启动。
|
||||
|
||||
在 (Xposed) 宿主环境需要在宿主启动时调用 `Context.registerModuleAppActivities` 进行注册。
|
@@ -0,0 +1,37 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModuleAppCompatActivity <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
open class ModuleAppCompatActivity : AppCompatActivity()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 代理 `AppCompatActivity`。
|
||||
|
||||
继承于此类的 `Activity` 可以同时在宿主与模块中启动。
|
||||
|
||||
在 (Xposed) 宿主环境需要在宿主启动时调用 `Context.registerModuleAppActivities` 进行注册。
|
||||
|
||||
在 (Xposed) 宿主环境需要重写 `moduleTheme` 设置 AppCompat 主题,否则会无法启动。
|
||||
|
||||
## moduleTheme <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
open val moduleTheme: Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前代理的 `Activity` 主题。
|
@@ -0,0 +1,35 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModuleContextThemeWrapper <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 代理 `ContextThemeWrapper`。
|
||||
|
||||
通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。
|
||||
|
||||
## applyConfiguration <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.1.0` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 设置当前 `ModuleContextThemeWrapper` 的 `Configuration`。
|
||||
|
||||
设置后会自动调用 `Resources.updateConfiguration`。
|
@@ -0,0 +1,491 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# YukiHookModulePrefs <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class YukiHookModulePrefs private constructor(private var context: Context?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 实现 Xposed 模块的数据存取,对接 `SharedPreferences` 和 `XSharedPreferences`。
|
||||
|
||||
在不同环境智能选择存取使用的对象。
|
||||
|
||||
::: danger
|
||||
|
||||
此功能为实验性功能,仅在 LSPosed 环境测试通过,EdXposed 理论也可以使用但不再推荐。
|
||||
|
||||
:::
|
||||
|
||||
使用 LSPosed 环境请在 `AndroidManifests.xml` 中将 `xposedminversion` 最低设置为 `93`。
|
||||
|
||||
详见 [New XSharedPreferences](https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module)。
|
||||
|
||||
若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 [isEnableHookSharedPreferences](YukiHookAPI#isenablehooksharedpreferences-field)。
|
||||
|
||||
未使用 LSPosed 环境请将你的模块 `API` 降至 `26` 以下,`YukiHookAPI` 将会尝试使用 `makeWorldReadable` 但仍有可能不成功。
|
||||
|
||||
太极请参阅 [文件权限/配置/XSharedPreference](https://taichi.cool/zh/doc/for-xposed-dev.html#文件权限-配置-xsharedpreference)。
|
||||
|
||||
::: danger
|
||||
|
||||
当你在 Xposed 模块中存取数据的时候 **context** 必须不能是空的。
|
||||
|
||||
:::
|
||||
|
||||
若你正在使用 `PreferenceFragmentCompat`,请迁移到 `ModulePreferenceFragment` 以适配上述功能特性。
|
||||
|
||||
**可选配置**
|
||||
|
||||
若你不想将你的模块的 `xposedminversion` 最低设置为 `93`,你可以在 `AndroidManifest.xml` 中添加 `xposedsharedprefs` 来实现支持。
|
||||
|
||||
详见 [New XSharedPreferences](https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module)。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```xml
|
||||
<meta-data
|
||||
android:name="xposedsharedprefs"
|
||||
android:value="true"/>
|
||||
```
|
||||
|
||||
## isXSharePrefsReadable <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isXSharePrefsReadable: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.90` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `XSharedPreferences` 是否可读。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在 (Xposed) 宿主环境中使用,模块环境中始终返回 false。
|
||||
|
||||
:::
|
||||
|
||||
## isRunInNewXShareMode <span class="symbol">- field</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
val isRunInNewXShareMode: Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.78` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `YukiHookModulePrefs` 是否正处于 EdXposed/LSPosed 的最高权限运行。
|
||||
|
||||
前提条件为当前 Xposed 模块已被激活。
|
||||
|
||||
::: danger
|
||||
|
||||
只能在模块环境中使用,(Xposed) 宿主环境中始终返回 false。
|
||||
|
||||
:::
|
||||
|
||||
## name <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun name(name: String): YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 自定义 Sp 存储名称。
|
||||
|
||||
**功能示例**
|
||||
|
||||
在 `Activity` 中的使用方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
modulePrefs("custom_name").getString("custom_key")
|
||||
```
|
||||
|
||||
在 (Xposed) 宿主环境 `PackageParam` 中的使用方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
prefs("custom_name").getString("custom_key")
|
||||
```
|
||||
|
||||
## direct <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun direct(): YukiHookModulePrefs
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 忽略缓存直接读取键值。
|
||||
|
||||
无论是否开启 `YukiHookAPI.Configs.isEnableModulePrefsCache`。
|
||||
|
||||
仅在 `XSharedPreferences` 下生效。
|
||||
|
||||
## getString <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getString(key: String, value: String): String
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `String` 键值。
|
||||
|
||||
## getStringSet <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getStringSet(key: String, value: Set<String>): Set<String>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `Set<String>` 键值。
|
||||
|
||||
## getBoolean <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getBoolean(key: String, value: Boolean): Boolean
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `Boolean` 键值。
|
||||
|
||||
## getInt <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getInt(key: String, value: Int): Int
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `Int` 键值。
|
||||
|
||||
## getLong <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getLong(key: String, value: Long): Long
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `Long` 键值。
|
||||
|
||||
## getFloat <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun getFloat(key: String, value: Float): Float
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取 `Float` 键值。
|
||||
|
||||
## all <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun all(): HashMap<String, Any?>
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 获取全部存储的键值数据。
|
||||
|
||||
智能识别对应环境读取键值数据。
|
||||
|
||||
::: danger
|
||||
|
||||
每次调用都会获取实时的数据,不受缓存控制,请勿在高并发场景中使用。
|
||||
|
||||
:::
|
||||
|
||||
## remove <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun remove(key: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 移除全部包含 `key` 的存储数据。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## remove <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> remove(prefs: PrefsData<T>)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 移除 `PrefsData.key` 的存储数据。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## clear <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun clear()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 移除全部存储数据。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putString <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putString(key: String, value: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `String` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putStringSet <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putStringSet(key: String, value: Set<String>)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.77` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `Set<String>` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putBoolean <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putBoolean(key: String, value: Boolean)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `Boolean` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putInt <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putInt(key: String, value: Int)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `Int` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putLong <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putLong(key: String, value: Long)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `Long` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## putFloat <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun putFloat(key: String, value: Float)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 存储 `Float` 键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## get <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 智能获取指定类型的键值。
|
||||
|
||||
## put <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
inline fun <reified T> put(prefs: PrefsData<T>, value: T)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 智能存储指定类型的键值。
|
||||
|
||||
::: warning
|
||||
|
||||
在 (Xposed) 宿主环境下只读,无法使用。
|
||||
|
||||
:::
|
||||
|
||||
## clearCache <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun clearCache()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 清除 `XSharedPreferences` 中缓存的键值数据。
|
||||
|
||||
无论是否开启 `YukiHookAPI.Configs.isEnableModulePrefsCache`。
|
||||
|
||||
调用此方法将清除当前存储的全部键值缓存。
|
||||
|
||||
下次将从 `XSharedPreferences` 重新读取。
|
||||
|
||||
在 (Xposed) 宿主环境中使用。
|
@@ -0,0 +1,63 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# PrefsData <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
data class PrefsData<T>(var key: String, var value: T)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.67` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 键值对存储构造类。
|
||||
|
||||
这个类是对 `YukiHookModulePrefs` 的一个扩展用法。
|
||||
|
||||
**功能示例**
|
||||
|
||||
建立一个模板类定义模块与宿主需要使用的键值数据。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
object DataConst {
|
||||
|
||||
val TEST_KV_DATA_1 = PrefsData("test_data_1", "defalut value")
|
||||
val TEST_KV_DATA_2 = PrefsData("test_data_2", false)
|
||||
val TEST_KV_DATA_3 = PrefsData("test_data_3", 0)
|
||||
}
|
||||
```
|
||||
|
||||
键值数据定义后,你就可以方便地在模块和宿主中调用所需要的数据。
|
||||
|
||||
> 模块示例如下
|
||||
|
||||
```kotlin
|
||||
// 读取
|
||||
val data = modulePrefs.get(DataConst.TEST_KV_DATA_1)
|
||||
// 写入
|
||||
modulePrefs.put(DataConst.TEST_KV_DATA_1, "written value")
|
||||
```
|
||||
|
||||
> 宿主示例如下
|
||||
|
||||
```kotlin
|
||||
// 读取 String
|
||||
val dataString = prefs.get(DataConst.TEST_KV_DATA_1)
|
||||
// 读取 Boolean
|
||||
val dataBoolean = prefs.get(DataConst.TEST_KV_DATA_2)
|
||||
```
|
||||
|
||||
你依然可以不使用模板定义的默认值,随时修改你的默认值。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 读取 - 此时 data 取到的默认值将会是 2 - 并不是模板提供的 0
|
||||
val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
|
||||
```
|
@@ -0,0 +1,93 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# ModulePreferenceFragment <span class="symbol">- class</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.78` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是对使用 `YukiHookAPI` Xposed 模块实现中的一个扩展功能。
|
||||
|
||||
此类接管了 `PreferenceFragmentCompat` 并对其实现了 Sp 存储在 Xposed 模块中的全局可读可写。
|
||||
|
||||
在你使用 `PreferenceFragmentCompat` 的实例中,将继承对象换成此类。
|
||||
|
||||
然后请将重写方法由 `onCreatePreferences` 替换为 `onCreatePreferencesInModuleApp` 即可。
|
||||
|
||||
**功能示例**
|
||||
|
||||
使用 `ModulePreferenceFragment` 创建一个 `PreferenceFragmentCompat` 对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class SettingsFragment : ModulePreferenceFragment() {
|
||||
|
||||
override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.settings_preferences, rootKey)
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其余用法与 `PreferenceFragmentCompat` 保持一致。
|
||||
|
||||
## onCreatePreferencesInModuleApp <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.78` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 对接原始方法 `onCreatePreferences`。
|
||||
|
||||
## onSharedPreferenceChanged <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.78` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 实现了 `SharedPreferences.OnSharedPreferenceChangeListener` 的原生监听功能。
|
||||
|
||||
**功能示例**
|
||||
|
||||
::: warning
|
||||
|
||||
在使用 **onSharedPreferenceChanged** 时请保留 super 方法。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class SettingsFragment : ModulePreferenceFragment() {
|
||||
|
||||
override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
super.onSharedPreferenceChanged(sharedPreferences, key)
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
@@ -0,0 +1,101 @@
|
||||
---
|
||||
pageClass: code-page
|
||||
---
|
||||
|
||||
# IYukiHookXposedInit <span class="symbol">- interface</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
interface IYukiHookXposedInit
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `修改` `作废`
|
||||
|
||||
作废了 ~~`YukiHookXposedInitProxy`~~ 名称但保留接口
|
||||
|
||||
转移到 `IYukiHookXposedInit` 新名称
|
||||
|
||||
**功能描述**
|
||||
|
||||
> YukiHookAPI 的 Xposed 装载 API 调用接口。
|
||||
|
||||
## onInit <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onInit()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.5` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 配置 `YukiHookAPI.Configs` 的初始化方法。
|
||||
|
||||
::: danger
|
||||
|
||||
在这里只能进行初始化配置,不能进行 Hook 操作。
|
||||
|
||||
:::
|
||||
|
||||
此方法可选,你也可以选择不对 [YukiHookAPI.Configs](../../../YukiHookAPI#configs-object) 进行配置。
|
||||
|
||||
## onHook <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onHook()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> Xposed API 的模块装载调用入口方法。
|
||||
|
||||
## onXposedEvent <span class="symbol">- method</span>
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun onXposedEvent()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.80` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 Xposed 原生装载事件。
|
||||
|
||||
若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。
|
||||
|
||||
请在这里使用 [YukiXposedEvent](../bridge/event/YukiXposedEvent) 创建回调事件监听。
|
||||
|
||||
可监听的事件如下:
|
||||
|
||||
`YukiXposedEvent.onInitZygote`
|
||||
|
||||
`YukiXposedEvent.onHandleLoadPackage`
|
||||
|
||||
`YukiXposedEvent.onHandleInitPackageResources`
|
||||
|
||||
::: danger
|
||||
|
||||
此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 **YukiHookAPI**。
|
||||
|
||||
:::
|
||||
|
||||
<h1 class="deprecated">YukiHookXposedInitProxy - interface</h1>
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.80` `作废`
|
||||
|
||||
请转移到 `IYukiHookXposedInit`
|
275
docs-source/src/zh-cn/api/special-features/host-inject.md
Normal file
275
docs-source/src/zh-cn/api/special-features/host-inject.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# 宿主资源注入扩展
|
||||
|
||||
> 这是一个将模块资源、`Activity` 组件以及 `Context` 主题注入到宿主的扩展功能。
|
||||
|
||||
在使用以下功能之前,为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 `build.gradle` 中修改资源 ID。
|
||||
|
||||
- Kotlin Gradle DSL
|
||||
|
||||
```kotlin
|
||||
android {
|
||||
androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
|
||||
}
|
||||
```
|
||||
|
||||
- Groovy
|
||||
|
||||
```groovy
|
||||
android {
|
||||
aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
提供的示例资源 ID 值仅供参考,不可使用 **0x7f**,默认为 **0x64**,为了防止当前宿主存在多个 Xposed 模块,建议自定义你自己的资源 ID。
|
||||
|
||||
:::
|
||||
|
||||
## 注入模块资源 (Resources)
|
||||
|
||||
在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 `Context` 注入当前模块资源。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
instance<Activity>().also {
|
||||
// <方案1> 通过 Context 注入模块资源
|
||||
it.injectModuleAppResources()
|
||||
// <方案2> 直接得到宿主 Resources 注入模块资源
|
||||
it.resources.injectModuleAppResources()
|
||||
// 直接使用模块资源 ID
|
||||
it.getString(R.id.app_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你还可以直接在 `AppLifecycle` 中注入当前模块资源。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
onAppLifecycle {
|
||||
onCreate {
|
||||
// 全局注入模块资源,但仅限于全局生命周期
|
||||
// 类似 ImageView.setImageResource 这样的方法在 Activity 中需要单独注入
|
||||
// <方案1> 通过 Context 注入模块资源
|
||||
injectModuleAppResources()
|
||||
// <方案2> 直接得到宿主 Resources 注入模块资源
|
||||
resources.injectModuleAppResources()
|
||||
// 直接使用模块资源 ID
|
||||
getString(R.id.app_name)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [Context+Resources.injectModuleAppResources](../public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory#context-resources-injectmoduleappresources-ext-method) 方法。
|
||||
|
||||
:::
|
||||
|
||||
## 注册模块 Activity
|
||||
|
||||
在 Android 系统中所有应用的 `Activity` 启动时,都需要在 `AndroidManifest.xml` 中进行注册,在 Hook 过程中,如果我们想通过宿主来直接启动模块中未注册的 `Activity` 要怎么做呢?
|
||||
|
||||
在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 `Context` 注册当前模块的 `Activity` 代理。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
instance<Activity>().registerModuleAppActivities()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你还可以直接在 `AppLifecycle` 中注册当前模块的 `Activity` 代理。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
onAppLifecycle {
|
||||
onCreate {
|
||||
registerModuleAppActivities()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果没有填写 `proxy` 参数,API 将会根据当前 `Context` 自动获取当前宿主的启动入口 `Activity` 进行代理。
|
||||
|
||||
通常情况下,它是有效的,但是以上情况在一些 APP 中会失效,例如一些 `Activity` 会在注册清单上加入启动参数,那么我们就需要使用另一种解决方案。
|
||||
|
||||
若未注册的 `Activity` 不能被正确启动,我们可以手动拿到宿主的 `AndroidManifest.xml` 进行分析,来得到一个注册过的 `Activity` 标签,获取其中的 `name`。
|
||||
|
||||
你需要选择一个当前宿主可能用不到的、不需要的 `Activity` 作为一个“傀儡”将其进行代理,通常是有效的。
|
||||
|
||||
比如我们已经找到了能够被代理的合适 `Activity`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```xml
|
||||
<activity
|
||||
android:name="com.demo.test.activity.TestActivity"
|
||||
...>
|
||||
```
|
||||
|
||||
根据其中的 `name`,我们只需要在方法中加入这个参数进行注册即可。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
|
||||
```
|
||||
|
||||
另一种情况,如果你对宿主的类编写了一个 `stub`,那么你可以直接通过 `Class` 对象来进行注册。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
registerModuleAppActivities(TestActivity::class.java)
|
||||
```
|
||||
|
||||
注册完成后,请将你需要使用宿主启动的模块中的 `Activity` 继承于 `ModuleAppActivity` 或 `ModuleAppCompatActivity`。
|
||||
|
||||
这些 `Activity` 现在无需注册即可无缝存活于宿主中。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HostTestActivity : ModuleAppActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// 模块资源已被自动注入,可以直接使用 xml 装载布局
|
||||
setContentView(R.layout.activity_main)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若你需要继承于 `ModuleAppCompatActivity`,你需要手动设置 AppCompat 主题。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HostTestActivity : ModuleAppCompatActivity() {
|
||||
|
||||
// 这里的主题名称仅供参考,请填写你模块中已有的主题名称
|
||||
override val moduleTheme get() = R.style.Theme_AppCompat
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// 模块资源已被自动注入,可以直接使用 xml 装载布局
|
||||
setContentView(R.layout.activity_main)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
以上步骤全部完成后,你就可以在 (Xposed) 宿主环境任意存在 `Context` 的地方愉快地调用 `startActivity` 了。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val context: Context = ... // 假设这就是你的 Context
|
||||
context.startActivity(context, HostTestActivity::class.java)
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [Context.registerModuleAppActivities](../public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory#context-registermoduleappactivities-ext-method) 方法。
|
||||
|
||||
:::
|
||||
|
||||
## 创建 ContextThemeWrapper 代理
|
||||
|
||||
有时候,我们需要使用 `MaterialAlertDialogBuilder` 来美化自己在宿主中的对话框,但是拿不到 AppCompat 主题就无法创建。
|
||||
|
||||
- 会得到如下异常
|
||||
|
||||
```:no-line-numbers
|
||||
The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
|
||||
```
|
||||
|
||||
这时,我们想在宿主被 Hook 的当前 `Activity` 中使用 `MaterialAlertDialogBuilder` 来创建对话框,就可以有如下方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
// 使用 applyModuleTheme 创建一个当前模块中的主题资源
|
||||
val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
|
||||
// 直接使用这个包装了模块主题后的 Context 创建对话框
|
||||
MaterialAlertDialogBuilder(appCompatContext)
|
||||
.setTitle("AppCompat 主题对话框")
|
||||
.setMessage("我是一个在宿主中显示的 AppCompat 主题对话框。")
|
||||
.setPositiveButton("确定", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你还可以对当前 `Context` 通过 `uiMode` 设置原生的夜间模式和日间模式,至少需要 Android 10 及以上系统版本支持且当前主题包含夜间模式相关元素。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
// 定义当前模块中的主题资源
|
||||
var appCompatContext: ModuleContextThemeWrapper
|
||||
// <方案1> 直接得到 Configuration 对象进行设置
|
||||
appCompatContext = instance<Activity>()
|
||||
.applyModuleTheme(R.style.Theme_AppCompat)
|
||||
.applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
|
||||
// <方案2> 创建一个新的 Configuration 对象
|
||||
// 此方案会破坏当前宿主中原有的字体缩放大小等设置,你需要手动重新传递 densityDpi 等参数
|
||||
appCompatContext = instance<Activity>().applyModuleTheme(
|
||||
theme = R.style.Theme_AppCompat,
|
||||
configuration = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
|
||||
)
|
||||
// 直接使用这个包装了模块主题后的 Context 创建对话框
|
||||
MaterialAlertDialogBuilder(appCompatContext)
|
||||
.setTitle("AppCompat 主题对话框")
|
||||
.setMessage("我是一个在宿主中显示的 AppCompat 主题对话框。")
|
||||
.setPositiveButton("确定", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这样,我们就可以在宿主中非常简单地使用 `MaterialAlertDialogBuilder` 创建对话框了。
|
||||
|
||||
::: warning 可能存在的问题
|
||||
|
||||
由于一些 APP 自身使用的 **androidx** 依赖库或自定义主题可能会对当前 **MaterialAlertDialog** 实际样式造成干扰,例如对话框的按钮样式,这种情况你可以参考 **模块 Demo** 中 [这里的示例代码](https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/factory/ComponentCompatFactory.kt) 来修复这个问题。
|
||||
|
||||
某些 APP 在创建时可能会发生 **ClassCastException** 异常,请手动指定新的 **Configuration** 实例来进行修复。
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [Context.applyModuleTheme](../public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory#context-applymoduletheme-ext-method) 方法。
|
||||
|
||||
:::
|
82
docs-source/src/zh-cn/api/special-features/host-lifecycle.md
Normal file
82
docs-source/src/zh-cn/api/special-features/host-lifecycle.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# 宿主生命周期扩展
|
||||
|
||||
> 这是一个自动 Hook 宿主 APP 生命周期的扩展功能。
|
||||
|
||||
## 监听生命周期
|
||||
|
||||
> 通过自动化 Hook 宿主 APP 的生命周期方法,来实现监听功能。
|
||||
|
||||
我们需要监听宿主 `Application` 的启动和生命周期方法,只需要使用以下方式实现。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.example.demo") {
|
||||
// 注册生命周期监听
|
||||
onAppLifecycle {
|
||||
// 你可以在这里实现 Application 中的生命周期方法监听
|
||||
attachBaseContext { baseContext, hasCalledSuper ->
|
||||
// 通过判断 hasCalledSuper 来确定是否已执行 super.attachBaseContext(base) 方法
|
||||
// ...
|
||||
}
|
||||
onCreate {
|
||||
// 通过 this 得到当前 Application 实例
|
||||
// ...
|
||||
}
|
||||
onTerminate {
|
||||
// 通过 this 得到当前 Application 实例
|
||||
// ...
|
||||
}
|
||||
onLowMemory {
|
||||
// 通过 this 得到当前 Application 实例
|
||||
// ...
|
||||
}
|
||||
onTrimMemory { self, level ->
|
||||
// 可在这里判断 APP 是否已切换到后台
|
||||
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
|
||||
// ...
|
||||
}
|
||||
// ...
|
||||
}
|
||||
onConfigurationChanged { self, config ->
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [AppLifecycle](../public/com/highcapable/yukihookapi/hook/param/PackageParam#applifecycle-class)。
|
||||
|
||||
:::
|
||||
|
||||
## 注册系统广播
|
||||
|
||||
> 通过 `Application.onCreate` 方法注册系统广播,来实现对系统广播的监听。
|
||||
|
||||
我们还可以在宿主 `Application` 中注册系统广播。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.example.demo") {
|
||||
// 注册生命周期监听
|
||||
onAppLifecycle {
|
||||
// 注册用户解锁时的广播监听
|
||||
registerReceiver(Intent.ACTION_USER_PRESENT) { context, intent ->
|
||||
// ...
|
||||
}
|
||||
// 注册多个广播监听 - 会同时回调多次
|
||||
registerReceiver(Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_TIME_TICK) { context, intent ->
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [AppLifecycle](../public/com/highcapable/yukihookapi/hook/param/PackageParam#applifecycle-class)。
|
||||
|
||||
:::
|
124
docs-source/src/zh-cn/api/special-features/logger.md
Normal file
124
docs-source/src/zh-cn/api/special-features/logger.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 调试日志
|
||||
|
||||
> 日志是调试过程最重要的一环,`YukiHookAPI` 为开发者封装了一套稳定高效的调试日志功能。
|
||||
|
||||
## 普通日志
|
||||
|
||||
你可以调用 `loggerD`、`loggerI`、`loggerW` 来向控制台打印普通日志。
|
||||
|
||||
使用方法如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerD(msg = "This is a log")
|
||||
```
|
||||
|
||||
此时,`YukiHookAPI` 会调用 `android.util.Log` 与 `XposedBridge.log` 同时打印这条日志。
|
||||
|
||||
日志默认的 `TAG` 为你在 `YukiHookAPI.Configs.debugTag` 中设置的值。
|
||||
|
||||
你也可以动态自定义这个值,但是不建议轻易修改 `TAG` 防止过滤不到日志。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerD(tag = "YukiHookAPI", msg = "This is a log")
|
||||
```
|
||||
|
||||
打印的结果为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
[YukiHookAPI][D][宿主包名]--> This is a log
|
||||
```
|
||||
|
||||
你还可以使用 `LoggerType` 自定义日志打印的类型,可选择使用 `android.util.Log` 还是 `XposedBridge.log` 来打印日志。
|
||||
|
||||
默认类型为 `LoggerType.BOTH`,含义为同时使用这两个方法来打印日志。
|
||||
|
||||
比如我们仅使用 `android.util.Log` 来打印日志。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
|
||||
```
|
||||
|
||||
或又仅使用 `XposedBridge.log` 来打印日志,此方法仅可在 (Xposed) 宿主环境使用。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
|
||||
```
|
||||
|
||||
若你想智能区分 (Xposed) 宿主环境与模块环境,可以写为如下形式。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
|
||||
```
|
||||
|
||||
这样 API 就会在不同环境智能选择指定的方法类型去打印这条日志。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [loggerD](../public/com/highcapable/yukihookapi/hook/log/LoggerFactory#loggerd-method)、[loggerI](../public/com/highcapable/yukihookapi/hook/log/LoggerFactory#loggeri-method) 及 [loggerW](../public/com/highcapable/yukihookapi/hook/log/LoggerFactory#loggerw-method) 方法。
|
||||
|
||||
:::
|
||||
|
||||
## 错误日志
|
||||
|
||||
你可以调用 `loggerE` 来向控制台打印 `E` 级别的日志。
|
||||
|
||||
使用方法如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loggerE(msg = "This is an error")
|
||||
```
|
||||
|
||||
错误日志的级别是最高的,无论你有没有过滤仅为 `E` 级别的日志。
|
||||
|
||||
对于错误级别的日志,你还可以在后面加上一个异常堆栈。
|
||||
|
||||
```kotlin
|
||||
// 假设这就是被抛出的异常
|
||||
val throwable = Throwable(...)
|
||||
// 打印日志
|
||||
loggerE(msg = "This is an error", e = throwable)
|
||||
```
|
||||
|
||||
打印的结果为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
[YukiHookAPI][E][宿主包名]--> This is an error
|
||||
```
|
||||
|
||||
同时,日志会帮你打印整个异常堆栈。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
java.lang.Throwable
|
||||
at com.demo.Test.<init>(...)
|
||||
at com.demo.Test.doTask(...)
|
||||
at com.demo.Test.stop(...)
|
||||
at com.demo.Test.init(...)
|
||||
at a.a.a(...)
|
||||
... 3 more
|
||||
```
|
||||
|
||||
在错误日志中,你同样也可以使用 `LoggerType` 来指定当前打印日志所用到的方法类型。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [loggerE](../public/com/highcapable/yukihookapi/hook/log/LoggerFactory#loggere-method) 方法。
|
||||
|
||||
:::
|
1373
docs-source/src/zh-cn/api/special-features/reflection.md
Normal file
1373
docs-source/src/zh-cn/api/special-features/reflection.md
Normal file
File diff suppressed because it is too large
Load Diff
181
docs-source/src/zh-cn/api/special-features/xposed-channel.md
Normal file
181
docs-source/src/zh-cn/api/special-features/xposed-channel.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Xposed 模块与宿主通讯桥
|
||||
|
||||
> 这是一个使用系统无序广播在模块与宿主之间发送和接收数据的解决方案。
|
||||
|
||||
::: danger 需要满足的条件
|
||||
|
||||
模块与宿主需要保持存活状态,否则无法建立通讯。
|
||||
|
||||
:::
|
||||
|
||||
## 基本用法
|
||||
|
||||
> 这里描述了 `wait` 与 `put` 方法的基本使用方法。
|
||||
|
||||
通过使用 `dataChannel` 来实现模块与宿主之间的通讯桥,原理为发送接收系统无序广播。
|
||||
|
||||
> 模块示例如下
|
||||
|
||||
```kotlin
|
||||
// 从指定包名的宿主获取
|
||||
dataChannel(packageName = "com.example.demo").wait<String>(key = "key_from_host") { value ->
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给指定包名的宿主
|
||||
dataChannel(packageName = "com.example.demo").put(key = "key_from_module", value = "I am module")
|
||||
```
|
||||
|
||||
> 宿主示例如下
|
||||
|
||||
```kotlin
|
||||
// 从模块获取
|
||||
dataChannel.wait<String>(key = "key_from_module") { value ->
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给模块
|
||||
dataChannel.put(key = "key_from_host", value = "I am host")
|
||||
```
|
||||
|
||||
你可以不设置 `dataChannel` 的 `value` 来达到仅通知模块或宿主回调 `wait` 方法。
|
||||
|
||||
> 模块示例如下
|
||||
|
||||
```kotlin
|
||||
// 从指定包名的宿主获取
|
||||
dataChannel(packageName = "com.example.demo").wait(key = "listener_from_host") {
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给指定包名的宿主
|
||||
dataChannel(packageName = "com.example.demo").put(key = "listener_from_module")
|
||||
```
|
||||
|
||||
> 宿主示例如下
|
||||
|
||||
```kotlin
|
||||
// 从模块获取
|
||||
dataChannel.wait(key = "listener_from_module") {
|
||||
// Your code here.
|
||||
}
|
||||
// 发送给模块
|
||||
dataChannel.put(key = "listener_from_host")
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
接收方需要保持存活状态才能收到通讯数据。
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiHookDataChannel](../public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel)。
|
||||
|
||||
:::
|
||||
|
||||
## 判断模块与宿主版本是否匹配
|
||||
|
||||
> 通过通讯桥功能,`YukiHookAPI` 还为你提供了在用户更新模块后,判断模块是否与宿主版本匹配的解决方案。
|
||||
|
||||
我们只需要调用 `checkingVersionEquals` 方法,即可实现这个功能。
|
||||
|
||||
在模块与宿主中可进行双向判断。
|
||||
|
||||
你可以在模块中判断指定包名的宿主是否与当前模块的版本匹配。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 从指定包名的宿主获取
|
||||
dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
你还可以在宿主中判断是否自身与当前模块的版本匹配。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 从模块获取
|
||||
dataChannel.checkingVersionEquals { isEquals ->
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: warning 方法回调的条件
|
||||
|
||||
宿主、模块保持存活状态,并在激活模块后重启了作用域中的 Hook 目标宿主对象。
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiHookDataChannel](../public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel)。
|
||||
|
||||
:::
|
||||
|
||||
## 回调事件响应的规则
|
||||
|
||||
这里只列出了在模块中使用的例子,在宿主中相同的 `key` 始终不允许重复创建。
|
||||
|
||||
::: danger
|
||||
|
||||
在模块和宿主中,每一个 **dataChannel** 对应的 **key** 的回调事件**都不允许重复创建**,若重复,之前的回调事件会被新增加的回调事件替换,若在模块中使用,在同一个 **Activity** 中不可以重复,不同的 **Activity** 中相同的 **key** 允许重复。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// 回调事件 A
|
||||
dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
|
||||
// Your code here.
|
||||
}
|
||||
// 回调事件 B
|
||||
dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
|
||||
// Your code here.
|
||||
}
|
||||
// 回调事件 C
|
||||
dataChannel(packageName = "com.example.demo").wait(key = "other_test_key") {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OtherActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// 回调事件 D
|
||||
dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在上述示例中,回调事件 A 会被回调事件 B 替换掉,回调事件 C 的 `key` 不与其它重复,回调事件 D 在另一个 Activity 中,所以最终回调事件 B、C、D 都可被创建成功。
|
||||
|
||||
::: danger
|
||||
|
||||
一个相同 **key** 的回调事件只会回调当前模块正在显示的 **Activity** 中注册的回调事件,例如上述中的 **test_key**,如果 **OtherActivity** 正在显示,那么 **MainActivity** 中的 **test_key** 就不会被回调。
|
||||
|
||||
相同的 **key** 在同一个 **Activity** 不同的 **Fragment** 中注册 **dataChannel**,它们依然会在当前 **Activity** 中同时被回调。
|
||||
|
||||
在模块中,你只能使用 **Activity** 的 **Context** 注册 **dataChannel**,你不能在 **Application** 以及 **Service** 等地方使用 **dataChannel**,若要在 **Fragment** 中使用 **dataChannel**,请使用 **activity?.dataChannel(...)**。
|
||||
|
||||
:::
|
||||
|
||||
## 安全性说明
|
||||
|
||||
在模块环境中,你只能接收<u>**指定包名的宿主**</u>发送的通讯数据且只能发送给<u>**指定包名的宿主**</u>。
|
||||
|
||||
::: danger
|
||||
|
||||
为了进一步防止广播滥用,通讯数据中 API 会自动指定宿主和模块的包名,防止其它 APP 监听并利用广播做出超限行为。
|
||||
|
||||
:::
|
89
docs-source/src/zh-cn/api/special-features/xposed-prefs.md
Normal file
89
docs-source/src/zh-cn/api/special-features/xposed-prefs.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Xposed 模块数据存储
|
||||
|
||||
> 这是一个自动对接 `SharedPreferences` 和 `XSharedPreferences` 的高效模块数据存储解决方案。
|
||||
|
||||
我们需要存储模块的数据,以供宿主调用,这个时候会遇到原生 `Sp` 存储的数据互通阻碍。
|
||||
|
||||
原生的 `Xposed` 给我们提供了一个 `XSharedPreferences` 用于读取模块的 `Sp` 数据。
|
||||
|
||||
## 在 Activity 中使用
|
||||
|
||||
> 这里描述了在 `Activity` 中装载 `YukiHookModulePrefs` 的场景。
|
||||
|
||||
通常情况下我们可以这样在 Hook 内对其进行初始化。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
XSharedPreferences(BuildConfig.APPLICATION_ID)
|
||||
```
|
||||
|
||||
有没有方便快捷的解决方案呢,此时你就可以使用 `YukiHookAPI` 的扩展能力快速实现这个功能。
|
||||
|
||||
当你在模块中存储数据的时候,若当前处于 `Activity` 内,可以使用如下方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
modulePrefs.putString("test_name", "saved_value")
|
||||
```
|
||||
|
||||
当你在 Hook 中读取数据时,可以使用如下方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val testName = prefs.getString("test_name", "default_value")
|
||||
```
|
||||
|
||||
你不需要考虑传入模块的包名以及一系列复杂的权限配置,一切都交给 `YukiHookModulePrefs` 来处理。
|
||||
|
||||
若要实现存储的区域划分,你可以指定每个 `prefs` 文件的名称。
|
||||
|
||||
在模块的 `Activity` 中这样使用。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 推荐用法
|
||||
modulePrefs("specify_file_name").putString("test_name", "saved_value")
|
||||
// 也可以这样用
|
||||
modulePrefs.name("specify_file_name").putString("test_name", "saved_value")
|
||||
```
|
||||
|
||||
在 Hook 中这样读取。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 推荐用法
|
||||
val testName = prefs("specify_file_name").getString("test_name", "default_value")
|
||||
// 也可以这样用
|
||||
val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
|
||||
```
|
||||
|
||||
若你的项目中有大量的固定数据需要存储和读取,推荐使用 `PrefsData` 来创建模板。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiHookModulePrefs](../public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs)、[PrefsData](../public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData)。
|
||||
|
||||
:::
|
||||
|
||||
## 在 PreferenceFragment 中使用
|
||||
|
||||
> 这里描述了在 `PreferenceFragment` 中装载 `YukiHookModulePrefs` 的场景。
|
||||
|
||||
若你的模块使用了 `PreferenceFragmentCompat`,你现在可以将其继承类开始迁移到 `ModulePreferenceFragment`。
|
||||
|
||||
::: danger
|
||||
|
||||
你必须继承 **ModulePreferenceFragment** 才能实现 **YukiHookModulePrefs** 的模块存储功能。
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [ModulePreferenceFragment](../public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment)。
|
||||
|
||||
:::
|
395
docs-source/src/zh-cn/config/api-example.md
Normal file
395
docs-source/src/zh-cn/config/api-example.md
Normal file
@@ -0,0 +1,395 @@
|
||||
# API 基本配置
|
||||
|
||||
> 这里介绍了 `YukiHookAPI` 的基本配置方法。
|
||||
|
||||
## 功能配置
|
||||
|
||||
> 无论是 [作为 Xposed 模块使用](../config/xposed-using) 还是 [作为 Hook API 使用](../config/api-using),你都可以在 API 装载之前或装载过程中对 `YukiHookAPI` 进行配置。
|
||||
|
||||
### configs 方法
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun configs(initiate: Configs.() -> Unit)
|
||||
```
|
||||
|
||||
`configs` 方法对 `Configs` 类实现了一个 `lambda` 方法体,你可以轻松地调用它进行配置。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiHookAPI.configs](../api/public/com/highcapable/yukihookapi/YukiHookAPI#configs-method) 方法。
|
||||
|
||||
:::
|
||||
|
||||
## Hooker 配置
|
||||
|
||||
> 一个 Xposed 模块或 Hook API 最重要的地方就是 Hooker 的创建与使用,`YukiHookAPI` 提供了两种使用方法。
|
||||
|
||||
### 通过 lambda 创建
|
||||
|
||||
> 这种方案是最简单的,如果你的模块功能不多,代码数量不大,不需要进行分类处理,推荐使用这种方式进行创建。
|
||||
|
||||
#### encase 方法
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
`encase` 方法是 Hook 一切生命的开始,在一个模块或一个 Hook 过程中,`encase` 方法只能作用一次,用于创建 Hooker。
|
||||
|
||||
`PackageParam` 为宿主(目标 APP)的重要实例对象,通过 `PackageParam` 来实现对当前 Hook 作用对象的全部 Hook 操作。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [PackageParam](../api/public/com/highcapable/yukihookapi/hook/param/PackageParam)。
|
||||
|
||||
:::
|
||||
|
||||
`encase` 方法可以在 `onHook` 方法中使用两种方案创建。
|
||||
|
||||
> 示例代码 1
|
||||
|
||||
```kotlin
|
||||
YukiHookAPI.encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 示例代码 2
|
||||
|
||||
```kotlin
|
||||
encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
在 `encase` 方法中进行你的 Hook 操作。
|
||||
|
||||
### 通过自定义 Hooker 创建
|
||||
|
||||
> 这种方案更加适用于大型项目,例如需要对 Hooker 进行分类或对 Hook 的作用对象进行分类。
|
||||
|
||||
#### encase 方法
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(vararg hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
同样为 `encase` 方法,这里的方法可变数组参数 `hooker` 为创建入口提供了一个对象,你可以将所有继承于 `YukiBaseHooker` 的 Hooker 一次性进行装载。
|
||||
|
||||
#### YukiBaseHooker 用法
|
||||
|
||||
`YukiBaseHooker` 继承于 `PackageParam`,你需要将你的子 Hooker 继承于 `YukiBaseHooker`。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiBaseHooker](../api/public/com/highcapable/yukihookapi/entity/YukiBaseHooker)。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
子 Hooker **建议使用**单例 `object` 创建,你也可以使用 `class` 但不推荐。
|
||||
|
||||
::: warning
|
||||
|
||||
你无需再在继承于 **YukiBaseHooker** 的 **onHook** 方法中重新调用 **encase**,这是错误的,且**不会生效**,你应该直接开始编写你的 Hook 代码。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
loadApp(name = "com.example.demo1") {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.example.demo2") {
|
||||
findClass(name = "$packageName.CustomClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
作为子 Hooker 使用,你还可以在外部调用 `loadApp` 方法,然后在内部直接开始 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadApp(name = "com.example.demo", ChildCustomHooker)
|
||||
}
|
||||
}
|
||||
|
||||
object ChildCustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你可以使用 `loadHooker` 方法在子 Hooker 中多层装载另一个 Hooker,请按照你的喜好进行即可。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
object FirstHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
loadHooker(SecondHooker)
|
||||
loadHooker(ThirdHooker)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
搭建完全部 Hooker 后,你就可以在你的 `HookEntryClass` 入口类中的 `onHook` 方法中装载你的 Hooker 了。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() =
|
||||
YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
|
||||
}
|
||||
```
|
||||
|
||||
当然,我们同样可以对其进行简写。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
|
||||
}
|
||||
```
|
||||
|
||||
### 扩展特性
|
||||
|
||||
如果你当前使用的 Hook Framework 支持并启用了资源钩子(Resources Hook)功能,你现在可以直接在 `encase` 中创建 Resources Hook。
|
||||
|
||||
你完全不需要与之前在使用 Xposed API 那样区分 `initZygote`、`handleLoadPackage`、`handleInitPackageResources` 方法来执行不同的功能。
|
||||
|
||||
在 `YukiHookAPI` 中,这些功能**是无缝的**。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
// 创建一个 Resources Hook (固定用法)
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你还可以同时使用 `loadZygote` 方法来装载新的进程被 fork 后的第一个事件 `initZygote`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
encase {
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// 在 Zygote 中创建 Resources Hook
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.example.demo") {
|
||||
findClass(name = "$packageName.DemoClass").hook {
|
||||
// Your code here.
|
||||
}
|
||||
// 在 APP 中创建 Resources Hook
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 注意事项
|
||||
|
||||
直接装载 Hooker 或直接开始 Hook 是错误的,`encase` 事件在被 Hook Framework 装载后,会经历三次回调。
|
||||
|
||||
- 装载 `initZygote` → `encase`
|
||||
|
||||
- 装载 `handleLoadPackage` → `encase`
|
||||
|
||||
- 装载 `handleInitPackageResources` → `encase`
|
||||
|
||||
在这个过程中,你需要使用 `loadApp`、`loadSystem`、`loadZygote` 来区分每一次装载代码的调用域,否则你的代码就会被<u>**多次执行造成错误**</u>。
|
||||
|
||||
::: warning
|
||||
|
||||
无论使用 **encase** 创建 **lambda** 方法体还是直接使用 Hooker 形式,你都不应该直接在首个 **onHook** 事件中直接装载 Hooker 或直接开始 Hook。
|
||||
|
||||
:::
|
||||
|
||||
下面是两个**错误**示例。
|
||||
|
||||
> 示例代码 1
|
||||
|
||||
```kotlin
|
||||
encase {
|
||||
// ❗错误的使用方法,不能直接开始 Hook
|
||||
findClass(name = "com.example.demo.DemoClass").hook {
|
||||
// ...
|
||||
}
|
||||
// ❗错误的使用方法,不能直接开始 Hook
|
||||
resources().hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 示例代码 2
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() {
|
||||
// <情景1>
|
||||
encase {
|
||||
loadHooker(CustomHooker)
|
||||
}
|
||||
// <情景2>
|
||||
encase(CustomHooker)
|
||||
}
|
||||
}
|
||||
|
||||
object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
// ❗错误的使用方法,由于外层没有任何判断对象,不能直接开始 Hook
|
||||
findClass(name = "com.example.demo.DemoClass").hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
下面是上述错误示例的**正确**示例。
|
||||
|
||||
> 示例代码 1
|
||||
|
||||
```kotlin
|
||||
encase {
|
||||
// ✅ 正确的使用方法,在 Zygote 中装载
|
||||
loadZygote(CustomHooker)
|
||||
// ✅ 正确的使用方法,在 Zygote 中装载
|
||||
loadZygote {
|
||||
// ✅ 正确的使用方法,在 Zygote 内 Hook
|
||||
resources().hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
// ✅ 正确的使用方法,使用 APP 作用域装载
|
||||
loadApp(/** name 参数可选 */, hooker = CustomHooker)
|
||||
// ✅ 正确的使用方法,判断 APP 作用域后再装载 Hooker
|
||||
loadApp(/** name 参数可选 */) {
|
||||
loadHooker(CustomHooker)
|
||||
// ✅ 正确的使用方法,在 APP 作用域内 Hook
|
||||
findClass(name = "com.example.demo.DemoClass").hook {
|
||||
// ...
|
||||
}
|
||||
// ✅ 正确的使用方法,在 APP 作用域内 Hook
|
||||
resources().hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 示例代码 2
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() {
|
||||
encase(CustomHooker)
|
||||
}
|
||||
}
|
||||
|
||||
object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
// ✅ 正确的使用方法,由于外层没有任何判断对象,需要判断 APP 作用域后再进行 Hook
|
||||
loadApp(/** name 参数可选 */) {
|
||||
findClass(name = "com.example.demo.DemoClass").hook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 作为 Hook API 使用需要注意的地方
|
||||
|
||||
若你作为 Hook API 使用,那么你只需要在入口处对 `encase` 方法进行区分。
|
||||
|
||||
::: warning
|
||||
|
||||
**encase** 方法对作为 Hook API 使用提供了两个完全一样的方法,但是比前两者仅多出一个参数 **baseContext**。
|
||||
|
||||
:::
|
||||
|
||||
> 方法 1
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
|
||||
```
|
||||
|
||||
> 方法 2
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
|
||||
```
|
||||
|
||||
此处的 `baseContext` 只需填入你在 `attachBaseContext` 处得到的 `Context` 即可,其它用法与上述内容完全一致。
|
||||
|
||||
::: danger
|
||||
|
||||
切勿以 Xposed 方式使用 **encase** 方法而漏掉 **baseContext** 参数,否则你的 Hook 将完全不工作。
|
||||
|
||||
Resources Hook 功能不支持作为 Hook API 使用。
|
||||
|
||||
:::
|
1551
docs-source/src/zh-cn/config/api-exception.md
Normal file
1551
docs-source/src/zh-cn/config/api-exception.md
Normal file
File diff suppressed because it is too large
Load Diff
112
docs-source/src/zh-cn/config/api-using.md
Normal file
112
docs-source/src/zh-cn/config/api-using.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# 作为 Hook API 使用的相关配置
|
||||
|
||||
> 作为 Hook API 通常为做自身 APP 热更新或功能需要以及产品测试的 Hook 操作。
|
||||
|
||||
## 依赖配置
|
||||
|
||||
你只需要集成 `com.highcapable.yukihookapi:api` 依赖即可。
|
||||
|
||||
然后请集成你目标使用的 `Hook Framework` 依赖。
|
||||
|
||||
## 入口配置
|
||||
|
||||
创建你的自定义 `Application`。
|
||||
|
||||
在 `attachBaseContext` 中添加 `YukiHookAPI.encase` 方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
class MyApplication : Application() {
|
||||
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// 装载 Hook Framework
|
||||
//
|
||||
// Your code here.
|
||||
//
|
||||
// 配置 YukiHookAPI
|
||||
YukiHookApi.configs {
|
||||
// Your code here.
|
||||
}
|
||||
// 装载 YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这样,你就完成了 API 的相关配置。
|
||||
|
||||
你可以 [点击这里](../config/api-example#作为-hook-api-使用需要注意的地方) 查看异同点和注意事项。
|
||||
|
||||
::: warning
|
||||
|
||||
你不能再使用 **loadApp** 进行包装,可直接开始编写你的 Hook 代码。
|
||||
|
||||
:::
|
||||
|
||||
## Hook Framework
|
||||
|
||||
> 这里给出了一些较高使用率的 `Hook Framework` 如何对接 `YukiHookAPI` 的相关方式。
|
||||
|
||||
### [Pine](https://github.com/canyie/pine)
|
||||
|
||||
> **所需 Xposed API 依赖** `top.canyie.pine:xposed`
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// 装载 Pine
|
||||
PineConfig.debug = true
|
||||
PineConfig.debuggable = BuildConfig.DEBUG
|
||||
// 装载 YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
||||
|
||||
### [SandHook](https://github.com/asLody/SandHook)
|
||||
|
||||
> **所需 Xposed API 依赖** `com.swift.sandhook:xposedcompat` 或 `com.swift.sandhook:xposedcompat_new`
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// 装载 SandHook
|
||||
SandHookConfig.DEBUG = BuildConfig.DEBUG
|
||||
XposedCompat.cacheDir = base?.cacheDir
|
||||
XposedCompat.context = base
|
||||
XposedCompat.classLoader = javaClass.classLoader
|
||||
XposedCompat.isFirstApplication = base?.processName == base?.packageName
|
||||
// 装载 YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
||||
|
||||
### [Whale](https://github.com/asLody/whale)
|
||||
|
||||
> **所需 Xposed API 依赖** `com.wind.xposed:xposed-on-whale`
|
||||
|
||||
请参考 [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale)。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// 装载 Whale 不需要任何配置
|
||||
// 装载 YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
23
docs-source/src/zh-cn/config/r8-proguard.md
Normal file
23
docs-source/src/zh-cn/config/r8-proguard.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# R8 与 Proguard 混淆
|
||||
|
||||
> 大部分场景下 Xposed 模块可通过原生混淆压缩体积,这里介绍了混淆的配置方法。
|
||||
|
||||
## R8
|
||||
|
||||
> 如果你使用的是 `R8`,那么你无需对 `YukiHookAPI` 进行任何特殊配置。
|
||||
|
||||
## Proguard
|
||||
|
||||
> ~~如果你仍然在使用 `Proguard`,你需要做一些规则配置。~~
|
||||
|
||||
::: danger
|
||||
|
||||
Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 **R8**,不再需要考虑混淆的问题。
|
||||
|
||||
:::
|
||||
|
||||
若要在任何版本下启用 `R8`,请在 `gradle.properties` 文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。
|
||||
|
||||
```groovy
|
||||
android.enableR8=true
|
||||
```
|
280
docs-source/src/zh-cn/config/xposed-using.md
Normal file
280
docs-source/src/zh-cn/config/xposed-using.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# 作为 Xposed 模块使用的相关配置
|
||||
|
||||
> 这里介绍了 `YukiHookAPI` 作为 Xposed 模块使用的相关配置方法。
|
||||
|
||||
## 依赖配置
|
||||
|
||||
> 作为 Xposed 模块,`YukiHookAPI` 提供了一个自动处理程序。
|
||||
|
||||
你需要在你的 `build.gradle` 中集成 `com.highcapable.yukihookapi:ksp-xposed` 依赖的最新版本。
|
||||
|
||||
## 自定义处理程序
|
||||
|
||||
> 你可以对 `YukiHookAPI` 将如何生成 `xposed_init` 入口进行相关配置。
|
||||
|
||||
### InjectYukiHookWithXposed 注解
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
annotation class InjectYukiHookWithXposed(
|
||||
val sourcePath: String,
|
||||
val modulePackageName: String,
|
||||
val entryClassName: String,
|
||||
val isUsingResourcesHook: Boolean
|
||||
)
|
||||
```
|
||||
|
||||
`@InjectYukiHookWithXposed` 注解是一个标记模块 Hook 入口的重要注解。
|
||||
|
||||
::: danger
|
||||
|
||||
**@InjectYukiHookWithXposed** 注解的 **Class** 必须实现 **IYukiHookXposedInit** 接口。
|
||||
|
||||
在你当前项目中的所有 **Class** 标记中**只能存在一次**,若存在多个声明自动处理程序<u>**会在编译时抛出异常**</u>,你可以自定义其相关参数。
|
||||
|
||||
:::
|
||||
|
||||
#### sourcePath 参数
|
||||
|
||||
`sourcePath` 参数决定了自动处理程序自动查找并匹配你当前项目路径的重要标识,此参数的内容为相对路径匹配,默认参数为 `src/main`。
|
||||
|
||||
::: danger
|
||||
|
||||
如果你的项目不在 **../src/main..** 或你手动使用 **sourceSets** 设置了项目路径,你就需要手动设置 **sourcePath** 参数,否则自动处理程序将无法识别你的项目路径并<u>**会在编译时抛出异常**</u>。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(sourcePath = "src/custom")
|
||||
```
|
||||
|
||||
`sourcePath` 使用的文件路径分隔符写法根据 `Windows` 和 `Unix` 将自动进行识别,使用 `/` 或 `\` 均可。
|
||||
|
||||
#### modulePackageName 参数
|
||||
|
||||
`modulePackageName` 是你当前项目的 `applicationId`,也就是你的模块包名 (最终生成的应用包名),留空或不填时自动处理程序将对当前项目文件进行分析并生成。
|
||||
|
||||
::: warning
|
||||
|
||||
若你想使用模块包名自动生成,你需要确保你的项目命名空间在 **AndroidManifest.xml**、**build.gradle** 或 **build.gradle.kts** 中存在如下任意定义方式。
|
||||
|
||||
:::
|
||||
|
||||
示例命名空间 `com.example.demo`,以下定义方式任选其一。
|
||||
|
||||
以下定义方式仅供参考,通常情况下**只要你的项目能够正常生成 `BuildConfig.java` 文件,就不需要做额外操作**。
|
||||
|
||||
> `AndroidManifest.xml` 示例
|
||||
|
||||
```xml
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.demo">
|
||||
```
|
||||
|
||||
> `build.gradle` 示例
|
||||
|
||||
```groovy
|
||||
android {
|
||||
namespace 'com.example.demo'
|
||||
}
|
||||
```
|
||||
|
||||
> `build.gradle.kts` 示例
|
||||
|
||||
```kotlin
|
||||
android {
|
||||
namespace = "com.example.demo"
|
||||
}
|
||||
```
|
||||
|
||||
若你的模块包名是非常规手段进行自动生成的,或你认为有必要手动定义模块包名,那么你可以直接设置 `modulePackageName` 的参数。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
|
||||
```
|
||||
|
||||
只要你自定义了 `modulePackageName` 的参数,你就会在编译时收到警告。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
You set the customize module package name to "com.example.demo", please check for yourself if it is correct
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
手动定义的模块包名除了格式之外,自动处理程序将不会再检查模块包名是否正确,需要你自行确认其有效性。
|
||||
|
||||
:::
|
||||
|
||||
#### entryClassName 参数
|
||||
|
||||
`entryClassName` 决定了自动处理程序如何生成 `xposed_init` 中的入口类名,默认会使用你的入口类包名插入 `_YukiHookXposedInit` 后缀进行生成。
|
||||
|
||||
假设这是你的入口类。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry: IYukiHookXposedInit
|
||||
```
|
||||
|
||||
Xposed 入口类处理如下。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
|
||||
```
|
||||
|
||||
编译后的类名结构如下。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
...hook.HookEntry ← 你的入口类
|
||||
...hook.HookEntry_Impl ← 自动生成的 Impl 类
|
||||
...hook.HookEntry_YukiHookXposedInit ← 自动生成的 Xposed 入口类
|
||||
```
|
||||
|
||||
我们现在定义入口类名称为 `HookXposedEntry`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
|
||||
class HookEntry: IYukiHookXposedInit
|
||||
```
|
||||
|
||||
Xposed 入口类处理如下。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
|
||||
```
|
||||
|
||||
编译后的类名结构如下。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```:no-line-numbers
|
||||
...hook.HookEntry ← 你的入口类
|
||||
...hook.HookEntry_Impl ← 自动生成的 Impl 类
|
||||
...hook.HookXposedEntry ← 自动生成的 Xposed 入口类
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
你定义的 **entryClassName** 不可与 **xposed_init** 中的类名相同,否则自动处理程序<u>会在编译时抛出异常</u>。
|
||||
|
||||
:::
|
||||
|
||||
#### isUsingResourcesHook 参数
|
||||
|
||||
`isUsingResourcesHook` 决定了自动处理程序是否生成针对 Resources Hook 的相关代码,此功能默认是启用的。
|
||||
|
||||
启用后生成的入口类将为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若你当前的项目并不需要用到 Reources Hook,可以设置 `isUsingResourcesHook = false` 来关闭自动生成。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||
```
|
||||
|
||||
关闭后生成的入口类将为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### IYukiHookXposedInit 接口
|
||||
|
||||
`IYukiHookXposedInit` 接口为你的 `HookEntryClass` 必须实现的接口,这是你的模块开始 Hook 的起点。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [IYukiHookXposedInit](../api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit)。
|
||||
|
||||
:::
|
||||
|
||||
当你的模块被 Xposed 装载后,`onHook` 方法将会被回调,你需要在此方法中开始使用 `YukiHookAPI`。
|
||||
|
||||
> 基本的调用流程为 `_YukiHookXposedInit` → `IYukiHookXposedInit.onXposedEvent` → `IYukiHookXposedInit.onInit` → `IYukiHookXposedInit.onHook`
|
||||
|
||||
详情请参考 [API 基本配置](../config/api-example)。
|
||||
|
||||
## 原生 Xposed API 事件
|
||||
|
||||
若你当前的 Xposed 模块使用了第三方的资源,但是短时间内可能无法转移它们,此时,你可以使用 `onXposedEvent` 实现监听原生 Xposed API 的全部装载事件。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry: IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun onXposedEvent() {
|
||||
// 监听原生 Xposed API 的装载事件
|
||||
YukiXposedEvent.events {
|
||||
onInitZygote {
|
||||
// it 对象即 [StartupParam]
|
||||
}
|
||||
onHandleLoadPackage {
|
||||
// it 对象即 [LoadPackageParam]
|
||||
}
|
||||
onHandleInitPackageResources {
|
||||
// it 对象即 [InitPackageResourcesParam]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`onXposedEvent` 与 `onHook` 方法完全独立存在,互不影响,你可以继续在 `onHook` 方法中使用 `YukiHookAPI`。
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [IYukiHookXposedInit.onXposedEvent](../api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit#onxposedevent-method) 方法。
|
||||
|
||||
:::
|
677
docs-source/src/zh-cn/guide/example.md
Normal file
677
docs-source/src/zh-cn/guide/example.md
Normal file
@@ -0,0 +1,677 @@
|
||||
# 用法示例
|
||||
|
||||
> 这里介绍了 `YukiHookAPI` 的基本工作方式以及列举了简单的 Hook 例子和常用功能。
|
||||
|
||||
## 结构图解
|
||||
|
||||
> 下方的结构描述了 `YukiHookAPI` 的基本工作方式和原理。
|
||||
|
||||
```:no-line-numbers
|
||||
Host Environment
|
||||
└── YukiMemberHookCreator
|
||||
└── Class
|
||||
└── MemberHookCreator
|
||||
└── Member
|
||||
├── Before
|
||||
└── After
|
||||
MemberHookCreator
|
||||
└── Member
|
||||
├── Before
|
||||
└── After
|
||||
...
|
||||
YukiResourcesHookCreator
|
||||
└── Resources
|
||||
└── ResourcesHookCreator
|
||||
└── Drawable
|
||||
└── Replace
|
||||
ResourcesHookCreator
|
||||
└── Layout
|
||||
└── Inject
|
||||
...
|
||||
```
|
||||
|
||||
> 上方的结构换做代码将可写为如下形式。
|
||||
|
||||
```kotlin
|
||||
TargetClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
// Your code here.
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
// Your code here.
|
||||
}
|
||||
replaceTo(...)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
> 你可以在下方找到 API 提供的 Demo 来学习 `YukiHookAPI` 的使用方法。
|
||||
|
||||
- 宿主 APP Demo [点击这里查看](https://github.com/fankes/YukiHookAPI/tree/master/demo-app)
|
||||
|
||||
- 模块 APP Demo [点击这里查看](https://github.com/fankes/YukiHookAPI/tree/master/demo-module)
|
||||
|
||||
同时安装宿主和模块 Demo,通过激活模块来测试宿主中被 Hook 的功能。
|
||||
|
||||
## 一个简单的 Hook 例子
|
||||
|
||||
> 这里给出了 Hook APP、Hook 系统框架与 Hook Resources 等例子,可供参考。
|
||||
|
||||
### Hook APP
|
||||
|
||||
假设,我们要 Hook `com.android.browser` 中的 `onCreate` 方法并弹出一个对话框。
|
||||
|
||||
在 `encase` 方法体中添加代码。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
AlertDialog.Builder(instance())
|
||||
.setTitle("Hooked")
|
||||
.setMessage("I am hook!")
|
||||
.setPositiveButton("OK", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
至此,`onCreate` 方法将被成功 Hook 并在 `com.android.browser` 中的每个 `Activity` 启动时弹出此对话框。
|
||||
|
||||
那么,我想继续 Hook `onStart` 方法要怎么做呢?
|
||||
|
||||
在刚刚的代码中,继续插入一个 `injectMember` 方法体即可。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
AlertDialog.Builder(instance())
|
||||
.setTitle("Hooked")
|
||||
.setMessage("I am hook!")
|
||||
.setPositiveButton("OK", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method {
|
||||
name = "onStart"
|
||||
emptyParam()
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
对于当前项目下没有的 `Class`,你可以使用 `stub` 方式或 `findClass` 方法来得到需要 Hook 的类。
|
||||
|
||||
比如,我要得到 `com.example.demo.TestClass`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass(name = "com.example.demo.TestClass").hook {
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若 `com.example.demo` 是你要 Hook 的 APP,那么写法可以更简单。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
findClass(name = "$packageName.TestClass").hook {
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
到这里有些同学可能就开始说了,在某些场景下 `findClass` 显得有些繁琐。
|
||||
|
||||
因为可能有些同学有如下需求。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
const val TestClass = "com.example.demo.TestClass"
|
||||
|
||||
TestClass.hook {
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
没关系,你还可以使用字符串类名直接创建一个 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"$packageName.TestClass".hook {
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [MemberHookCreator](../api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator#memberhookcreator-class)。
|
||||
|
||||
:::
|
||||
|
||||
### Hook Zygote
|
||||
|
||||
在 APP 启动时,新的进程被 fork 后的第一个事件 `initZygote`。
|
||||
|
||||
假设我们要全局 Hook 一个 APP `Activity` 的 `onCreate` 事件
|
||||
|
||||
在 `encase` 方法体中添加代码。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
在 **loadZygote** 中进行的功能十分有限,几乎很少的情况下需要用到 **loadZygote** 方法。
|
||||
|
||||
:::
|
||||
|
||||
### Hook 系统框架
|
||||
|
||||
在 `YukiHookAPI` 中,Hook 系统框架的实现非常简单。
|
||||
|
||||
假设,你要得到 `ApplicationInfo` 与 `PackageInfo` 并对它们进行一些操作。
|
||||
|
||||
在 `encase` 方法体中添加代码。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadSystem {
|
||||
ApplicationInfoClass.hook {
|
||||
// Your code here.
|
||||
}
|
||||
PackageInfoClass.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
**loadZygote** 与 **loadSystem** 有直接性区别,**loadZygote** 会在 **initZygote** 中装载,系统框架被视为 **loadApp(name = "android")** 而存在,若要 Hook 系统框架,可直接使用 **loadSystem**。
|
||||
|
||||
:::
|
||||
|
||||
### Hook Resources
|
||||
|
||||
假设,我们要 Hook `com.android.browser` 中 `string` 类型的 `app_name` 内容替换为 `123`。
|
||||
|
||||
在 `encase` 方法体中添加代码。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "app_name"
|
||||
string()
|
||||
}
|
||||
replaceTo("123")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若当前 APP 使用 `app_name` 设置了标题栏文本,则它就会变成我们的 `123`。
|
||||
|
||||
你还可以使用当前 Xposed 模块的 Resources 替换 Hook APP 的 Resources。
|
||||
|
||||
假设,我们要继续 Hook `com.android.browser` 中 `mipmap` 类型的 `ic_launcher`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
至此目标 APP 的图标将会被替换为我们设置的图标。
|
||||
|
||||
若你想替换系统框架的资源,同样也可以这样实现,只需要把 `loadApp` 换成 `loadZygote` 即可。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadZygote {
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [ResourcesHookCreator](../api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator#resourceshookcreator-class)。
|
||||
|
||||
:::
|
||||
|
||||
### 解除 Hook
|
||||
|
||||
原生的 Xposed 为我们提供了一个 `XC_MethodHook.Unhook` 功能,可以从 Hook 队列中将当前 Hook 移除,`YukiHookAPI` 同样可以实现此功能。
|
||||
|
||||
第一种方法,保存当前注入对象的 `Result` 实例,在适当的时候和地方调用 `remove` 即可解除该注入对象。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 设置一个变量保存当前实例
|
||||
val hookResult = injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
// 在适当的时候调用如下方法即可
|
||||
hookResult.remove()
|
||||
```
|
||||
|
||||
第二种方法,在 Hook 回调方法中调用 `removeSelf` 移除自身。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
// 直接调用如下方法即可
|
||||
removeSelf()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [MemberHookCreator](../api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator#memberhookcreator-class)。
|
||||
|
||||
:::
|
||||
|
||||
## 异常处理
|
||||
|
||||
> `YukiHookAPI` 重新设计了对异常的监听,任何异常都不会在 Hook 过程中抛出,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。
|
||||
|
||||
### 监听异常
|
||||
|
||||
你可以处理 Hook 方法过程发生的异常。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}.result {
|
||||
// 处理 Hook 开始时的异常
|
||||
onHookingFailure {}
|
||||
// 处理 Hook 过程中的异常
|
||||
onConductFailure { param, throwable -> }
|
||||
// 处理全部异常
|
||||
onAllFailure {}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
在 Resources Hook 时此方法同样适用。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectResource {
|
||||
// Your code here.
|
||||
}.result {
|
||||
// 处理 Hook 时的任意异常
|
||||
onHookingFailure {}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
你还可以处理 Hook 的 `Class` 不存在时发生的异常。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
TargetClass.hook {
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}
|
||||
}.onHookClassNotFoundFailure {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
你还可以处理查找方法时的异常。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
method {
|
||||
// Your code here.
|
||||
}.onNoSuchMethod {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [MemberHookCreator.Result](../api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator#result-class)、[ResourcesHookCreator.Result](../api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator#result-class)。
|
||||
|
||||
:::
|
||||
|
||||
这里介绍了可能发生的常见异常,若要了解更多请参考 [API 异常处理](../config/api-exception)。
|
||||
|
||||
### 抛出异常
|
||||
|
||||
在某些情况下,你可以**手动抛出异常**来达到提醒某些功能存在问题的目的。
|
||||
|
||||
上面已经介绍过,在 `hook` 方法体内抛出的异常会被 `YukiHookAPI` 接管,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。
|
||||
|
||||
以下是 `YukiHookAPI` 接管时这些异常的运作方式。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// <情景1>
|
||||
injectMember {
|
||||
method {
|
||||
throw RuntimeException("Exception Test")
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}.result {
|
||||
// 能够捕获到 RuntimeException
|
||||
onHookingFailure {}
|
||||
}
|
||||
// <情景2>
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
throw RuntimeException("Exception Test")
|
||||
}
|
||||
}.result {
|
||||
// 能够捕获到 RuntimeException
|
||||
onConductFailure { param, throwable -> }
|
||||
}
|
||||
```
|
||||
|
||||
以上情景只会在 (Xposed) 宿主环境被处理,不会对宿主自身造成任何影响。
|
||||
|
||||
若我们想将这些异常直接抛给宿主,原生的 Xposed 为我们提供了 `param.throwable` 方法,`YukiHookAPI` 同样可以实现此功能。
|
||||
|
||||
若想在 Hook 回调方法体中将一个异常直接抛给宿主,可以有如下实现方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
RuntimeException("Exception Test").throwToApp()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
你也可以直接在 Hook 回调方法体中抛出异常,然后标识将异常抛给宿主。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
throw RuntimeException("Exception Test")
|
||||
}.onFailureThrowToApp()
|
||||
}
|
||||
```
|
||||
|
||||
以上两种方法均可在宿主接收到异常从而使宿主进程崩溃。
|
||||
|
||||
::: warning
|
||||
|
||||
为了保证 Hook 调用域与宿主内调用域相互隔离,异常只有在 **beforeHook** 与 **afterHook** 回调方法体中才能抛给宿主。
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [Throwable.throwToApp](../api/public/com/highcapable/yukihookapi/hook/param/HookParam#throwable-throwtoapp-i-ext-method)、[YukiMemberHookCreator.MemberMookCreator.HookCallback](../api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator#hookcallback-class)。
|
||||
|
||||
:::
|
||||
|
||||
## 状态监听
|
||||
|
||||
在使用 `XposedHelpers` 的同学往往会在 Hook 后打印 `Unhook` 的方法确定是否 Hook 成功。
|
||||
|
||||
在 `YukiHookAPI` 中,你可以用以下方法方便地重新实现这个功能。
|
||||
|
||||
首先我们可以监听 Hook 已经准备开始。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
YourClass.hook {
|
||||
// Your code here.
|
||||
}.onPrepareHook {
|
||||
loggerD(msg = "$instanceClass hook start")
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
**instanceClass** 建议只在 **onPrepareHook** 中使用,否则被 Hook 的 **Class** 不存在会抛出无法拦截的异常导致 Hook 进程“死掉”。
|
||||
|
||||
:::
|
||||
|
||||
然后,我们还可以对 Hook 的方法结果进行监听是否成功。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}.onHooked { member ->
|
||||
loggerD(msg = "$member has hooked")
|
||||
}
|
||||
```
|
||||
|
||||
## 扩展用法
|
||||
|
||||
> 你可以在 Hook 过程中使用下面的方法方便地实现各种判断和功能。
|
||||
|
||||
### 多个宿主
|
||||
|
||||
如果你的模块需要同时处理多个 APP 的 Hook 事件,你可以使用 `loadApp` 方法体来区分你要 Hook 的 APP。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
// Your code here.
|
||||
}
|
||||
loadApp(name = "com.android.phone") {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [PackageParam.loadApp](../api/public/com/highcapable/yukihookapi/hook/param/PackageParam#loadapp-method)。
|
||||
|
||||
:::
|
||||
|
||||
### 多个进程
|
||||
|
||||
如果你 Hook 的宿主 APP 有多个进程,你可以使用 `withProcess` 方法体来对它们分别进行 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
withProcess(mainProcessName) {
|
||||
// Your code here.
|
||||
}
|
||||
withProcess(name = "$packageName:tool") {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [PackageParam.withProcess](../api/public/com/highcapable/yukihookapi/hook/param/PackageParam#withprocess-method)。
|
||||
|
||||
:::
|
||||
|
||||
## 写法优化
|
||||
|
||||
为了使代码更加简洁,你可以删去 `YukiHookAPI` 的名称,将你的 `onHook` 入口写作 `lambda` 形式。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
override fun onHook() = encase {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
## Xposed 模块判断自身激活状态
|
||||
|
||||
通常情况下,我们会选择写一个方法,使其返回 `false`,然后 Hook 掉这个方法使其返回 `true` 来证明 Hook 已经生效。
|
||||
|
||||
在 `YukiHookAPI` 中你完全不需要再这么做了,`YukiHookAPI` 已经帮你封装好了这个操作,你可以直接进行使用。
|
||||
|
||||
现在,你可以直接使用 `YukiHookAPI.Status.isXposedModuleActive` 在模块中判断自身是否被激活。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if(YukiHookAPI.Status.isXposedModuleActive) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
由于一些特殊原因,在太极、无极中的模块无法使用标准方法检测激活状态。
|
||||
|
||||
此时你可以使用 `YukiHookAPI.Status.isTaiChiModuleActive` 判断自身是否被激活。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if(YukiHookAPI.Status.isTaiChiModuleActive) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
若你想使用两者得兼的判断方案,`YukiHookAPI` 同样为你封装了便捷的方式。
|
||||
|
||||
此时你可以使用 `YukiHookAPI.Status.isModuleActive` 判断自身是否在 Xposed 或太极、无极中被激活。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if(YukiHookAPI.Status.isModuleActive) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
更多功能请参考 [YukiHookAPI.Status](../api/public/com/highcapable/yukihookapi/YukiHookAPI#status-object)。
|
||||
|
||||
:::
|
||||
|
||||
::: warning
|
||||
|
||||
若模块激活判断中包含太极、无极中的激活状态,就必须将模块的 **Application** 继承于 **ModuleApplication** 或直接使用 **ModuleApplication**;
|
||||
|
||||
**1.0.91** 版本后的 API 修改了激活逻辑判断方式,现在你可以在模块与 Hook APP (宿主) 中同时使用此 API;
|
||||
|
||||
需要确保 **YukiHookAPI.Configs.isEnableHookModuleStatus** 是启用状态;
|
||||
|
||||
除了提供标准 API 的 Hook 框架之外,其它情况下模块可能都将无法判断自己是否被激活。
|
||||
|
||||
:::
|
186
docs-source/src/zh-cn/guide/home.md
Normal file
186
docs-source/src/zh-cn/guide/home.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# 介绍
|
||||
|
||||
> 这是一个 Hook API 框架,本身不提供任何 Hook 功能,需要 Xposed 基础 API 的支持。
|
||||
|
||||
## 背景
|
||||
|
||||
这是一个使用 `Kotlin` 重新构建的高效 Xposed Hook API。
|
||||
|
||||
名称取自 [《ももくり》女主 栗原 雪(Yuki)](https://www.bilibili.com/bangumi/play/ss5016)。
|
||||
|
||||
前身为 [开发学习项目](https://github.com/fankes/TMore) 中使用的 Innocent Xposed API,现在重新命名并开源。
|
||||
|
||||
## 用途
|
||||
|
||||
`YukiHookAPI` 完全采用 `Kotlin` `lambda` 语法构建。
|
||||
|
||||
抛弃原始不太友好的 `XposedHelpers`,你可以使用它来轻松创建 Xposed 模块以及轻松实现自定义 Hook API。
|
||||
|
||||
## 语言要求
|
||||
|
||||
请使用 `Kotlin`,框架部分代码构成同样兼容 `Java` 但基础 Hook 场景的实现**可能完全无法使用**。
|
||||
|
||||
文档全部的 Demo 示例代码都将使用 `Kotlin` 进行描述,如果你完全不会使用 `Kotlin` 那你将有可能无法使用 `YukiHookAPI`。
|
||||
|
||||
部分 Java Demo 代码可在 [这里](https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java) 找到,但不推荐使用。
|
||||
|
||||
## 灵感来源
|
||||
|
||||
以前,我们在构建 Xposed 模块的时候,首先需要在 `assets` 下创建 `xposed_init` 文件。
|
||||
|
||||
然后,将自己的入口类名手动填入文件中,使用 `XposedHelpers` 去实现我们的 Hook 逻辑。
|
||||
|
||||
自 `Kotlin` 作为 Android 主要开发语言以来,这套 API 用起来确实已经不是很优雅了。
|
||||
|
||||
有没有什么 **好用、轻量、优雅** 的解决办法呢?
|
||||
|
||||
本着这样的想法,`YukiHookAPI` 诞生了。
|
||||
|
||||
现在,我们只需要编写少量的代码,一切时间开销和花费交给自动化处理。
|
||||
|
||||
借助 `Kotlin` 优雅的 `lambda` 写法以及 `YukiHookAPI`,可以让你的 Hook 逻辑更加美观清晰。
|
||||
|
||||
> 示例如下
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "sym_def_app_icon"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||
XResources.setSystemWideReplacement(
|
||||
"android", "mipmap", "sym_def_app_icon",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity::class.java.name,
|
||||
null, "onCreate",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
if (lpparam.packageName == "com.android.browser")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity::class.java.name,
|
||||
lpparam.classLoader, "onCreate",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
if (resparam.packageName == "com.android.browser")
|
||||
resparam.res.setReplacement(
|
||||
"com.android.browser", "mipmap", "ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
是的,你没有看错,仅仅就需要这些代码,就能完全取代 Xposed API 实现同样的功能。
|
||||
|
||||
现在,借助高效强大的 `YukiHookAPI`,你就可以实现一个非常简单的 Xposed 模块。
|
||||
|
||||
## 支持的 Hook 框架
|
||||
|
||||
以下是 `YukiHookAPI` 支持的 `Hook Framework` 以及 Xposed 框架。
|
||||
|
||||
| Hook Framework | ST | Description |
|
||||
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
|
||||
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | 多场景下稳定使用 |
|
||||
| [LSPatch](https://github.com/LSPosed/LSPatch) | ⭕ | 将在此项目完善后逐渐加入 API 支持 |
|
||||
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ❎ | 已停止维护,不再推荐使用 |
|
||||
| [Pine](https://github.com/canyie/pine) | ⭕ | 可以使用 |
|
||||
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | 可以使用 |
|
||||
| [Whale](https://github.com/asLody/whale) | ⭕ | 需要 [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
|
||||
| [YAHFA](https://github.com/PAGalaxyLab/YAHFA) | ❗ | 需要自行实现 Xposed API |
|
||||
| [FastHook](https://github.com/turing-technician/FastHook) | ❗ | 需要自行实现 Xposed API |
|
||||
| [Epic](https://github.com/tiann/epic) | ❗ | 需要自行对接 [Dexposed](https://github.com/alibaba/dexposed) |
|
||||
| [TaiChi](https://github.com/taichi-framework/TaiChi) | ⭕ | 可以作为模块使用 |
|
||||
| [Xposed](https://github.com/rovo89/Xposed) | ❎ | 未测试,不再推荐使用 |
|
85
docs-source/src/zh-cn/guide/knowledge.md
Normal file
85
docs-source/src/zh-cn/guide/knowledge.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 基础知识
|
||||
|
||||
> 这里收集了 Xposed 相关的介绍以及开启前需要掌握的知识要点,已经了解的同学可以略过。
|
||||
|
||||
基础知识内容<u>**并不一定完全准确**</u>,请根据自己的见解酌情阅读,若发现内容**有错误欢迎指正并帮助我们完善和改进**。
|
||||
|
||||
## 相关介绍
|
||||
|
||||
> 这里介绍了 Xposed 以及 Hook 的工作原理。
|
||||
|
||||
### Xposed 是什么
|
||||
|
||||
> Xposed 框架(Xposed Framework)是一套开源的、在 Android 高权限模式下运行的框架服务,可以在不修改 APK 文件的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。
|
||||
|
||||
上述内容复制自百度百科。
|
||||
|
||||
### Xposed 能做什么
|
||||
|
||||
> 下方的结构描述了 Xposed 的基本工作方式和原理。
|
||||
|
||||
```:no-line-numbers
|
||||
Xposed Framework
|
||||
└── App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
我们可以在宿主 (APP) 运行时通过注入宿主 (APP) 来达到控制其行为的最终目的。
|
||||
|
||||
Xposed 的这种运行方式被称为**寄生**,Xposed 模块跟随宿主的生命周期,在宿主的生命周期内完成自己的生命历程。
|
||||
|
||||
我们可以通过反射的方式调用宿主的方法、变量、构造方法,以及使用 `XposedBridge` 所提供的 Hook 操作动态地在宿主 (APP) 要执行的方法前后插入自己的代码,或完全替换目标,甚至是拦截。
|
||||
|
||||
### 发展过程
|
||||
|
||||
如今的 Xposed 管理器已完全被其衍生作品替代,而 **SuperSU** 的时代也已经落幕了,现在,借助 **Magisk** 使后面的一切又成为了可能。
|
||||
|
||||
> 其发展史大致可分为 **Xposed(Dalvik)** → **Xposed(ART)** → **Xposed(Magisk)** → **EdXposed(Riru)**/**LSPosed(Riru/Zygisk)**
|
||||
|
||||
### 衍生产品
|
||||
|
||||
> 下方的结构描述了类似 Xposed 的 Hook Framework 的工作方式和原理。
|
||||
|
||||
```:no-line-numbers
|
||||
App's Environment
|
||||
└── Hook Framework
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
```
|
||||
|
||||
通过 Xposed 的运行原理,从而衍生了很多同类型框架,随着当今时代的移动设备获取 Root 权限甚至刷机越来越困难且不是刚需的时候,一些免 Root 框架也随之产生,例如**太极**。
|
||||
|
||||
这些在 ART 层面上的 Hook 框架同样也可不借助 Xposed API 完成其和 Xposed 原理一样的 Hook 流程,免 Root 的运行原理为修改 APK 并将 Hook 进程注入宿主,通过外部模块对其进行控制。
|
||||
|
||||
另外一种产品就是利用 Android 运行环境现有的功能虚拟出一个完全与当前设备系统一样的环境,并在其中运行 APP,这个就是虚拟 APP 技术 **VirtualApp**,后来衍生为 **VirtualXposed**。
|
||||
|
||||
上述提到的免 Root 框架分别为**太极/无极**、**VirtualXposed/SandVXposed**。
|
||||
|
||||
### YukiHookAPI 做了什么
|
||||
|
||||
自从 Xposed 出现到现在为止,除了开发者人人皆知的 `XposedHelpers`,依然没有一套针对 `Kotlin` 打造的语法糖以及用法封装十分完善的 API。
|
||||
|
||||
本 API 框架的诞生就是希望在 Xposed 的如今时代,能让更多有动手能力的 Xposed 模块开发者少走弯路,更容易、更简单地完成整个开发流程。
|
||||
|
||||
未来,`YukiHookAPI` 将在使用 Xposed API 的目标基础上适配更多第三方 Hook 框架,使得整个生态得到完善,并帮助更多开发者让 Xposed 模块开发变得更加简单和易懂。
|
||||
|
||||
## 让我们开始吧
|
||||
|
||||
在开始之前,你需要拥有以下基础才能更好地使用 `YukiHookAPI`。
|
||||
|
||||
- 掌握并了解 Android 开发及简单的系统运行原理
|
||||
|
||||
- 掌握并了解 Android APK 内部结构以及简单的反编译知识要领,可参考 [Jadx](https://github.com/skylot/jadx) 与 [ApkTool](https://github.com/iBotPeaches/Apktool)
|
||||
|
||||
- 掌握并熟练使用 Java 反射,了解简单的 Smali 语法,了解 DEX 文件结构,会使用逆向分析定位方法位置
|
||||
|
||||
- 掌握基础的原生 [Xposed API](https://api.xposed.info) 用法,了解 Xposed 的运行原理,可参考本文以及 [这里](https://blog.ketal.icu/2022/01/13/Xposed%E6%A8%A1%E5%9D%97%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8%E4%BF%9D%E5%A7%86%E7%BA%A7%E6%95%99%E7%A8%8B) **(友情链接)**
|
||||
|
||||
- 掌握 Kotlin 语言,学会灵活运用 [Kotlin lambda](https://blog.ketal.icu/2022/01/01/kotlin-lambda%E5%85%A5%E9%97%A8) **(友情链接)**
|
||||
|
||||
- 掌握并了解 Kotlin 与 Java 混编、互相调用以及 Kotlin 生成的 Java 字节码
|
259
docs-source/src/zh-cn/guide/move-to-new-api.md
Normal file
259
docs-source/src/zh-cn/guide/move-to-new-api.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# 从 Xposed API 迁移
|
||||
|
||||
> 若你熟悉 Xposed API,你可以参考下方的相同点将自己的 API 快速迁移到 `YukiHookAPI`。
|
||||
|
||||
## 迁移 Hook 入口点
|
||||
|
||||
> 从 `XC_LoadPackage.LoadPackageParam` 迁移至 `PackageParam`。
|
||||
|
||||
`YukiHookAPI` 对 `PackageParam` 实现了 `lambda` 方法体 `this` 用法,在 `encase` 方法体内即可全局得到 `PackageParam` 对象。
|
||||
|
||||
> API 功能差异对比如下
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
override fun onHook() = encase {
|
||||
// 得到当前 Hook 的包名
|
||||
packageName
|
||||
// 得到当前 Hook 的 ApplicationInfo
|
||||
appInfo
|
||||
// 得到系统上下文对象
|
||||
systemContext
|
||||
// 得到宿主 Application 生命周期
|
||||
appContext
|
||||
// Hook 指定的 APP
|
||||
loadApp(name = "com.demo.test") {
|
||||
// Class Hook
|
||||
findClass("com.demo.test.TestClass").hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(BooleanType)
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (固定用法)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
// 得到当前 Hook 的包名
|
||||
lpparam.packageName
|
||||
// 得到当前 Hook 的 ApplicationInfo
|
||||
lpparam.applicationInfo
|
||||
// 得到系统上下文对象
|
||||
// 在原生 Xposed API 中没有现成的调用方法,你需要自行反射 ActivityThread 来实现
|
||||
// 得到宿主 Application 生命周期
|
||||
AndroidAppHelper.currentApplication()
|
||||
// Class Hook
|
||||
if(lpparam.packageName == "com.demo.test")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.demo.test.TestClass", lpparam.classLoader,
|
||||
"test", Boolean::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
// 得到当前 Hook 的包名
|
||||
resparam.packageName
|
||||
// Resources Hook
|
||||
resparam.res.setReplacement(
|
||||
"com.demo.test", "mipmap","ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## 迁移 Hook 方法体
|
||||
|
||||
> 从 `XC_MethodHook.MethodHookParam` 迁移至 `HookParam`。
|
||||
|
||||
### Before/After Hook
|
||||
|
||||
`YukiHookAPI` 同样对 `HookParam` 实现了 `lambda` 方法体 `this` 用法,在 `beforeHook`、`afterHook` 等方法体内即可全局得到 `HookParam` 对象。
|
||||
|
||||
> API 功能差异对比如下
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
afterHook {
|
||||
// 得到当前 Hook 的实例
|
||||
instance
|
||||
// 得到当前 Hook 的 Class 实例
|
||||
instanceClass
|
||||
// 得到并 cast 当前 Hook 的实例为指定类型 T
|
||||
instance<T>()
|
||||
// 得到方法参数数组
|
||||
args
|
||||
// 得到方法参数的第一位 T
|
||||
args().first().cast<T>()
|
||||
// 得到方法参数的最后一位 T
|
||||
args().last().cast<T>()
|
||||
// 得到方法参数的任意下标 T,这里用 2 举例
|
||||
args(index = 2).cast<T>()
|
||||
// 设置方法参数的任意下标,这里用 2 举例
|
||||
args(index = 2).set(...)
|
||||
// 得到返回值
|
||||
result
|
||||
// 得到返回值并 cast 为 T
|
||||
result<T>()
|
||||
// 修改返回值内容
|
||||
result = ...
|
||||
// 删除返回值内容
|
||||
resultNull()
|
||||
// 向 Hook APP 抛出异常
|
||||
Throwable("Fatal").throwToApp()
|
||||
// 执行未经 Hook 的原始方法并使用原始方法参数调用,泛型可略
|
||||
callOriginal<Any?>()
|
||||
// 执行未经 Hook 的原始方法并自定义方法参数调用,泛型可略
|
||||
invokeOriginal<Any?>(...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// 得到当前 Hook 的实例
|
||||
param.thisObject
|
||||
// 得到当前 Hook 的 Class 实例
|
||||
param.thisObject.javaClass
|
||||
// 得到并 cast 当前 Hook 的实例为指定类型 T
|
||||
param.thisObject as T
|
||||
// 得到方法参数数组
|
||||
param.args
|
||||
// 得到方法参数的第一位 T
|
||||
param.args[0] as T
|
||||
// 得到方法参数的最后一位 T
|
||||
param.args[param.args.lastIndex] as T
|
||||
// 得到方法参数的任意下标 T,这里用 2 举例
|
||||
param.args[2] as T
|
||||
// 设置方法参数的任意下标,这里用 2 举例
|
||||
param.args[2] = ...
|
||||
// 得到返回值
|
||||
param.result
|
||||
// 得到返回值并 cast 为 T
|
||||
param.result as T
|
||||
// 修改返回值内容
|
||||
param.result = ...
|
||||
// 删除返回值内容
|
||||
param.result = null
|
||||
// 向 Hook APP 抛出异常
|
||||
param.throwable = Throwable("Fatal")
|
||||
// 执行未经 Hook 的原始方法
|
||||
XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
### Replace Hook
|
||||
|
||||
`replaceHook` 方法比较特殊,`YukiHookAPI` 为它做出了多种形式以供选择。
|
||||
|
||||
> API 功能差异对比如下
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
/// 无返回值的方法 void
|
||||
|
||||
replaceUnit {
|
||||
// 直接在这里实现被替换的逻辑
|
||||
}
|
||||
|
||||
/// 有返回值的方法
|
||||
|
||||
replaceAny {
|
||||
// 在这里实现被替换的逻辑
|
||||
// ...
|
||||
// 需要返回方法对应的返回值,无需写 return,只需将参数放到最后一位
|
||||
// 假设这个方法的返回值是 Int,我们只需要保证最后一位是我们需要的返回值即可
|
||||
0
|
||||
}
|
||||
|
||||
/// 有些方法我们只需替换其返回值,则有如下实现
|
||||
/// 需要注意的是:直接替换返回值的方法传入的参数是固定不变的,若想实现动态替换返回值请使用上面的 replaceAny 方法体
|
||||
|
||||
// 替换为你需要的返回值
|
||||
replaceTo(...)
|
||||
// 替换为 Boolean 类型的返回值
|
||||
replaceToTrue()
|
||||
// 拦截返回值
|
||||
intercept()
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
/// 无返回值的方法 void
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Any? {
|
||||
// 直接在这里实现被替换的逻辑
|
||||
return null
|
||||
}
|
||||
|
||||
/// 有返回值的方法
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Int {
|
||||
// 在这里实现被替换的逻辑
|
||||
// ...
|
||||
// 假设这个方法的返回值是 Int
|
||||
return 0
|
||||
}
|
||||
|
||||
/// 有些方法我们只需替换其返回值,则有如下实现
|
||||
|
||||
// 替换为你需要的返回值
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = ...
|
||||
// 替换为 Boolean 类型的返回值
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = true
|
||||
// 拦截返回值
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = null
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## 迁移其它功能
|
||||
|
||||
`YukiHookAPI` 对 Xposed API 进行了完全重写,你可以参考 [API 文档](../api/home) 以及 [特色功能](../api/special-features/reflection) 来决定一些功能性的迁移和使用。
|
208
docs-source/src/zh-cn/guide/quick-start.md
Normal file
208
docs-source/src/zh-cn/guide/quick-start.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# 快速开始
|
||||
|
||||
> 集成 `YukiHookAPI` 到你的项目中。
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Windows 7 及以上/macOS 10.14 及以上/Linux 发行版(Arch/Debian)
|
||||
|
||||
- Android Studio 2021.1 及以上
|
||||
|
||||
- IntelliJ IDEA 2021.1 及以上
|
||||
|
||||
- Kotlin 1.7.0 及以上
|
||||
|
||||
- Android Gradle Plugin 7.0 及以上
|
||||
|
||||
- Gradle 7.0 及以上
|
||||
|
||||
- Jvm 11 及以上 (Since API `1.0.80`)
|
||||
|
||||
## 自动构建项目
|
||||
|
||||
`YukiHookAPI` 提供了一个自动化构建工具,它可以帮助你快速构建一个拥有 Xposed 模块依赖的 Android 标准项目模板,使用构建好的模板即可直接开始下一步工作。
|
||||
|
||||
你可以 [点击这里](../tools/yukihookapi-projectbuilder) 进行查看。
|
||||
|
||||
## 手动配置项目
|
||||
|
||||
若你不想使用自动化构建工具,你依然可以按照以下方式手动配置项目依赖。
|
||||
|
||||
### 创建项目
|
||||
|
||||
使用 `Android Studio` 或 `IntelliJ IDEA` 创建新的 Android 项目,并在 `Language` 一栏选择 `Kotlin` 以自动添加基础依赖。
|
||||
|
||||
### 集成依赖
|
||||
|
||||
在你的项目 `build.gradle` 中添加依赖。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// ❗若你的 Plugin 版本过低,作为 Xposed 模块使用务必添加,其它情况可选
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||
// ❗作为 Xposed 模块使用务必添加,其它情况可选
|
||||
maven { url "https://api.xposed.info/" }
|
||||
// MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||
}
|
||||
```
|
||||
|
||||
在你的 app `build.gradle` 中添加 `plugin`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```groovy
|
||||
plugins {
|
||||
// ❗作为 Xposed 模块使用务必添加,其它情况可选
|
||||
id 'com.google.devtools.ksp' version '<ksp-version>'
|
||||
}
|
||||
```
|
||||
|
||||
在你的 app `build.gradle` 中添加依赖。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
// 基础依赖
|
||||
implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
|
||||
// ❗作为 Xposed 模块使用务必添加,其它情况可选
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
// ❗作为 Xposed 模块使用务必添加,其它情况可选
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
|
||||
}
|
||||
```
|
||||
|
||||
请将 **<ksp-version>** 修改为 [这里](https://github.com/google/ksp/releases) 的最新版本 **(请注意选择你当前对应的 Kotlin 版本)**。
|
||||
|
||||
请将 **<yuki-version>** 修改为 [这里](../about/changelog) 的最新版本。
|
||||
|
||||
::: danger
|
||||
|
||||
**YukiHookAPI** 的 **api** 与 **ksp-xposed** 依赖的版本必须一一对应,否则将会造成版本不匹配错误。
|
||||
|
||||
:::
|
||||
|
||||
在你的 app `build.gradle` 中修改 `Kotlin` 的 Jvm 版本为 11 及以上。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```groovy
|
||||
android {
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
自 API **1.0.80** 版本后 Jvm 版本默认为 11,不再支持 1.8 及以下版本。
|
||||
|
||||
:::
|
||||
|
||||
### 作为 Xposed 模块使用
|
||||
|
||||
在你的 `AndroidManifest.xml` 中添加基础代码。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```xml
|
||||
<!-- 设置为 Xposed 模块 -->
|
||||
<meta-data
|
||||
android:name="xposedmodule"
|
||||
android:value="true" />
|
||||
|
||||
<!-- 设置你的模块描述 -->
|
||||
<meta-data
|
||||
android:name="xposeddescription"
|
||||
android:value="填写你的 Xposed 模块描述" />
|
||||
|
||||
<!-- 最低 Xposed 版本号,若你正在使用 EdXposed/LSPosed,建议最低为 93 -->
|
||||
<meta-data
|
||||
android:name="xposedminversion"
|
||||
android:value="93" />
|
||||
|
||||
<!-- 可选:配置支持 New XSharePrefs 可无需调整 xposedminversion 为 93 -->
|
||||
<meta-data
|
||||
android:name="xposedsharedprefs"
|
||||
android:value="true"/>
|
||||
```
|
||||
|
||||
在你的项目中创建一个 Hook 入口类,继承于 `IYukiHookXposedInit` 并加入注解 `@InjectYukiHookWithXposed`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = YukiHookAPI.encase {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip 建议
|
||||
|
||||
你可以将你的模块 APP 的 **Application** 继承于 **ModuleApplication** 以实现完整使用体验。
|
||||
|
||||
更多功能请参考 [ModuleApplication](../api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication)。
|
||||
|
||||
:::
|
||||
|
||||
然后,你就可以开始编写 Hook 代码了。
|
||||
|
||||
有关作为 Xposed 模块使用的相关配置详细内容,你可以 [点击这里](../config/xposed-using) 继续阅读。
|
||||
|
||||
若你目前正在使用 Xposed API,你可以参考 [从 Xposed API 迁移](../guide/move-to-new-api)。
|
||||
|
||||
### 作为 Hook API 使用
|
||||
|
||||
#### 集成方式
|
||||
|
||||
创建你的自定义 `Application`。
|
||||
|
||||
::: danger
|
||||
|
||||
无论使用任何 **Hook Framework**,你都需要加入其对接的 Xposed 依赖支持。
|
||||
|
||||
若目标 **Hook Framework** 没有集成 Xposed API 你需要自行实现并对接 **XposedBridge**。
|
||||
|
||||
:::
|
||||
|
||||
在 `attachBaseContext` 中添加 `YukiHookAPI.encase` 方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// 装载 Hook Framework
|
||||
//
|
||||
// Your code here.
|
||||
//
|
||||
// 装载 YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
||||
|
||||
然后,你就可以开始编写 Hook 代码了,方式与作为 Xposed 模块使用基本一致。
|
||||
|
||||
有关作为 Hook API 使用的相关配置详细内容,你可以 [点击这里](../config/api-using) 继续阅读。
|
||||
|
||||
::: warning
|
||||
|
||||
使用自定义的 Hook 框架而并非完整的 Xposed 模块时,**YukiHookModuleStatus**、**YukiHookModulePrefs**、**YukiHookDataChannel** 以及 Resources Hook 功能将失效。
|
||||
|
||||
:::
|
56
docs-source/src/zh-cn/index.md
Normal file
56
docs-source/src/zh-cn/index.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
home: true
|
||||
title: 首页
|
||||
heroImage: /images/logo.png
|
||||
actions:
|
||||
- text: 快速上手
|
||||
link: /zh-cn/guide/home
|
||||
type: primary
|
||||
- text: 更新日志
|
||||
link: /zh-cn/about/changelog
|
||||
type: secondary
|
||||
features:
|
||||
- title: Xposed 模块开发
|
||||
details: 自动构建程序可以帮你快速创建一个 Xposed 模块,完全省去配置入口类和 xposed_init 文件。
|
||||
- title: 轻量优雅
|
||||
details: 拥有一套强大、优雅、人性化、完全使用 Kotlin lambda 打造的 API,可以帮你快速实现字节码的查找以及方法 Hook。
|
||||
- title: 高效调试
|
||||
details: 拥有丰富的调试日志功能,细到每个 Hook 方法的名称、所在类以及查找耗时,可进行快速调试和排错。
|
||||
- title: 方便移植
|
||||
details: 原生支持 Xposed API 用法,并原生对接 Xposed API,拥有 Xposed API 的 Hook 框架都能进行快速对接。
|
||||
- title: 支持混淆
|
||||
details: 构建的 Xposed 模块原生支持 R8 压缩优化混淆,混淆不会破坏 Hook 入口点,R8 下无需任何其它配置。
|
||||
- title: 快速上手
|
||||
details: 简单易用,不需要繁琐的配置,不需要十足的开发经验,搭建环境集成依赖即可立即开始使用。
|
||||
footer: MIT License | Copyright (C) 2019-2022 HighCapable
|
||||
---
|
||||
|
||||
### 所有 Hook 流程一步到位,拒绝繁琐
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
37
docs-source/src/zh-cn/tools/yukihookapi-projectbuilder.md
Normal file
37
docs-source/src/zh-cn/tools/yukihookapi-projectbuilder.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# YukiHookAPI 构建工具
|
||||
|
||||
> 这是一个使用 `YukiHookAPI` 作为核心的 Xposed 模块自动构建工具。
|
||||
>
|
||||
> 实现自动化搜索依赖快速搭建一个包含 Xposed 模块环境的 Android 项目模板。
|
||||
|
||||
<img src="/images/yukihookapi-projectbuilder-zh-cn.png" width = "720"/>
|
||||
|
||||
## 获取项目
|
||||
|
||||
本项目完全开源免费,且会根据大家的使用情况持续维护,初代版本可能存在不完善或 BUG,欢迎反馈。
|
||||
|
||||
项目地址 [YukiHookAPI-ProjectBuilder](https://github.com/fankes/YukiHookAPI-ProjectBuilder)。
|
||||
|
||||
若你想直接下载可以 [点击这里](https://github.com/fankes/YukiHookAPI-ProjectBuilder/releases) 前往 Release 发布地址。
|
||||
|
||||
## 使用方法
|
||||
|
||||
> 这里包含了基本的使用方法和功能讲解。
|
||||
|
||||
### 基本用法
|
||||
|
||||
- 软件使用过程需要当前设备已连接互联网,若项目依赖无法搜索请尝试 **科学上网** 。
|
||||
|
||||
- 启动软件后,对你期望创建的项目进行简单配置,点击右下角的 **按钮** 或菜单栏选择 **项目 > 开始创建** 即可开始任务。
|
||||
|
||||
- 等待依赖自动搜索完成后,你可以对项目依赖进行配置,建议使用最新依赖保证项目的稳定性,构建工具也仅对最新依赖进行支持。
|
||||
|
||||
- 选择你需要创建项目的目录,开始后项目会在你选择的位置中创建,并等待整个过程完成,项目就创建好了。
|
||||
|
||||
### 配置模板
|
||||
|
||||
配置模板是一个扩展功能,你可以选择菜单栏 **项目 > 配置模板 > 新建模板**,即可使用当前填写的配置创建一份模板,下次可以从 **已保存的模板** 中重新载入模板,即可还原当前配置。
|
||||
|
||||
### 多语言支持
|
||||
|
||||
软件语言跟随当前系统,你可以在菜单栏 **语言 (Language)** 一栏手动选择软件的界面语言。
|
2115
docs-source/yarn.lock
Normal file
2115
docs-source/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user