From 5f0d3158e181930d56926ff9a71bbb2debd124e2 Mon Sep 17 00:00:00 2001
From: LiuYi <1354548951@qq.com>
Date: Sat, 13 May 2023 09:48:41 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=BB=91=E5=90=8D=E5=8D=95?=
=?UTF-8?q?=E6=94=AF=E6=8C=81,=20=E5=85=B6=E4=B8=AD=E5=8C=85=E6=8B=AC?=
=?UTF-8?q?=E7=A3=81=E8=B4=B4=E3=80=81=E8=B7=B3=E8=BD=AC=E3=80=81=E5=88=86?=
=?UTF-8?q?=E4=BA=AB=E3=80=81=E5=B9=B3=E8=A1=8C=E5=B0=8F=E7=AA=97=20?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B9=B3=E8=A1=8C=E5=B0=8F=E7=AA=97=E7=9A=84?=
=?UTF-8?q?=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91=EF=BC=8C=E5=87=8F=E5=B0=91?=
=?UTF-8?q?=E6=97=A0=E9=99=90=E6=B7=BB=E5=8A=A0=E5=BA=94=E7=94=A8=E5=AF=BC?=
=?UTF-8?q?=E8=87=B4=E5=86=85=E5=AD=98=E8=BF=87=E5=A4=9A=E7=9A=84=E5=8F=AF?=
=?UTF-8?q?=E8=83=BD=EF=BC=8C=E5=87=8F=E5=B0=91=E5=BA=94=E7=94=A8=E5=8A=A0?=
=?UTF-8?q?=E8=BD=BD=20=E5=8E=BB=E9=99=A4=E6=82=AC=E6=B5=AE=E7=90=83?=
=?UTF-8?q?=E7=9A=84=E5=B9=B3=E8=A1=8C=E5=B0=8F=E7=AA=97=E9=80=82=E9=85=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/deploymentTargetDropDown.xml | 17 --
app/build.gradle | 1 +
.../java/org/liuyi/mifreeformx/BlackList.kt | 48 ++++
.../mifreeformx/activity/MainActivity.kt | 7 +
.../activity/page/AppSelectPage.kt | 87 +++++++
.../JumpAndShareBetweenApplicationsPage.kt | 17 ++
.../page/NotificationAndControlCenterPage.kt | 5 +
.../activity/page/ParallelSmallWindowPage.kt | 5 +
.../mifreeformx/adapter/AppSelectAdapter.kt | 61 +++++
.../org/liuyi/mifreeformx/bean/BlackList.kt | 27 ++
.../liuyi/mifreeformx/bean/BlackListBean.kt | 75 ++++++
.../proxy/systemui/DependencyProxy.kt | 24 --
.../xposed/hooker/FrameworkBaseHooker.kt | 234 ++++++------------
.../xposed/hooker/SystemUiHooker.kt | 33 +--
.../xposed/operation/AppJumpOpt.kt | 37 +++
.../xposed/operation/AppShareOpt.kt | 44 ++++
.../operation/ParallelSmallWindowOpt.kt | 52 ++++
app/src/main/res/values/strings.xml | 1 +
build.gradle | 2 +-
19 files changed, 560 insertions(+), 217 deletions(-)
delete mode 100644 .idea/deploymentTargetDropDown.xml
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/BlackList.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/activity/page/AppSelectPage.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/adapter/AppSelectAdapter.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/bean/BlackList.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/bean/BlackListBean.kt
delete mode 100644 app/src/main/java/org/liuyi/mifreeformx/proxy/systemui/DependencyProxy.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppJumpOpt.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppShareOpt.kt
create mode 100644 app/src/main/java/org/liuyi/mifreeformx/xposed/operation/ParallelSmallWindowOpt.kt
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 1501d99..0000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 55794ad..2954412 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -53,6 +53,7 @@ dependencies {
implementation project(path: ':blockmiui')
implementation 'androidx.annotation:annotation-jvm:1.6.0'
+ implementation 'androidx.collection:collection:1.2.0'
// 基础依赖
implementation 'com.highcapable.yukihookapi:api:1.1.11'
diff --git a/app/src/main/java/org/liuyi/mifreeformx/BlackList.kt b/app/src/main/java/org/liuyi/mifreeformx/BlackList.kt
new file mode 100644
index 0000000..2eba336
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/BlackList.kt
@@ -0,0 +1,48 @@
+package org.liuyi.mifreeformx
+
+import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
+import org.liuyi.mifreeformx.bean.BlackListBean
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/09/9:47:41
+ * @Description:
+ */
+
+
+object BlackList {
+
+ object AppJumpSourceBlacklist :
+ BlackListBean(PrefsData("app_jump_source_blacklist", setOf("com.android.providers.media.module")))
+
+ object AppJumpTargetBlacklist : BlackListBean(
+ PrefsData(
+ "app_jump_target_blacklist",
+ setOf("com.android.camera", "com.miui.tsmclient", "com.lbe.security.miui")
+ )
+ )
+
+ object AppShareSourceBlacklist :
+ BlackListBean(PrefsData("app_share_source_blacklist", setOf("com.android.providers.media.module")))
+
+ object AppShareTargetBlacklist : BlackListBean(
+ PrefsData(
+ "app_share_target_blacklist",
+ setOf("com.android.camera", "com.miui.tsmclient", "com.lbe.security.miui")
+ )
+ )
+
+ object ParallelFreeformBlacklist : BlackListBean(
+ PrefsData(
+ "parallel_small_window_blacklist",
+ setOf("com.android.camera", "com.miui.tsmclient", "com.lbe.security.miui")
+ )
+ )
+
+ object TileBlacklist : BlackListBean(
+ PrefsData(
+ "tile_blacklist",
+ setOf("com.android.camera", "com.miui.tsmclient", "com.lbe.security.miui")
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/activity/MainActivity.kt b/app/src/main/java/org/liuyi/mifreeformx/activity/MainActivity.kt
index de58e61..e7cc4cc 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/activity/MainActivity.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/activity/MainActivity.kt
@@ -3,7 +3,9 @@ package org.liuyi.mifreeformx.activity
import android.os.Bundle
import cn.fkj233.ui.activity.MIUIActivity
import cn.fkj233.ui.dialog.MIUIDialog
+import com.blankj.utilcode.util.AppUtils
import com.highcapable.yukihookapi.YukiHookAPI
+import com.highcapable.yukihookapi.hook.factory.prefs
import org.liuyi.mifreeformx.R
import org.liuyi.mifreeformx.activity.page.*
@@ -14,6 +16,10 @@ import org.liuyi.mifreeformx.activity.page.*
*/
class MainActivity : MIUIActivity() {
+ companion object {
+ lateinit var appsInfo: Any
+ }
+
init {
registerPage(MainPage::class.java)
registerPage(NotificationAndControlCenterPage::class.java)
@@ -22,6 +28,7 @@ class MainActivity : MIUIActivity() {
registerPage(MiscellaneousPage::class.java)
registerPage(MenuPage::class.java)
registerPage(AboutPage::class.java)
+ registerPage(AppSelectPage::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
diff --git a/app/src/main/java/org/liuyi/mifreeformx/activity/page/AppSelectPage.kt b/app/src/main/java/org/liuyi/mifreeformx/activity/page/AppSelectPage.kt
new file mode 100644
index 0000000..727f68b
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/activity/page/AppSelectPage.kt
@@ -0,0 +1,87 @@
+package org.liuyi.mifreeformx.activity.page
+
+import android.annotation.SuppressLint
+import cn.fkj233.ui.activity.annotation.BMPage
+import cn.fkj233.ui.activity.fragment.MIUIFragment
+import com.blankj.utilcode.util.AppUtils
+import com.highcapable.yukihookapi.hook.factory.prefs
+import com.highcapable.yukihookapi.hook.log.loggerD
+import org.liuyi.mifreeformx.R
+import org.liuyi.mifreeformx.adapter.AppSelectAdapter
+import org.liuyi.mifreeformx.bean.BlackListBean
+import org.liuyi.mifreeformx.utils.PinyinUtils
+import kotlin.concurrent.thread
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/07/13:26:35
+ * @Description:
+ */
+@SuppressLint("NonConstantResourceId")
+@BMPage(key = "AppSelectPage", titleId = R.string.select_app)
+class AppSelectPage : MyBasePage() {
+
+ init {
+ skipLoadItem = true
+ }
+
+ companion object {
+ init {
+ thread { allAppInfo }
+ }
+
+ val allAppInfo: MutableList by lazy { AppUtils.getAppsInfo() }
+ var currentBlackList: BlackListBean? = null
+ }
+
+ private var lastBlackList: BlackListBean? = null
+
+
+ private val mAppSelectAdapter by lazy {
+ AppSelectAdapter(activity, allAppInfo.toMutableList(), mutableSetOf(), setOf()) { _, _ ->
+ lastBlackList?.addAll(activity.prefs(), selectedSet)
+ }
+ }
+
+
+ override fun onCreate() {
+ List {
+ adapter = mAppSelectAdapter
+ }
+ }
+
+ override fun asyncInit(fragment: MIUIFragment) {
+ fragment.showLoading()
+ // 初始化
+ mAppSelectAdapter.apply {
+ val current = currentBlackList?.getAll(activity.prefs())
+
+ mAppInfoList = current?.let {
+ allAppInfo.toMutableList().apply {
+ sortWith { a1, a2 ->
+ if (current.contains(a1.packageName) && current.contains(a2.packageName)) {
+ PinyinUtils.ccs2Pinyin(a1.name).compareTo(PinyinUtils.ccs2Pinyin(a2.name))
+ } else if (current.contains(a1.packageName)) {
+ -1
+ } else if (current.contains(a2.packageName)) {
+ 1
+ } else PinyinUtils.ccs2Pinyin(a1.name).compareTo(PinyinUtils.ccs2Pinyin(a2.name))
+ }
+ }
+ } ?: mutableListOf()
+
+ disEnabledSet = currentBlackList?.forceList ?: setOf()
+ selectedSet = current?.toMutableSet() ?: mutableSetOf()
+
+ loggerD(msg = "当前黑名单: $currentBlackList")
+ loggerD(msg = "上次黑名单: $lastBlackList")
+ loggerD(msg = "不可选项: $disEnabledSet")
+ loggerD(msg = "当前选择项: $selectedSet")
+ notifyDataSetChanged()
+ }
+ lastBlackList = currentBlackList
+ currentBlackList = null
+ fragment.initData()
+ fragment.closeLoading()
+ }
+}
diff --git a/app/src/main/java/org/liuyi/mifreeformx/activity/page/JumpAndShareBetweenApplicationsPage.kt b/app/src/main/java/org/liuyi/mifreeformx/activity/page/JumpAndShareBetweenApplicationsPage.kt
index c852be7..a02acb0 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/activity/page/JumpAndShareBetweenApplicationsPage.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/activity/page/JumpAndShareBetweenApplicationsPage.kt
@@ -3,6 +3,7 @@ package org.liuyi.mifreeformx.activity.page
import android.annotation.SuppressLint
import cn.fkj233.ui.activity.annotation.BMPage
import cn.fkj233.ui.activity.view.TextSummaryV
+import org.liuyi.mifreeformx.BlackList
import org.liuyi.mifreeformx.DataConst
import org.liuyi.mifreeformx.R
@@ -27,6 +28,14 @@ class JumpAndShareBetweenApplicationsPage : MyBasePage() {
),
createSwitchV(DataConst.APP_JUMP)
)
+ TextSummaryWithArrow(TextSummaryV(text = "源黑名单", tips = "不使用小窗处理打开其他应用") {
+ AppSelectPage.currentBlackList = BlackList.AppJumpSourceBlacklist
+ showFragment("AppSelectPage")
+ })
+ TextSummaryWithArrow(TextSummaryV(text = "目标黑名单", tips = "对将打开的应用不处理") {
+ AppSelectPage.currentBlackList = BlackList.AppJumpTargetBlacklist
+ showFragment("AppSelectPage")
+ })
Line()
TitleText(textId = R.string.share_between_applications)
@@ -44,5 +53,13 @@ class JumpAndShareBetweenApplicationsPage : MyBasePage() {
),
createSwitchV(DataConst.SHARE_TO_APP_FORCE_NEW_TASK)
)
+ TextSummaryWithArrow(TextSummaryV(text = "源黑名单", tips = "不处理当前应用的分享") {
+ AppSelectPage.currentBlackList = BlackList.AppShareSourceBlacklist
+ showFragment("AppSelectPage")
+ })
+ TextSummaryWithArrow(TextSummaryV(text = "目标黑名单", tips = "不处理分享的目标应用") {
+ AppSelectPage.currentBlackList = BlackList.AppShareTargetBlacklist
+ showFragment("AppSelectPage")
+ })
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/activity/page/NotificationAndControlCenterPage.kt b/app/src/main/java/org/liuyi/mifreeformx/activity/page/NotificationAndControlCenterPage.kt
index f9f7011..8fb9b3e 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/activity/page/NotificationAndControlCenterPage.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/activity/page/NotificationAndControlCenterPage.kt
@@ -3,6 +3,7 @@ package org.liuyi.mifreeformx.activity.page
import android.annotation.SuppressLint
import cn.fkj233.ui.activity.annotation.BMPage
import cn.fkj233.ui.activity.view.TextSummaryV
+import org.liuyi.mifreeformx.BlackList
import org.liuyi.mifreeformx.DataConst
import org.liuyi.mifreeformx.R
@@ -47,6 +48,10 @@ class NotificationAndControlCenterPage : MyBasePage() {
),
createSwitchV(DataConst.FORCE_CONTROL_ALL_OPEN)
)
+ TextSummaryWithArrow(TextSummaryV(text = "黑名单") {
+ AppSelectPage.currentBlackList = BlackList.TileBlacklist
+ showFragment("AppSelectPage")
+ })
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/activity/page/ParallelSmallWindowPage.kt b/app/src/main/java/org/liuyi/mifreeformx/activity/page/ParallelSmallWindowPage.kt
index 2c44e28..189a4f0 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/activity/page/ParallelSmallWindowPage.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/activity/page/ParallelSmallWindowPage.kt
@@ -3,6 +3,7 @@ package org.liuyi.mifreeformx.activity.page
import android.annotation.SuppressLint
import cn.fkj233.ui.activity.annotation.BMPage
import cn.fkj233.ui.activity.view.TextSummaryV
+import org.liuyi.mifreeformx.BlackList
import org.liuyi.mifreeformx.DataConst
import org.liuyi.mifreeformx.R
@@ -23,5 +24,9 @@ class ParallelSmallWindowPage : MyBasePage() {
),
createSwitchV(DataConst.PARALLEL_MULTI_WINDOW_PLUS)
)
+ TextSummaryWithArrow(TextSummaryV(text = "黑名单") {
+ AppSelectPage.currentBlackList = BlackList.ParallelFreeformBlacklist
+ showFragment("AppSelectPage")
+ })
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/adapter/AppSelectAdapter.kt b/app/src/main/java/org/liuyi/mifreeformx/adapter/AppSelectAdapter.kt
new file mode 100644
index 0000000..ff7435d
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/adapter/AppSelectAdapter.kt
@@ -0,0 +1,61 @@
+package org.liuyi.mifreeformx.adapter
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.CompoundButton
+import android.widget.LinearLayout
+import cn.fkj233.ui.activity.fragment.MIUIFragment
+import cn.fkj233.ui.activity.view.ImageTextSummaryWithSwitchV
+import cn.fkj233.ui.activity.view.ImageV
+import cn.fkj233.ui.activity.view.SwitchV
+import cn.fkj233.ui.activity.view.TextSummaryV
+import com.blankj.utilcode.util.AppUtils.AppInfo
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/08/22:21:49
+ * @Description:
+ */
+class AppSelectAdapter(
+ var mContext: Context,
+ var mAppInfoList: MutableList,
+ var selectedSet: MutableSet,
+ var disEnabledSet: Set,
+ private val block: AppSelectAdapter.(Boolean, AppInfo) -> Unit
+) : BaseAdapter() {
+
+
+ override fun getCount() = mAppInfoList.size
+
+ override fun getItem(position: Int) = mAppInfoList[position]
+
+ override fun getItemId(position: Int) = position.toLong()
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ return LinearLayout(mContext).also { layout ->
+ mAppInfoList[position].run {
+ SwitchV("").let { switchV ->
+ ImageTextSummaryWithSwitchV(
+ ImageV(icon),
+ TextSummaryV(text = name, tips = packageName),
+ switchV
+ ).let {
+ it.onDraw(MIUIFragment(""), layout, it.create(mContext) {})
+ switchV.switch.apply {
+ isChecked = selectedSet.contains(packageName)
+ isEnabled = !disEnabledSet.contains(packageName)
+ setOnCheckedChangeListener { _, isChecked ->
+ if (isChecked) selectedSet += this@run.packageName
+ else selectedSet -= this@run.packageName
+ block(this@AppSelectAdapter, isChecked, this@run)
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/bean/BlackList.kt b/app/src/main/java/org/liuyi/mifreeformx/bean/BlackList.kt
new file mode 100644
index 0000000..7017e94
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/bean/BlackList.kt
@@ -0,0 +1,27 @@
+package org.liuyi.mifreeformx.bean
+
+import android.app.Activity
+import com.highcapable.yukihookapi.hook.param.PackageParam
+import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/12/20:32:26
+ * @Description:
+ */
+interface BlackList {
+
+ fun add(prefs: YukiHookPrefsBridge? = null, item: String)
+
+ fun addAll(prefs: YukiHookPrefsBridge? = null, items: Set)
+
+ fun remove(prefs: YukiHookPrefsBridge? = null, item: String)
+
+ fun contains(prefs: YukiHookPrefsBridge? = null, item: String): Boolean
+
+ fun size(prefs: YukiHookPrefsBridge? = null, item: String): Int
+
+ fun clear(prefs: YukiHookPrefsBridge? = null, item: String)
+
+ fun getAll(prefs: YukiHookPrefsBridge? = null): Set
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/bean/BlackListBean.kt b/app/src/main/java/org/liuyi/mifreeformx/bean/BlackListBean.kt
new file mode 100644
index 0000000..ad19722
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/bean/BlackListBean.kt
@@ -0,0 +1,75 @@
+package org.liuyi.mifreeformx.bean
+
+import android.content.Context
+import android.content.Intent
+import com.highcapable.yukihookapi.hook.log.loggerD
+import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge
+import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/12/20:31:43
+ * @Description:
+ */
+open class BlackListBean(private val prefsData: PrefsData>? = null) : BlackList {
+
+ var forceList: Set = prefsData?.value?: setOf()
+
+ override fun add(prefs: YukiHookPrefsBridge?, item: String) {
+ if (item in forceList) {
+ loggerD(msg = "$item is forced to open")
+ return
+ }
+ if (prefs != null && prefsData != null) {
+ val mutableSet = prefs.get(prefsData).toMutableSet()
+ mutableSet.add(item)
+ prefs.edit { put(prefsData, mutableSet) }
+ }
+ }
+
+ override fun addAll(prefs: YukiHookPrefsBridge?, items: Set) {
+ loggerD(msg = "$prefs $items $prefsData")
+ if (prefs != null && prefsData != null) {
+ prefs.edit { put(prefsData, items) }
+ }
+ }
+
+ override fun remove(prefs: YukiHookPrefsBridge?, item: String) {
+ if (item in forceList) {
+ loggerD(msg = "$item is forced to open")
+ return
+ }
+ if (prefs != null && prefsData != null) {
+ val mutableSet = prefs.get(prefsData).toMutableSet()
+ mutableSet.remove(item)
+ prefs.edit { put(prefsData, mutableSet) }
+ }
+ }
+
+ override fun contains(prefs: YukiHookPrefsBridge?, item: String): Boolean {
+ return item in forceList || prefsData?.let { prefs?.get(it)?.contains(item) } ?: false
+ }
+
+ override fun size(prefs: YukiHookPrefsBridge?, item: String): Int {
+ return if (prefs != null && prefsData != null) {
+ forceList.toMutableSet().apply { addAll(prefs.get(prefsData)) }.size
+ } else forceList.size
+ }
+
+ override fun clear(prefs: YukiHookPrefsBridge?, item: String) {
+ if (prefs != null && prefsData != null) {
+ prefs.edit { put(prefsData, setOf()) }
+ }
+ }
+
+ override fun getAll(prefs: YukiHookPrefsBridge?): Set {
+ return if (prefs != null && prefsData != null) {
+ forceList.toMutableSet().apply { addAll(prefs.get(prefsData)) }
+ } else forceList
+ }
+
+ fun contains(prefs: YukiHookPrefsBridge? = null, intent: Intent, context: Context? = null): Boolean {
+ val comparable = intent.component ?: context?.packageManager?.let { intent.resolveActivity(it) }
+ return comparable?.let { contains(prefs, it.packageName) } ?: false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/proxy/systemui/DependencyProxy.kt b/app/src/main/java/org/liuyi/mifreeformx/proxy/systemui/DependencyProxy.kt
deleted file mode 100644
index b551d90..0000000
--- a/app/src/main/java/org/liuyi/mifreeformx/proxy/systemui/DependencyProxy.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.liuyi.mifreeformx.proxy.systemui
-
-import android.content.ComponentName
-import com.highcapable.yukihookapi.hook.factory.method
-import org.liuyi.mifreeformx.xposed.base.ReflectStaticMethod
-import org.liuyi.mifreeformx.xposed.hooker.SystemUiHooker.toClass
-
-/**
- * @Author: Liuyi
- * @Date: 2023/05/06/23:42:13
- * @Description:
- */
-object DependencyProxy {
- internal val clazz by lazy { "com.android.systemui.Dependency".toClass() }
-
-
- internal val getTopActivity by lazy {
- ReflectStaticMethod {
- clazz.method { name("getTopActivity") }.give()!!
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/FrameworkBaseHooker.kt b/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/FrameworkBaseHooker.kt
index 781f7eb..c3c52f7 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/FrameworkBaseHooker.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/FrameworkBaseHooker.kt
@@ -1,18 +1,23 @@
package org.liuyi.mifreeformx.xposed.hooker
import android.annotation.SuppressLint
-import android.app.ActivityOptions
-import android.content.Context
import android.content.Intent
import android.os.Bundle
-import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.log.loggerD
+import org.liuyi.mifreeformx.BlackList
import org.liuyi.mifreeformx.DataConst
import org.liuyi.mifreeformx.intent_extra.FreeFormIntent
import org.liuyi.mifreeformx.intent_extra.forceFreeFromMode
import org.liuyi.mifreeformx.intent_extra.getFreeFormMode
import org.liuyi.mifreeformx.intent_extra.setFreeFromBundle
+import org.liuyi.mifreeformx.proxy.framework.ActivityTaskManagerService
+import org.liuyi.mifreeformx.proxy.framework.RootWindowContainer
+import org.liuyi.mifreeformx.proxy.framework.SafeActivityOptions
import org.liuyi.mifreeformx.utils.*
+import org.liuyi.mifreeformx.xposed.base.LyBaseHooker
+import org.liuyi.mifreeformx.xposed.operation.AppJumpOpt
+import org.liuyi.mifreeformx.xposed.operation.AppShareOpt
+import org.liuyi.mifreeformx.xposed.operation.ParallelSmallWindowOpt
/**
* @Author: Liuyi
@@ -21,80 +26,13 @@ import org.liuyi.mifreeformx.utils.*
*/
@SuppressLint("QueryPermissionsNeeded")
-object FrameworkBaseHooker : YukiBaseHooker() {
-
- private val targetBlacklist =
- listOf("com.android.camera", "com.miui.tsmclient", "com.lbe.security.miui")
-
- // 禁止小窗黑名单
- private fun isInBlacklist(context: Context? = null, intent: Intent?): Boolean {
- intent ?: return false
- intent.component?.let {
- if (targetBlacklist.contains(it.packageName)) return true
- }
- intent.`package`?.let {
- if (targetBlacklist.contains(it)) return true
- }
- context ?: return false
- context.packageManager?.let {
- val componentName = intent.resolveActivity(it)
- componentName?.run {
- if (targetBlacklist.contains(packageName)) return true
- }
- }
- return false
- }
-
- // 应用间跳转
- private fun isAppJump(
- callingThread: Any?, callingPackage: String?, intent: Intent, context: Context
- ): Boolean {
- // 排除系统调用
- callingThread ?: return false
- // 排除如,系统后台进入,获取桌面进入
- if (intent.flags and Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED != 0) return false
- if (callingPackage == "com.miui.securityadd") return false
- if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0) {
- // 包含 new 标签
- val componentName = intent.component ?: intent.resolveActivity(context.packageManager)
- loggerD(msg = "$componentName")
- // 修复微信分享回调导致源activity使用小窗
- if (componentName.className.endsWith(".wxapi.WXEntryActivity")) return false
- componentName?.packageName?.let { name ->
- loggerD(msg = name)
- if (callingPackage != name) {
- // 判断为应用间跳转
- return true
- }
- }
- }
- return false
- }
-
- // 应用间分享
- private fun isShareToApp(callingPackage: String?, intent: Intent?): Boolean {
- if (intent?.`package` == callingPackage) return false
- intent?.action.let {
- if (it == Intent.ACTION_SEND) return true
- // 使用全屏打开 miui 系统选择分享界面
- if (it == "miui.intent.action.MIUI_CHOOSER") return false
- }
- intent?.component?.let {
- // 微信分享sdk
- if (it.className == "com.tencent.mm.plugin.base.stub.WXEntryActivity") return true
- if (it.packageName == callingPackage) return false
- }
- if (intent?.clipData != null) return true
- intent?.data?.let {
- // QQ分享sdk
- if (it.scheme == "mqqapi" && it.host == "share") return true
- }
- return false
- }
+object FrameworkBaseHooker : LyBaseHooker() {
override fun onHook() {
+ var rootWindowContainer: RootWindowContainer? = null
+ val activityTaskManagerService: ActivityTaskManagerService? = null
"com.android.server.wm.ActivityTaskManagerService".hook {
/**
* 用户应用调用会来到这里
@@ -109,37 +47,39 @@ object FrameworkBaseHooker : YukiBaseHooker() {
// 全局管控,只要在intent设置了 FreeFormIntent 都会优先判断是否开启小窗
val caller = args[1] as String?
val intent = Intent(args[3] as? Intent?)
+ val atmService = activityTaskManagerService ?: instance.getProxyAs()
+ rootWindowContainer = rootWindowContainer ?: atmService.mRootWindowContainer
args[3] = intent
- val context = instance.getFieldValueOrNull("mContext") as Context?
- if (isInBlacklist(context, intent)) return@beforeHook
+ val context = atmService.mContext ?: return@beforeHook
+ val callee = intent.resolveActivity(context.packageManager)?.packageName ?: return@beforeHook
- if (context != null) {
- if (prefs.get(DataConst.PARALLEL_MULTI_WINDOW_PLUS)) {
- if (caller == "com.miui.touchassistant" || caller == "com.miui.securitycenter") {
- if (!intent.isSameApp(caller) && intent.action == Intent.ACTION_MAIN) {
- intent.forceFreeFromMode()
- intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
- }
- }
- }
- if (prefs.get(DataConst.APP_JUMP)
- && isAppJump(args[0], caller, intent, context)
- ) {
- intent.forceFreeFromMode()
- }
- if (prefs.get(DataConst.SHARE_TO_APP)
- && isShareToApp(args[1] as? String?, intent)
- ) {
- intent.forceFreeFromMode()
- intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
- if (prefs.get(DataConst.SHARE_TO_APP_FORCE_NEW_TASK)) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
- }
- if (intent.getFreeFormMode() == FreeFormIntent.FREE_FORM_EXTRA_FORCE) {
- args[10] = args[10] ?: getBasicBundle()
- intent.setFreeFromBundle(args[10] as Bundle, context)
- }
+ if (prefs.get(DataConst.PARALLEL_MULTI_WINDOW_PLUS)
+ && ParallelSmallWindowOpt.isFromSidebar(caller, intent)
+ && !BlackList.ParallelFreeformBlacklist.contains(prefs, callee)
+ ) {
+ ParallelSmallWindowOpt.handle(intent, atmService, rootWindowContainer)
+ }
+
+ if (prefs.get(DataConst.APP_JUMP)
+ && AppJumpOpt.isAppJump(args[0], caller, intent, context)
+ && caller != null
+ && !BlackList.AppJumpSourceBlacklist.contains(prefs, caller)
+ && !BlackList.AppJumpTargetBlacklist.contains(prefs, callee)
+ ) {
+ intent.forceFreeFromMode()
+ }
+
+ if (prefs.get(DataConst.SHARE_TO_APP)
+ && AppShareOpt.isShareToApp(args[1] as? String?, intent)
+ && caller != null
+ && !BlackList.AppShareSourceBlacklist.contains(prefs, caller)
+ && !BlackList.AppShareTargetBlacklist.contains(prefs, callee)
+ ) {
+ AppShareOpt.handle(intent)
+ }
+ if (intent.getFreeFormMode() == FreeFormIntent.FREE_FORM_EXTRA_FORCE) {
+ args[10] = args[10] ?: getBasicBundle()
+ intent.setFreeFromBundle(args[10] as Bundle, context)
}
}
}
@@ -149,43 +89,21 @@ object FrameworkBaseHooker : YukiBaseHooker() {
injectMember {
method { name("startActivityAsCaller") }
beforeHook {
- if (prefs.get(DataConst.SHARE_TO_APP)) {
- val context = instance.getFieldValueOrNull("mContext") as? Context?
- val intent = Intent(args[2] as? Intent?)
- args[2] = intent
- if (!isInBlacklist(context, intent) && context != null) {
- if (isShareToApp(args[1] as? String?, intent)) {
- // 开启分享应用
- intent.forceFreeFromMode()
- // 强制添加 new task 标签
- if (prefs.get(DataConst.SHARE_TO_APP_FORCE_NEW_TASK)) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
- }
- if (intent.getFreeFormMode() == FreeFormIntent.FREE_FORM_EXTRA_FORCE) {
- args[9] = args[9] ?: getBasicBundle()
- intent.setFreeFromBundle(args[9] as Bundle, context)
- }
- }
+ val atmService = activityTaskManagerService ?: instance.getProxyAs()
+ val context = atmService.mContext ?: return@beforeHook
+ val intent = Intent(args[2] as? Intent?)
+ val caller = args[1] as? String?
+ args[2] = intent
+
+ if (prefs.get(DataConst.SHARE_TO_APP)
+ && AppShareOpt.isShareToApp(caller, intent)
+ && !BlackList.AppShareTargetBlacklist.contains(prefs, intent, context)
+ ) {
+ AppShareOpt.handle(intent)
}
- if (prefs.get(DataConst.SHARE_TO_APP)) {
- val context = instance.getFieldValueOrNull("mContext") as? Context?
- val intent = Intent(args[2] as? Intent?)
- args[2] = intent
- if (!isInBlacklist(context, intent) && context != null) {
- if (isShareToApp(args[1] as? String?, intent)) {
- // 开启分享应用
- intent.forceFreeFromMode()
- // 强制添加 new task 标签
- if (prefs.get(DataConst.SHARE_TO_APP_FORCE_NEW_TASK)) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
- }
- if (intent.getFreeFormMode() == FreeFormIntent.FREE_FORM_EXTRA_FORCE) {
- args[9] = args[9] ?: getBasicBundle()
- intent.setFreeFromBundle(args[9] as Bundle, context)
- }
- }
+ if (intent.getFreeFormMode() == FreeFormIntent.FREE_FORM_EXTRA_FORCE) {
+ args[9] = args[9] ?: getBasicBundle()
+ intent.setFreeFromBundle(args[9] as Bundle, context)
}
}
}
@@ -205,30 +123,28 @@ object FrameworkBaseHooker : YukiBaseHooker() {
loggerD(msg = "${args.asList()}")
val intent = Intent(args[5] as? Intent?)
args[5] = intent
- val context = instanceOrNull?.getFieldValueOrNull("mService")
- ?.getFieldValueOrNull("mContext") as? Context?
-
- val callingPackage = args[3] as? String?
-
- if (
- context != null
- && callingPackage != "com.android.providers.media.module" // 排除【媒体存储设备】
+ val realCallingPid = args[1] as Int
+ val atmService = activityTaskManagerService ?: instance.getFieldValueByName("mService").getProxyAs()
+ rootWindowContainer = rootWindowContainer ?: atmService.mRootWindowContainer
+ val caller = args[3] as? String?
+ val context = atmService.mContext ?: return@beforeHook
+ val safeActivityOptions = args[11]?.getProxyAs() ?: return@beforeHook
+ if (AppShareOpt.isShareToApp(caller, intent) && prefs.get(DataConst.SHARE_TO_APP)
+ && !BlackList.AppShareTargetBlacklist.contains(prefs, intent, context)
) {
- if (isShareToApp(callingPackage, intent)) {
- if (prefs.get(DataConst.SHARE_TO_APP)) {
- val mOriginalOptions =
- (args[11]?.getFieldValueOrNull("mOriginalOptions") as? ActivityOptions?)
- mOriginalOptions?.setLaunchWindowingModeExt(5)
- mOriginalOptions?.launchBounds =
- MiuiMultiWindowUtils.getFreeformRect(context)
- }
- } else {
- if (prefs.get(DataConst.PARALLEL_MULTI_WINDOW_PLUS)) {
- intent.removeFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
- }
+ safeActivityOptions.mOriginalOptions?.apply {
+ setLaunchWindowingModeExt(5)
+ launchBounds = MiuiMultiWindowUtils.getFreeformRect(context)
}
}
+ if (
+ prefs.get(DataConst.PARALLEL_MULTI_WINDOW_PLUS)
+ && realCallingPid == context.getPidFromPackageNameExt("com.android.systemui")
+ && !BlackList.ParallelFreeformBlacklist.contains(prefs, intent, context)
+ && safeActivityOptions.mOriginalOptions?.getLaunchWindowingModeExt() == 5
+ ) {
+ ParallelSmallWindowOpt.handle(intent, atmService, rootWindowContainer)
+ }
}
}
}
diff --git a/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/SystemUiHooker.kt b/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/SystemUiHooker.kt
index b5457f2..d7550d9 100644
--- a/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/SystemUiHooker.kt
+++ b/app/src/main/java/org/liuyi/mifreeformx/xposed/hooker/SystemUiHooker.kt
@@ -1,14 +1,18 @@
package org.liuyi.mifreeformx.xposed.hooker
import android.annotation.SuppressLint
+import android.app.PendingIntent
import android.content.Context
import android.content.Intent
-import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.log.loggerD
+import org.liuyi.mifreeformx.BlackList
import org.liuyi.mifreeformx.DataConst
import org.liuyi.mifreeformx.intent_extra.forceFreeFromMode
-import org.liuyi.mifreeformx.proxy.systemui.CommonUtil
+import org.liuyi.mifreeformx.proxy.systemui.AppMiniWindowManager
import org.liuyi.mifreeformx.proxy.systemui.CentralSurfacesImpl
+import org.liuyi.mifreeformx.proxy.systemui.CommonUtil
+import org.liuyi.mifreeformx.proxy.systemui.Dependency
+import org.liuyi.mifreeformx.proxy.systemui.MiuiExpandableNotificationRow
import org.liuyi.mifreeformx.utils.*
import org.liuyi.mifreeformx.xposed.base.LyBaseHooker
@@ -49,7 +53,9 @@ object SystemUiHooker : LyBaseHooker() {
val componentName = intent.resolveActivity(context!!.packageManager)
loggerD(msg = "$topActivity and $componentName")
// 如果是顶部App 则不处理
- if (topActivity?.packageName == componentName.packageName) return@beforeHook
+ if (topActivity?.packageName == componentName.packageName
+ || BlackList.TileBlacklist.contains(prefs, componentName.packageName)
+ ) return@beforeHook
if (prefs.get(DataConst.FORCE_CONTROL_ALL_OPEN) || isTile(intent)) {
intent.forceFreeFromMode()
var flag = args[5] as Int
@@ -75,23 +81,18 @@ object SystemUiHooker : LyBaseHooker() {
loggerD(msg = "${this.args.asList()}")
if (prefs.get(DataConst.OPEN_NOTICE)) {
// 加载类
- val dependencyClass = "com.android.systemui.Dependency".toClass()
val appMiniWindowManagerClass =
"com.android.systemui.statusbar.notification.policy.AppMiniWindowManager".toClass()
-
// 逻辑开始
- val appMiniWindowManager = dependencyClass.method {
- name("get")
- param(Class::class.java)
- }.get().call(appMiniWindowManagerClass)
+ val appMiniWindowManager =
+ Dependency.Proxy.get(appMiniWindowManagerClass).getProxyAs()
- appMiniWindowManagerClass.method { name("launchMiniWindowActivity") }
- .get(appMiniWindowManager).let {
- val targetPkg = args[3]?.javaClass
- ?.method { name("getMiniWindowTargetPkg") }
- ?.get(args[3])?.invoke()
- it.call(targetPkg, args[0])
- }
+ args[3]?.getProxyAs()?.let {
+ appMiniWindowManager.launchMiniWindowActivity(
+ it.getMiniWindowTargetPkg(), args[0] as PendingIntent
+ )
+ resultNull()
+ }
}
}
}
diff --git a/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppJumpOpt.kt b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppJumpOpt.kt
new file mode 100644
index 0000000..3c7045f
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppJumpOpt.kt
@@ -0,0 +1,37 @@
+package org.liuyi.mifreeformx.xposed.operation
+
+import android.content.Context
+import android.content.Intent
+import com.highcapable.yukihookapi.hook.log.loggerD
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/13/7:36:24
+ * @Description:
+ */
+object AppJumpOpt {
+
+ // 应用间跳转
+ fun isAppJump(callingThread: Any?, callingPackage: String?, intent: Intent, context: Context): Boolean {
+ // 排除系统调用
+ callingThread ?: return false
+ // 排除如,系统后台进入,获取桌面进入
+ if (intent.flags and Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED != 0) return false
+ if (callingPackage == "com.miui.securityadd") return false
+ if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0) {
+ // 包含 new 标签
+ val componentName = intent.component ?: intent.resolveActivity(context.packageManager)
+ loggerD(msg = "$componentName")
+ // 修复微信分享回调导致源activity使用小窗
+ if (componentName.className.endsWith(".wxapi.WXEntryActivity")) return false
+ componentName?.packageName?.let { name ->
+ loggerD(msg = name)
+ if (callingPackage != name) {
+ // 判断为应用间跳转
+ return true
+ }
+ }
+ }
+ return false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppShareOpt.kt b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppShareOpt.kt
new file mode 100644
index 0000000..f89d63c
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/AppShareOpt.kt
@@ -0,0 +1,44 @@
+package org.liuyi.mifreeformx.xposed.operation
+
+import android.content.Intent
+import org.liuyi.mifreeformx.DataConst
+import org.liuyi.mifreeformx.intent_extra.forceFreeFromMode
+import org.liuyi.mifreeformx.xposed.hooker.FrameworkBaseHooker
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/13/7:39:12
+ * @Description:
+ */
+object AppShareOpt {
+
+ // 应用间分享
+ internal fun isShareToApp(callingPackage: String?, intent: Intent?): Boolean {
+ if (intent?.`package` == callingPackage) return false
+ intent?.action.let {
+ if (it == Intent.ACTION_SEND) return true
+ // 使用全屏打开 miui 系统选择分享界面
+ if (it == "miui.intent.action.MIUI_CHOOSER") return false
+ }
+ intent?.component?.let {
+ // 微信分享sdk
+ if (it.className == "com.tencent.mm.plugin.base.stub.WXEntryActivity") return true
+ if (it.packageName == callingPackage) return false
+ }
+ if (intent?.clipData != null) return true
+ intent?.data?.let {
+ // QQ分享sdk
+ if (it.scheme == "mqqapi" && it.host == "share") return true
+ }
+ return false
+ }
+
+ internal fun handle(intent: Intent): Boolean {
+ intent.forceFreeFromMode()
+ intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ if (FrameworkBaseHooker.prefs.get(DataConst.SHARE_TO_APP_FORCE_NEW_TASK)) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ return true
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/ParallelSmallWindowOpt.kt b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/ParallelSmallWindowOpt.kt
new file mode 100644
index 0000000..62248d3
--- /dev/null
+++ b/app/src/main/java/org/liuyi/mifreeformx/xposed/operation/ParallelSmallWindowOpt.kt
@@ -0,0 +1,52 @@
+package org.liuyi.mifreeformx.xposed.operation
+
+import android.content.Intent
+import com.highcapable.yukihookapi.hook.log.loggerD
+import org.liuyi.mifreeformx.proxy.framework.ActivityTaskManagerService
+import org.liuyi.mifreeformx.proxy.framework.RootWindowContainer
+import org.liuyi.mifreeformx.utils.isSameApp
+
+/**
+ * @Author: Liuyi
+ * @Date: 2023/05/13/7:08:07
+ * @Description:
+ */
+object ParallelSmallWindowOpt {
+
+ /**
+ * 判断是否来自侧边栏
+ * 逻辑来自手机管家
+ */
+ internal fun isFromSidebar(callingPackage: String?, intent: Intent): Boolean {
+ return callingPackage == "com.miui.securitycenter"
+ && !intent.isSameApp(callingPackage)
+ && intent.action == Intent.ACTION_MAIN
+ && intent.categories.contains(Intent.CATEGORY_LAUNCHER)
+ && intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0
+ }
+
+ /**
+ *
+ * @param intent
+ * @param atmService
+ * @param container
+ * @return 是否运行其他的分支
+ */
+ internal fun handle(
+ intent: Intent,
+ atmService: ActivityTaskManagerService,
+ container: RootWindowContainer?
+ ): Boolean {
+ loggerD(msg = "开启平行小窗: $this")
+ atmService.getTasks(Int.MAX_VALUE).orEmpty().lastOrNull { taskInfo ->
+ // 获得栈底最后一个符合条件的task
+ taskInfo != null && taskInfo.baseActivity == intent.component
+ && taskInfo.isRunning && taskInfo.topActivity == intent.component
+ }?.also {
+ // 如果获取到了将其放入堆栈前
+ loggerD(msg = "已存在一个任务: $it")
+ container?.anyTaskForId(it.taskId)?.moveToFront("god let me do it")
+ } ?: intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ return false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1b34fcc..3ca8451 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -68,4 +68,5 @@
基于 MIUI13(Android12)适配的系统拓展Xposed模块
小窗失去焦点时行为
点击小窗外时触发小窗行为,多小窗情景下谨慎使用
+ 选择应用
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 25ad99d..84be749 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,5 +2,5 @@
plugins {
id 'com.android.application' version '8.0.1' apply false
id 'com.android.library' version '8.0.1' apply false
- id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
+ id 'org.jetbrains.kotlin.android' version '1.8.21' apply false
}
\ No newline at end of file