├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .idea
├── .gitignore
├── .name
├── AndroidProjectSystem.xml
├── appInsightsSettings.xml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── deploymentTargetSelector.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── migrations.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── android-stub
├── .gitignore
├── build.gradle.kts
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ ├── android
│ ├── app
│ │ ├── IActivityTaskManager.java
│ │ └── ITaskStackListener.java
│ ├── content
│ │ └── pm
│ │ │ ├── IPackageManagerHidden.java
│ │ │ ├── PackageManagerHidden.java
│ │ │ └── UserInfo.java
│ ├── hardware
│ │ └── input
│ │ │ └── IInputManager.java
│ ├── view
│ │ ├── IRotationWatcher.java
│ │ ├── IWindowManager.java
│ │ ├── WindowLayoutParamsHidden.java
│ │ └── WindowManagerHidden.java
│ └── window
│ │ └── TaskSnapshot.java
│ └── com
│ └── android
│ └── internal
│ └── statusbar
│ └── IStatusBarService.java
├── app
├── .gitignore
├── build.gradle.kts
├── debug
│ ├── app-debug.apk
│ └── output-metadata.json
├── proguard-rules.pro
├── release
│ ├── app-release.apk
│ ├── app-release.zip
│ ├── baselineProfiles
│ │ ├── 0
│ │ │ └── app-release.dm
│ │ └── 1
│ │ │ └── app-release.dm
│ └── output-metadata.json
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── mja
│ │ └── reyamf
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── aidl
│ │ └── com
│ │ │ └── mja
│ │ │ └── reyamf
│ │ │ └── xposed
│ │ │ ├── IOpenCountListener.aidl
│ │ │ └── IYAMFManager.aidl
│ ├── assets
│ │ └── xposed_init
│ ├── java
│ │ ├── android
│ │ │ └── app
│ │ │ │ └── ITaskStackListenerProxy.kt
│ │ └── com
│ │ │ ├── mja
│ │ │ └── reyamf
│ │ │ │ ├── Application.kt
│ │ │ │ ├── common
│ │ │ │ ├── Utils.kt
│ │ │ │ └── model
│ │ │ │ │ ├── AppInfo.kt
│ │ │ │ │ ├── Config.kt
│ │ │ │ │ ├── FavApps.kt
│ │ │ │ │ └── StartCmd.kt
│ │ │ │ ├── manager
│ │ │ │ ├── Application.kt
│ │ │ │ ├── adapter
│ │ │ │ │ ├── AppListAdapter.kt
│ │ │ │ │ ├── SideBarAdapter.kt
│ │ │ │ │ └── VerticalSpaceItemDecoration.kt
│ │ │ │ ├── broadcastreceiver
│ │ │ │ │ └── BootReceiver.kt
│ │ │ │ ├── providers
│ │ │ │ │ └── ServiceProvider.kt
│ │ │ │ ├── services
│ │ │ │ │ ├── AccessibilityService.kt
│ │ │ │ │ ├── CurrentToFloatingService.kt
│ │ │ │ │ ├── QSEnterWindow.kt
│ │ │ │ │ ├── QSNewWindowService.kt
│ │ │ │ │ ├── QSResetAllWindow.kt
│ │ │ │ │ ├── SidebarHiderService.kt
│ │ │ │ │ └── YAMFManagerProxy.kt
│ │ │ │ ├── sidebar
│ │ │ │ │ └── SideBar.kt
│ │ │ │ ├── ui
│ │ │ │ │ ├── CurrentToFloatingActivity.kt
│ │ │ │ │ ├── main
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ │ └── setting
│ │ │ │ │ │ └── SettingActivity.kt
│ │ │ │ └── utils
│ │ │ │ │ ├── AppContext.kt
│ │ │ │ │ ├── TipUtil.kt
│ │ │ │ │ └── Utils.kt
│ │ │ │ └── xposed
│ │ │ │ ├── hook
│ │ │ │ ├── HookLauncher.kt
│ │ │ │ ├── HookPermission.kt
│ │ │ │ ├── HookPermissionDefault.kt
│ │ │ │ └── HookSystem.kt
│ │ │ │ ├── services
│ │ │ │ ├── UserService.kt
│ │ │ │ └── YAMFManager.kt
│ │ │ │ ├── ui
│ │ │ │ └── window
│ │ │ │ │ ├── AppListWindow.kt
│ │ │ │ │ └── AppWindow.kt
│ │ │ │ └── utils
│ │ │ │ ├── AppInfoCache.kt
│ │ │ │ ├── Instances.kt
│ │ │ │ ├── RunMainThreadQueue.kt
│ │ │ │ ├── TipUtil.kt
│ │ │ │ └── Utils.kt
│ │ │ └── qauxv
│ │ │ ├── ui
│ │ │ └── CommonContextWrapper.java
│ │ │ └── util
│ │ │ ├── Initiator.java
│ │ │ └── SavedInstanceStatePatchedClassReferencer.java
│ └── res
│ │ ├── drawable
│ │ ├── a_bg.xml
│ │ ├── bar_corners_bg.xml
│ │ ├── baseline_apps_24.xml
│ │ ├── baseline_keyboard_double_arrow_left_24.xml
│ │ ├── baseline_restart_alt_24.xml
│ │ ├── demo.gif
│ │ ├── ic_back.xml
│ │ ├── ic_close_24.xml
│ │ ├── ic_error_outline_24.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_maximize.xml
│ │ ├── ic_minimize.xml
│ │ ├── ic_picture_in_picture_alt_24.xml
│ │ ├── ic_round_check_circle_24.xml
│ │ ├── ic_settings_24.xml
│ │ ├── ic_warning_amber_24.xml
│ │ ├── menu_bg.xml
│ │ ├── three_dot_horiz.xml
│ │ └── work_icon.xml
│ │ ├── layout-land
│ │ └── sidebar_itemview.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_setting.xml
│ │ ├── item_app.xml
│ │ ├── sidebar_itemview.xml
│ │ ├── sidebar_layout.xml
│ │ ├── window_app.xml
│ │ └── window_app_list.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-anydpi
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── values-night
│ │ ├── colors.xml
│ │ └── themes.xml
│ │ ├── values-zh
│ │ └── strings.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ids.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── accessibility_service_config.xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── com
│ └── mja
│ └── reyamf
│ └── ExampleUnitTest.kt
├── build.gradle.kts
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - main
5 |
6 | jobs:
7 | contrib-readme-job:
8 | runs-on: ubuntu-latest
9 | name: A job to automate contrib in readme
10 | permissions:
11 | contents: write
12 | pull-requests: write
13 | steps:
14 | - name: Contribute List
15 | uses: akhilmhdh/contributors-readme-action@v2.3.10
16 | env:
17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | reYAMF
--------------------------------------------------------------------------------
/.idea/AndroidProjectSystem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/appInsightsSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | xmlns:android
18 |
19 | ^$
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | xmlns:.*
29 |
30 | ^$
31 |
32 |
33 | BY_NAME
34 |
35 |
36 |
37 |
38 |
39 |
40 | .*:id
41 |
42 | http://schemas.android.com/apk/res/android
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | .*:name
52 |
53 | http://schemas.android.com/apk/res/android
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | name
63 |
64 | ^$
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | style
74 |
75 | ^$
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | .*
85 |
86 | ^$
87 |
88 |
89 | BY_NAME
90 |
91 |
92 |
93 |
94 |
95 |
96 | .*
97 |
98 | http://schemas.android.com/apk/res/android
99 |
100 |
101 | ANDROID_ATTRIBUTE_ORDER
102 |
103 |
104 |
105 |
106 |
107 |
108 | .*
109 |
110 | .*
111 |
112 |
113 | BY_NAME
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetSelector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://t.me/+HjGegWE9jBM0N2Rl)
2 | [](https://github.com/JuanArton/reYAMF)
3 |
4 | # reYAMF
5 |
6 | A fork of YAMF (forked from [YAMFSquared](https://github.com/kaii-lb/YAMFsquared), actually), with my changes.
7 |
8 | (project recreated. Check main-old branch to see previous commit by duzhaokun123 and kaii-lb)
9 |
10 | ## Requirements
11 | - Android 13+ (>= api 33)
12 | - LSPosed
13 |
14 | ## Features
15 | - Launch from recents app icon
16 | - Launch by home button long press (read further)
17 | - Launch from app icon long press from homescreen/app drawer
18 | - Launch from taskbar
19 | - Multiple window support
20 | - Minimize window to take up less space
21 | - Resize window
22 | - FLAG_SECURE support
23 | - Quick Settings tiles
24 | - App Rotation detection
25 | - Custom default window size
26 | - Bunch of others in app :D
27 |
28 | ## My Changes
29 | - Fix crash on Android 15
30 | - Added sidebar. From app list window, long press app icon until the phone vibrate to add app to sidebar.
31 | - Removed custom dpi, replace with auto density according to window size. Increase 'Reduce DPI' number from setting if you feel the app appearance is too big. Setting this value too big may cause crash (I recommended value between 50-100)
32 |
33 | ## Launch by home button long press (or swipe gesture)
34 | - Be willing to give up google assistant
35 | - Go to Settings -> Assistant App
36 | - Change it to reYAMF
37 | - Profit
38 |
39 | ## How to install
40 | - Grab the latest APK from the [releases section](https://github.com/JuanArton/YAMFsquared/releases)
41 | - Install it
42 | - Enable module in LSPosed
43 | - Go to Accessibility Settings and enable reYAMF accessibility service
44 | - Reboot
45 |
46 | ## "API"
47 | - Broadcast `com.mja.reyamf.action.CURRENT_TO_WINDOW` to float the currently visible app
48 | - Maybe more to come
49 |
50 | ## Issues
51 | - The system will crash if the module is different from the injected version, its an xposed thing
52 | - Some apps can't seem to launch in small windows
53 | - Some apps scale abnormally at certain sizes
54 | - Some app restart while being resized. (Will fix by adding lock DPI option)
55 |
56 | ## TODO
57 | - Minimize to app icon (half done? long press minimize button to try)
58 | - RtL support
59 | - Lock window DPI option
60 | - You tell me
61 |
62 | ## Contributors List
63 |
64 |
91 |
92 |
93 | ## Special Thanks
94 | - MASSIVE thanks to [duzhaokun123](https://github.com/duzhaokun123) and [kaii-lb](https://github.com/kaii-lb/YAMFsquared)
95 |
96 | - [AOSP](https://source.android.com/)
97 | - [EzXHelper](https://github.com/KyuubiRan/EzXHelper)
98 | - [FlexboxLayout](https://github.com/google/flexbox-layout)
99 | - [Hide-My-Applist](https://github.com/Dr-TSNG/Hide-My-Applist)
100 | - [LSPosed](https://github.com/LSPosed/LSPosed)
101 | - [Material](https://material.io/)
102 | - [Mi-FreeForm](https://github.com/sunshine0523/Mi-FreeForm)
103 | - [QAuxiliary](https://github.com/cinit/QAuxiliary)
104 | - [ViewBindingUtil](https://github.com/matsudamper/ViewBindingUtil)
105 | - [gson](https://github.com/google/gson)
106 | - [xposed](https://forum.xda-developers.com/xposed)
107 |
--------------------------------------------------------------------------------
/android-stub/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/android-stub/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | }
4 |
5 | android {
6 | compileSdk = 35
7 |
8 | defaultConfig {
9 | minSdk = 31
10 | lint.targetSdk = 35
11 |
12 | consumerProguardFiles("consumer-rules.pro")
13 | }
14 |
15 | buildTypes {
16 | getByName("release") {
17 | isMinifyEnabled = false
18 | proguardFiles(
19 | getDefaultProguardFile("proguard-android-optimize.txt"),
20 | "proguard-rules.pro"
21 | )
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility = JavaVersion.VERSION_11
26 | targetCompatibility = JavaVersion.VERSION_11
27 | }
28 |
29 | namespace = "com.mja.android_stub"
30 | }
31 |
32 | dependencies {
33 | annotationProcessor(libs.rikka.annotation.processor)
34 | compileOnly(libs.rikka.annotation)
35 | compileOnly(libs.androidx.annotation)
36 | compileOnly(libs.rikka.hidden.stub)
37 | }
38 |
--------------------------------------------------------------------------------
/android-stub/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/android-stub/consumer-rules.pro
--------------------------------------------------------------------------------
/android-stub/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/android-stub/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/app/IActivityTaskManager.java:
--------------------------------------------------------------------------------
1 | package android.app;
2 |
3 | import android.os.Binder;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 | import android.os.RemoteException;
7 |
8 | import java.util.List;
9 |
10 | public interface IActivityTaskManager extends IInterface {
11 | void moveRootTaskToDisplay(int taskId, int displayId) throws RemoteException;
12 |
13 | void registerTaskStackListener(ITaskStackListener listener) throws RemoteException;
14 |
15 | void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException;
16 |
17 | ActivityManager.TaskDescription getTaskDescription(int taskId) throws RemoteException;
18 |
19 | List getAllRootTaskInfosOnDisplay(int displayId) throws RemoteException;
20 |
21 | abstract class Stub extends Binder implements IActivityTaskManager {
22 | public static IActivityTaskManager asInterface(IBinder obj) {
23 | throw new UnsupportedOperationException();
24 | }
25 |
26 | @Override
27 | public IBinder asBinder() {
28 | throw new UnsupportedOperationException();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/app/ITaskStackListener.java:
--------------------------------------------------------------------------------
1 | package android.app;
2 |
3 | import android.content.ComponentName;
4 | import android.hardware.display.IDisplayManager;
5 | import android.os.Binder;
6 | import android.os.IBinder;
7 | import android.os.IInterface;
8 | import android.os.RemoteException;
9 | import android.window.TaskSnapshot;
10 |
11 | public interface ITaskStackListener extends IInterface {
12 | // https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/ITaskStackListener.aidl
13 | abstract class Stub extends Binder implements ITaskStackListener {
14 | @Override
15 | public IBinder asBinder() {
16 | throw new UnsupportedOperationException();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/content/pm/IPackageManagerHidden.java:
--------------------------------------------------------------------------------
1 | package android.content.pm;
2 |
3 | import android.content.ComponentName;
4 | import android.os.RemoteException;
5 |
6 | import androidx.annotation.RequiresApi;
7 |
8 | import dev.rikka.tools.refine.RefineAs;
9 |
10 | @RefineAs(IPackageManager.class)
11 | public interface IPackageManagerHidden {
12 | ActivityInfo getActivityInfo(ComponentName className, long flags, int userId)
13 | throws RemoteException;
14 |
15 | ActivityInfo getActivityInfo(ComponentName className, int flags, int userId)
16 | throws RemoteException;
17 | }
18 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/content/pm/PackageManagerHidden.java:
--------------------------------------------------------------------------------
1 | package android.content.pm;
2 |
3 | import android.content.Intent;
4 |
5 | import java.util.List;
6 |
7 | import dev.rikka.tools.refine.RefineAs;
8 |
9 | @RefineAs(PackageManager.class)
10 | public abstract class PackageManagerHidden {
11 | public abstract List queryIntentActivitiesAsUser(Intent intent, int flags, int userId);
12 |
13 | public abstract PackageInfo getPackageInfoAsUser(String packageName,
14 | int flags, int userId) throws PackageManager.NameNotFoundException;
15 |
16 | public abstract ApplicationInfo getApplicationInfoAsUser(String packageName,
17 | int flags, int userId) throws PackageManager.NameNotFoundException;
18 | }
19 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/content/pm/UserInfo.java:
--------------------------------------------------------------------------------
1 | package android.content.pm;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 | import android.os.UserHandle;
6 |
7 | public class UserInfo {
8 |
9 | public static final int FLAG_MANAGED_PROFILE = 0x00000020;
10 |
11 | public int id;
12 | public String name;
13 | public int flags;
14 | public int serialNumber;
15 |
16 | public String userType;
17 |
18 | public boolean isPrimary() {
19 | throw new RuntimeException("STUB");
20 | }
21 |
22 | public boolean isAdmin() {
23 | throw new RuntimeException("STUB");
24 | }
25 |
26 | public boolean isGuest() {
27 | throw new RuntimeException("STUB");
28 | }
29 |
30 | public boolean isRestricted() {
31 | throw new RuntimeException("STUB");
32 | }
33 |
34 | public boolean isProfile() {
35 | throw new RuntimeException("STUB");
36 | }
37 |
38 | public boolean isManagedProfile() {
39 | throw new RuntimeException("STUB");
40 | }
41 |
42 | public boolean isEnabled() {
43 | throw new RuntimeException("STUB");
44 | }
45 |
46 | public UserHandle getUserHandle() {
47 | throw new RuntimeException("STUB");
48 | }
49 |
50 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
51 |
52 | public UserInfo createFromParcel(Parcel in) {
53 | throw new UnsupportedOperationException();
54 | }
55 |
56 | public UserInfo[] newArray(int size) {
57 | throw new UnsupportedOperationException();
58 | }
59 | };
60 | }
61 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/hardware/input/IInputManager.java:
--------------------------------------------------------------------------------
1 | package android.hardware.input;
2 |
3 | import android.os.Binder;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 | import android.os.RemoteException;
7 | import android.view.InputEvent;
8 |
9 | public interface IInputManager extends IInterface {
10 | boolean injectInputEvent(InputEvent ev, int mode) throws RemoteException;
11 |
12 | abstract class Stub extends Binder implements IInputManager {
13 | public static IInputManager asInterface(IBinder obj) {
14 | throw new UnsupportedOperationException();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/view/IRotationWatcher.java:
--------------------------------------------------------------------------------
1 | package android.view;
2 |
3 | import android.os.Binder;
4 |
5 | public interface IRotationWatcher {
6 | void onRotationChanged(int rotation);
7 |
8 | abstract class Stub extends Binder implements IRotationWatcher {
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/view/IWindowManager.java:
--------------------------------------------------------------------------------
1 | package android.view;
2 |
3 | import android.os.Binder;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 | import android.os.RemoteException;
7 |
8 | public interface IWindowManager extends IInterface {
9 |
10 | int watchRotation(IRotationWatcher watcher, int displayId) throws RemoteException;
11 |
12 | void removeRotationWatcher(IRotationWatcher watcher) throws RemoteException;
13 |
14 | abstract class Stub extends Binder implements IWindowManager {
15 | public static IWindowManager asInterface(IBinder obj) {
16 | throw new UnsupportedOperationException();
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/view/WindowLayoutParamsHidden.java:
--------------------------------------------------------------------------------
1 | package android.view;
2 |
3 | import dev.rikka.tools.refine.RefineAs;
4 |
5 | @RefineAs(WindowManager.LayoutParams.class)
6 | public class WindowLayoutParamsHidden {
7 | public int privateFlags;
8 |
9 | public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000;
10 | }
11 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/view/WindowManagerHidden.java:
--------------------------------------------------------------------------------
1 | package android.view;
2 |
3 | import androidx.annotation.IntDef;
4 |
5 | import dev.rikka.tools.refine.RefineAs;
6 |
7 | @RefineAs(WindowManager.class)
8 | public interface WindowManagerHidden {
9 | /**
10 | * Display IME Policy: The IME should appear on the local display.
11 | * @hide
12 | */
13 | int DISPLAY_IME_POLICY_LOCAL = 0;
14 |
15 | /**
16 | * Display IME Policy: The IME should appear on the fallback display.
17 | * @hide
18 | */
19 | int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1;
20 |
21 | /**
22 | * Display IME Policy: The IME should be hidden.
23 | *
24 | * Setting this policy will prevent the IME from making a connection. This
25 | * will prevent any IME from receiving metadata about input.
26 | * @hide
27 | */
28 | int DISPLAY_IME_POLICY_HIDE = 2;
29 |
30 | /**
31 | * @hide
32 | */
33 | @IntDef({
34 | DISPLAY_IME_POLICY_LOCAL,
35 | DISPLAY_IME_POLICY_FALLBACK_DISPLAY,
36 | DISPLAY_IME_POLICY_HIDE,
37 | })
38 | @interface DisplayImePolicy {}
39 |
40 | /**
41 | * Sets the policy for how the display should show IME.
42 | *
43 | * @param displayId Display ID.
44 | * @param imePolicy Indicates the policy for how the display should show IME.
45 | * @hide
46 | */
47 | default void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) {
48 | }
49 |
50 | /**
51 | * Indicates the policy for how the display should show IME.
52 | *
53 | * @param displayId The id of the display.
54 | * @return The policy for how the display should show IME.
55 | * @hide
56 | */
57 | default @DisplayImePolicy int getDisplayImePolicy(int displayId) {
58 | return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/android/window/TaskSnapshot.java:
--------------------------------------------------------------------------------
1 | package android.window;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | public class TaskSnapshot implements Parcelable {
7 | protected TaskSnapshot(Parcel in) {}
8 |
9 | @Override
10 | public void writeToParcel(Parcel dest, int flags) {}
11 |
12 | @Override
13 | public int describeContents() {
14 | return 0;
15 | }
16 |
17 | public static final Creator CREATOR = new Creator() {
18 | @Override
19 | public TaskSnapshot createFromParcel(Parcel in) {
20 | return new TaskSnapshot(in);
21 | }
22 |
23 | @Override
24 | public TaskSnapshot[] newArray(int size) {
25 | return new TaskSnapshot[size];
26 | }
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/android-stub/src/main/java/com/android/internal/statusbar/IStatusBarService.java:
--------------------------------------------------------------------------------
1 | package com.android.internal.statusbar;
2 |
3 | import android.os.Binder;
4 | import android.os.IBinder;
5 | import android.os.IInterface;
6 |
7 | public interface IStatusBarService extends IInterface {
8 |
9 | void collapsePanels();
10 |
11 | abstract class Stub extends Binder implements IStatusBarService {
12 | public static IStatusBarService asInterface(IBinder obj) {
13 | throw new UnsupportedOperationException();
14 | }
15 |
16 | @Override
17 | public IBinder asBinder() {
18 | throw new UnsupportedOperationException();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream
2 |
3 | plugins {
4 | alias(libs.plugins.android.application)
5 | alias(libs.plugins.kotlin.android)
6 | alias(libs.plugins.rikka.tools.refine)
7 | id("kotlin-parcelize")
8 | }
9 |
10 | android {
11 | val buildTime = System.currentTimeMillis()
12 | val baseVersionName = "0.9.8"
13 | namespace = "com.mja.reyamf"
14 | compileSdk = 35
15 |
16 | defaultConfig {
17 | applicationId = "com.mja.reyamf"
18 | minSdk = 33
19 | targetSdk = 35
20 | versionCode = 1
21 | versionName = "$baseVersionName-git.$gitHash${if (isDirty) "-dirty" else ""}"
22 |
23 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
24 |
25 | buildConfigField("long", "BUILD_TIME", buildTime.toString())
26 | }
27 | packaging {
28 | resources.excludes.addAll(
29 | arrayOf(
30 | "META-INF/**",
31 | "kotlin/**"
32 | )
33 | )
34 | }
35 | buildTypes {
36 | release {
37 | isMinifyEnabled = false
38 | isShrinkResources = false
39 | proguardFiles(
40 | getDefaultProguardFile("proguard-android-optimize.txt"),
41 | "proguard-rules.pro"
42 | )
43 | }
44 | }
45 | compileOptions {
46 | sourceCompatibility = JavaVersion.VERSION_11
47 | targetCompatibility = JavaVersion.VERSION_11
48 | }
49 | kotlinOptions {
50 | jvmTarget = "11"
51 | languageVersion = "2.0"
52 | }
53 | buildFeatures {
54 | viewBinding = true
55 | aidl = true
56 | buildConfig = true
57 | }
58 | lint {
59 | abortOnError = false
60 | }
61 | }
62 |
63 | dependencies {
64 |
65 | implementation(libs.androidx.core.ktx)
66 | implementation(libs.androidx.appcompat)
67 | implementation(libs.material)
68 | implementation(libs.androidx.activity)
69 | implementation(libs.androidx.constraintlayout)
70 | implementation(libs.androidx.wear)
71 | testImplementation(libs.junit)
72 | androidTestImplementation(libs.androidx.junit)
73 | androidTestImplementation(libs.androidx.espresso.core)
74 | implementation(libs.androidx.preference.ktx)
75 |
76 | compileOnly(project(":android-stub"))
77 | compileOnly(libs.rikka.hidden.stub)
78 | implementation(libs.rikka.hidden.compat)
79 |
80 | //never upgrade until new extension function
81 | //noinspection GradleDependency
82 | implementation(libs.ezxhelper)
83 | compileOnly(libs.xposed.api)
84 |
85 | //lifecycle
86 | implementation(libs.androidx.lifecycle.viewmodel.ktx)
87 | implementation(libs.androidx.lifecycle.livedata.ktx)
88 |
89 | //flexbox
90 | implementation(libs.flexbox)
91 |
92 | //dynamicanimation
93 | implementation(libs.androidx.dynamicanimation.ktx)
94 |
95 | //gson
96 | implementation(libs.gson)
97 |
98 | //material
99 | implementation(libs.material)
100 |
101 | //glide
102 | implementation (libs.glide)
103 |
104 | // byte buddy
105 | implementation(libs.byte.buddy.android)
106 | }
107 |
108 | val gitHash: String
109 | get() {
110 | val out = ByteArrayOutputStream()
111 | val cmd = exec {
112 | commandLine("git", "rev-parse", "--short", "HEAD")
113 | standardOutput = out
114 | isIgnoreExitValue = true
115 | }
116 | return if (cmd.exitValue == 0)
117 | out.toString().trim()
118 | else
119 | "(error)"
120 | }
121 |
122 | val isDirty: Boolean
123 | get() {
124 | val out = ByteArrayOutputStream()
125 | exec {
126 | commandLine("git", "diff", "--stat")
127 | standardOutput = out
128 | isIgnoreExitValue = true
129 | }
130 | return out.size() != 0
131 | }
--------------------------------------------------------------------------------
/app/debug/app-debug.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/debug/app-debug.apk
--------------------------------------------------------------------------------
/app/debug/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "com.mja.reyamf",
8 | "variantName": "debug",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 1,
15 | "versionName": "0.9.2-git.2b15d16-dirty",
16 | "outputFile": "app-debug.apk"
17 | }
18 | ],
19 | "elementType": "File",
20 | "minSdkVersionForDexing": 33
21 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class com.mja.reyamf.** { *; }
2 | -keepclassmembers class com.android.dx.dex.cf.CfTranslator { public static *** translate(...); }
3 | -dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings
4 | -dontwarn javax.annotation.Nonnull
--------------------------------------------------------------------------------
/app/release/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/release/app-release.apk
--------------------------------------------------------------------------------
/app/release/app-release.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/release/app-release.zip
--------------------------------------------------------------------------------
/app/release/baselineProfiles/0/app-release.dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/release/baselineProfiles/0/app-release.dm
--------------------------------------------------------------------------------
/app/release/baselineProfiles/1/app-release.dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/release/baselineProfiles/1/app-release.dm
--------------------------------------------------------------------------------
/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "com.mja.reyamf",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 1,
15 | "versionName": "0.9.7-git.ced9113",
16 | "outputFile": "app-release.apk"
17 | }
18 | ],
19 | "elementType": "File",
20 | "baselineProfiles": [
21 | {
22 | "minApi": 28,
23 | "maxApi": 30,
24 | "baselineProfiles": [
25 | "baselineProfiles/1/app-release.dm"
26 | ]
27 | },
28 | {
29 | "minApi": 31,
30 | "maxApi": 2147483647,
31 | "baselineProfiles": [
32 | "baselineProfiles/0/app-release.dm"
33 | ]
34 | }
35 | ],
36 | "minSdkVersionForDexing": 33
37 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/mja/reyamf/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.mja.reyamf", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
19 |
20 |
23 |
24 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
44 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
62 |
63 |
64 |
70 |
71 |
72 |
73 |
74 |
79 |
80 |
81 |
82 |
83 |
86 |
87 |
88 |
89 |
93 |
94 |
98 |
99 |
100 |
101 |
102 |
103 |
106 |
109 |
112 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/app/src/main/aidl/com/mja/reyamf/xposed/IOpenCountListener.aidl:
--------------------------------------------------------------------------------
1 | // IOpenCountListener.aidl
2 | package com.mja.reyamf.xposed;
3 |
4 | // Declare any non-default types here with import statements
5 |
6 | interface IOpenCountListener {
7 | void onUpdate(int count);
8 | }
--------------------------------------------------------------------------------
/app/src/main/aidl/com/mja/reyamf/xposed/IYAMFManager.aidl:
--------------------------------------------------------------------------------
1 | // IYAMFManager.aidl
2 | package com.mja.reyamf.xposed;
3 |
4 | import com.mja.reyamf.xposed.IOpenCountListener;
5 | // Declare any non-default types here with import statements
6 |
7 | interface IYAMFManager {
8 | String getVersionName();
9 |
10 | int getVersionCode();
11 |
12 | int getUid();
13 |
14 | void createWindow();
15 |
16 | long getBuildTime();
17 |
18 | String getConfigJson();
19 |
20 | void updateConfig(String newConfig);
21 |
22 | void registerOpenCountListener(IOpenCountListener iOpenCountListener);
23 |
24 | void unregisterOpenCountListener(IOpenCountListener iOpenCountListener);
25 |
26 | void openAppList();
27 |
28 | void currentToWindow();
29 |
30 | void resetAllWindow();
31 |
32 | void launchSideBar();
33 |
34 | void killSideBar();
35 | }
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | com.mja.reyamf.xposed.hook.HookSystem
2 | com.mja.reyamf.xposed.hook.HookLauncher
3 | com.mja.reyamf.xposed.hook.HookPermission
4 | com.mja.reyamf.xposed.hook.HookPermissionDefault
--------------------------------------------------------------------------------
/app/src/main/java/android/app/ITaskStackListenerProxy.kt:
--------------------------------------------------------------------------------
1 | package android.app
2 |
3 | import android.util.Log
4 | import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
5 | import com.github.kyuubiran.ezxhelper.init.InitFields
6 | import com.mja.reyamf.xposed.ui.window.AppWindow
7 | import com.mja.reyamf.xposed.ui.window.AppWindow.Companion.TAG
8 | import com.mja.reyamf.xposed.utils.byteBuddyStrategy
9 | import net.bytebuddy.ByteBuddy
10 | import net.bytebuddy.implementation.MethodDelegation
11 | import net.bytebuddy.implementation.bind.annotation.AllArguments
12 | import net.bytebuddy.implementation.bind.annotation.Origin
13 | import net.bytebuddy.implementation.bind.annotation.RuntimeType
14 | import net.bytebuddy.matcher.ElementMatchers
15 | import java.lang.reflect.Method
16 |
17 | object ITaskStackListenerProxy {
18 | fun newInstance(
19 | classLoader: ClassLoader,
20 | intercept: (Array, Method) -> Any?
21 | ): ITaskStackListener {
22 | return ByteBuddy()
23 | .subclass(ITaskStackListener.Stub::class.java)
24 | .method(ElementMatchers.any())
25 | .intercept(MethodDelegation.to(object {
26 | @RuntimeType
27 | fun intercept(
28 | @AllArguments allArguments: Array,
29 | @Origin method: Method
30 | ) {
31 | intercept(allArguments, method)
32 | }
33 | }))
34 | .make()
35 | .load(classLoader, byteBuddyStrategy)
36 | .loaded
37 | .getDeclaredConstructor()
38 | .newInstance()
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/Application.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf
2 |
3 | import android.app.Application
4 | import com.google.android.material.color.DynamicColors
5 | import com.mja.reyamf.manager.utils.AppContext
6 |
7 | lateinit var application: Application
8 |
9 | class Application: Application() {
10 |
11 | init {
12 | application = this
13 | AppContext.context = this
14 | }
15 |
16 | override fun onCreate() {
17 | super.onCreate()
18 |
19 | DynamicColors.applyToActivitiesIfAvailable(this)
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/common/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.common
2 |
3 | import android.content.res.Resources
4 | import android.util.TypedValue
5 | import androidx.annotation.AttrRes
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.google.gson.Gson
8 | import kotlinx.coroutines.CoroutineScope
9 | import kotlinx.coroutines.DelicateCoroutinesApi
10 | import kotlinx.coroutines.Dispatchers
11 | import kotlinx.coroutines.GlobalScope
12 | import kotlinx.coroutines.launch
13 |
14 | val gson by lazy { Gson() }
15 |
16 | fun RecyclerView.resetAdapter() {
17 | this.adapter = adapter
18 | }
19 |
20 | inline fun Result.onException(action: (exception: Exception) -> Unit): Result =
21 | this.onFailure { t ->
22 | if (t is Error) throw t
23 | action(t as Exception)
24 | }
25 |
26 | @OptIn(DelicateCoroutinesApi::class)
27 | fun runMain(block: suspend CoroutineScope.() -> Unit) =
28 | GlobalScope.launch(Dispatchers.Main, block = block)
29 |
30 | @OptIn(DelicateCoroutinesApi::class)
31 | fun runIO(block: suspend CoroutineScope.() -> Unit) =
32 | GlobalScope.launch(Dispatchers.IO, block = block)
33 |
34 | fun Resources.Theme.getAttr(@AttrRes id: Int) =
35 | TypedValue().apply { resolveAttribute(id, this, true) }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/common/model/AppInfo.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.common.model
2 |
3 | import android.content.ComponentName
4 | import android.graphics.drawable.Drawable
5 | import android.os.Parcelable
6 | import kotlinx.parcelize.Parcelize
7 | import kotlinx.parcelize.RawValue
8 |
9 | @Parcelize
10 | data class AppInfo(
11 | val id: Int,
12 | val icon: @RawValue Drawable,
13 | val label: CharSequence,
14 | val componentName: ComponentName,
15 | val userId: Int
16 | ) : Parcelable
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/common/model/Config.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.common.model
2 |
3 | data class Config(
4 | var reduceDPI: Int = 50,
5 | /*
6 | * VIRTUAL_DISPLAY_FLAG_SECURE 1 << 2
7 | * VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT 1 << 7
8 | * VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 1 << 9
9 | * VIRTUAL_DISPLAY_FLAG_TRUSTED 1 << 10
10 | */
11 | var flags: Int = 1668,
12 | var coloredController: Boolean = false,
13 | /*
14 | * 0: move task only
15 | * 1: start activity only
16 | * 2: move task, failback to start activity
17 | */
18 | var windowfy: Int = 0,
19 | /*
20 | * 0: TextureView
21 | * 1: SurfaceView
22 | */
23 | var surfaceView: Int = 0,
24 | var recentBackHome: Boolean = false,
25 | var showImeInWindow: Boolean = false,
26 | var defaultWindowWidth: Int = 280,
27 | var defaultWindowHeight: Int = 380,
28 | var hookLauncher: HookLauncher = HookLauncher(),
29 | var showForceShowIME: Boolean = false,
30 | var portraitY: Int = 0,
31 | var landscapeY: Int = 0,
32 | var favApps: MutableList = mutableListOf(),
33 | var launchSideBarAtBoot: Boolean = false,
34 | var enableSidebar: Boolean = true,
35 | var sidebarTransparency: Int = 80,
36 | var windowRoundedCorner: Int = 20,
37 | var sidebarPosition: Boolean = false //false=left, true=right
38 | ) {
39 | data class HookLauncher(
40 | var hookRecents: Boolean = true,
41 | var hookTaskbar: Boolean = true,
42 | var hookPopup: Boolean = true,
43 | var hookTransientTaskbar: Boolean = false,
44 | )
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/common/model/FavApps.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.common.model
2 |
3 | import android.os.Parcelable
4 | import kotlinx.parcelize.Parcelize
5 |
6 | @Parcelize
7 | data class FavApps(
8 | val packageName: String,
9 | val userId: Int
10 | ): Parcelable
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/common/model/StartCmd.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.common.model
2 |
3 | import android.content.ComponentName
4 |
5 | data class StartCmd(
6 | val componentName: ComponentName? = null,
7 | val userId: Int? = null,
8 | val taskId: Int? = null
9 | ) {
10 | val canStartActivity
11 | get() = componentName != null && userId != null
12 |
13 | val canMoveTask
14 | get() = taskId != null && taskId != 0
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/Application.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager
2 |
3 | import com.google.android.material.color.DynamicColors
4 | import com.mja.reyamf.manager.utils.AppContext
5 |
6 | lateinit var application: Application
7 |
8 | class Application: android.app.Application() {
9 | init {
10 | application = this
11 | AppContext.context = this
12 | }
13 |
14 | override fun onCreate() {
15 | super.onCreate()
16 | DynamicColors.applyToActivitiesIfAvailable(this)
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/adapter/AppListAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.adapter
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.mja.reyamf.R
8 | import com.mja.reyamf.common.model.AppInfo
9 | import com.mja.reyamf.databinding.ItemAppBinding
10 |
11 | class AppListAdapter (
12 | private val onClick: (AppInfo) -> Unit,
13 | private val appList: ArrayList,
14 | private val onLongClick: (AppInfo) -> Unit
15 | ) : RecyclerView.Adapter() {
16 |
17 | fun setData(items: List?) {
18 | appList.apply {
19 | clear()
20 | items?.let { addAll(it) }
21 | }
22 | }
23 | override fun onCreateViewHolder(
24 | parent: ViewGroup,
25 | viewType: Int
26 | ): ViewHolder {
27 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_app, parent, false)
28 | return ViewHolder(view)
29 | }
30 | override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(appList[position])
31 |
32 | override fun getItemCount(): Int = appList.size
33 |
34 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
35 | private val binding = ItemAppBinding.bind(itemView)
36 | fun bind(appInfo: AppInfo){
37 | binding.apply {
38 | val icon = appInfo.icon
39 | val label = appInfo.label
40 | ivIcon.setImageDrawable(icon)
41 | tvLabel.text = label
42 |
43 | ll.setOnClickListener {
44 | onClick(appInfo)
45 | }
46 |
47 | ll.setOnLongClickListener {
48 | onLongClick(appInfo)
49 | true
50 | }
51 | }
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/adapter/SideBarAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.adapter
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.github.kyuubiran.ezxhelper.utils.Log
8 | import com.mja.reyamf.R
9 | import com.mja.reyamf.common.model.AppInfo
10 | import com.mja.reyamf.databinding.SidebarItemviewBinding
11 |
12 | class SideBarAdapter (
13 | private val onClick: (AppInfo) -> Unit,
14 | private val sideBarApp: ArrayList,
15 | private val onLongClick: (Int) -> Unit
16 | ) : RecyclerView.Adapter() {
17 |
18 | fun setData(items: List?) {
19 | android.util.Log.d("XPOSED", items?.size.toString())
20 | sideBarApp.apply {
21 | clear()
22 | items?.let { addAll(it) }
23 | }
24 | }
25 |
26 | override fun onCreateViewHolder(
27 | parent: ViewGroup,
28 | viewType: Int
29 | ): ViewHolder {
30 | val view = LayoutInflater.from(parent.context).inflate(R.layout.sidebar_itemview, parent, false)
31 | return ViewHolder(view)
32 | }
33 |
34 | override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(sideBarApp[position])
35 |
36 | override fun getItemCount(): Int = sideBarApp.size
37 |
38 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
39 | private val binding = SidebarItemviewBinding.bind(itemView)
40 | fun bind(appInfo: AppInfo){
41 | binding.apply {
42 | ivAppIcon.setImageDrawable(appInfo.icon)
43 | ivAppIcon.setOnClickListener {
44 | onClick(appInfo)
45 | }
46 | ivAppIcon.setOnLongClickListener {
47 | onLongClick(adapterPosition)
48 | true
49 | }
50 | if (appInfo.userId == 0) {
51 | ivWorkIcon.visibility = View.INVISIBLE
52 | }
53 | }
54 | }
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/adapter/VerticalSpaceItemDecoration.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.adapter
2 |
3 | import android.graphics.Rect
4 | import android.view.View
5 | import androidx.recyclerview.widget.RecyclerView
6 |
7 | class VerticalSpaceItemDecoration(private val verticalSpaceHeight: Int) : RecyclerView.ItemDecoration() {
8 | override fun getItemOffsets(
9 | outRect: Rect,
10 | view: View,
11 | parent: RecyclerView,
12 | state: RecyclerView.State
13 | ) {
14 | outRect.bottom = verticalSpaceHeight
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/broadcastreceiver/BootReceiver.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.broadcastreceiver
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import com.mja.reyamf.common.gson
7 | import com.mja.reyamf.common.model.Config
8 | import com.mja.reyamf.manager.services.YAMFManagerProxy
9 |
10 | class BootReceiver : BroadcastReceiver() {
11 |
12 | lateinit var config: Config
13 |
14 | override fun onReceive(context: Context, intent: Intent) {
15 | if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
16 | config = gson.fromJson(YAMFManagerProxy.configJson, Config::class.java)
17 |
18 | if (config.launchSideBarAtBoot) {
19 | YAMFManagerProxy.launchSideBar()
20 | }
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/providers/ServiceProvider.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.providers
2 |
3 | import android.content.ContentProvider
4 | import android.content.ContentValues
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import com.mja.reyamf.manager.services.YAMFManagerProxy
8 |
9 | class ServiceProvider: ContentProvider() {
10 | override fun onCreate() = false
11 |
12 | override fun query(
13 | uri: Uri,
14 | projection: Array?,
15 | selection: String?,
16 | selectionArgs: Array?,
17 | sortOrder: String?
18 | ) = null
19 |
20 | override fun getType(uri: Uri) = null
21 |
22 | override fun insert(uri: Uri, values: ContentValues?) = null
23 |
24 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?) = 0
25 |
26 | override fun update(
27 | uri: Uri,
28 | values: ContentValues?,
29 | selection: String?,
30 | selectionArgs: Array?
31 | ) = 0
32 |
33 | override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
34 | if (callingPackage != "android" || extras == null) return null
35 | val binder = extras.getBinder("binder") ?: return null
36 | YAMFManagerProxy.linkService(binder)
37 | return Bundle()
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/AccessibilityService.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.accessibilityservice.AccessibilityService
4 | import android.view.accessibility.AccessibilityEvent
5 |
6 | class AccessibilityService : AccessibilityService() {
7 | override fun onAccessibilityEvent(event: AccessibilityEvent?) {
8 |
9 | }
10 |
11 | override fun onInterrupt() {
12 |
13 | }
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/CurrentToFloatingService.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.content.Intent
4 | import android.service.voice.VoiceInteractionService
5 | import android.util.Log
6 |
7 | class CurrentToFloatingService : VoiceInteractionService() {
8 | override fun onCreate() {
9 | super.onCreate()
10 |
11 | val intent = Intent()
12 | intent.action = "com.mja.reyamf.action.CURRENT_TO_WINDOW"
13 | intent.addCategory(Intent.CATEGORY_DEFAULT)
14 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
15 |
16 | Log.d("reYAMFDWOO", "long pressed")
17 |
18 | sendBroadcast(intent)
19 | }
20 |
21 | override fun onReady() {
22 | super.onReady()
23 |
24 | Log.d("reYAMFWOO", "readyyyyyyyy")
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/QSEnterWindow.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.service.quicksettings.TileService
4 |
5 | class QSEnterWindow: TileService() {
6 | override fun onClick() {
7 | super.onClick()
8 | YAMFManagerProxy.currentToWindow()
9 | }
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/QSNewWindowService.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.service.quicksettings.TileService
4 | import androidx.preference.PreferenceManager
5 |
6 | class QSNewWindowService : TileService() {
7 | override fun onClick() {
8 | super.onClick()
9 | if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("useAppList", true))
10 | YAMFManagerProxy.openAppList()
11 | else YAMFManagerProxy.createWindow()
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/QSResetAllWindow.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.service.quicksettings.TileService
4 |
5 | class QSResetAllWindow: TileService() {
6 | override fun onClick() {
7 | YAMFManagerProxy.resetAllWindow()
8 | }
9 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/SidebarHiderService.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.app.Service
4 | import android.content.Intent
5 | import android.os.IBinder
6 |
7 | class SidebarHiderService : Service() {
8 | override fun onBind(intent: Intent?): IBinder? {
9 | return null
10 | }
11 |
12 | override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
13 | val receivedString = intent?.getStringExtra("act")
14 | receivedString?.let {
15 | if (it == "KILL") {
16 | YAMFManagerProxy.killSideBar()
17 | } else {
18 | YAMFManagerProxy.launchSideBar()
19 | }
20 | stopSelf()
21 | }
22 | return START_NOT_STICKY
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/services/YAMFManagerProxy.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.services
2 |
3 | import android.os.IBinder
4 | import android.os.IBinder.DeathRecipient
5 | import android.util.Log
6 | import com.mja.reyamf.xposed.IOpenCountListener
7 | import com.mja.reyamf.xposed.IYAMFManager
8 | import java.lang.reflect.InvocationHandler
9 | import java.lang.reflect.Method
10 | import java.lang.reflect.Proxy
11 |
12 | object YAMFManagerProxy : IYAMFManager, DeathRecipient {
13 | private const val TAG = "reYAMFManagerProxy"
14 |
15 | private class ServiceProxy(private val obj: IYAMFManager) : InvocationHandler {
16 | override fun invoke(proxy: Any?, method: Method, args: Array?): Any? {
17 | val result = method.invoke(obj, *args.orEmpty())
18 | if (result == null) Log.i(TAG, "Call service method ${method.name}")
19 | else Log.i(
20 | TAG,
21 | "Call service method ${method.name} with result " + result.toString().take(20)
22 | )
23 | return result
24 | }
25 | }
26 |
27 | @Volatile
28 | private var service: IYAMFManager? = null
29 |
30 | fun linkService(binder: IBinder) {
31 | service = Proxy.newProxyInstance(
32 | javaClass.classLoader,
33 | arrayOf(IYAMFManager::class.java),
34 | ServiceProxy(IYAMFManager.Stub.asInterface(binder))
35 | ) as IYAMFManager
36 | binder.linkToDeath(this, 0)
37 | }
38 |
39 | override fun binderDied() {
40 | service = null
41 | Log.e(TAG, "Binder died")
42 | }
43 |
44 | override fun asBinder() = service?.asBinder()
45 |
46 | override fun getVersionName(): String? {
47 | return service?.versionName
48 | }
49 |
50 | override fun getVersionCode() = service?.versionCode ?: 0
51 |
52 | override fun getUid() = service?.uid ?: -1
53 |
54 | override fun createWindow() {
55 | service?.createWindow()
56 | }
57 |
58 | override fun getBuildTime(): Long {
59 | return service?.buildTime ?: 0
60 | }
61 |
62 | override fun getConfigJson(): String {
63 | return service?.configJson ?: "{}"
64 | }
65 |
66 | override fun updateConfig(newConfig: String) {
67 | service?.updateConfig(newConfig)
68 | }
69 |
70 | override fun registerOpenCountListener(iOpenCountListener: IOpenCountListener) {
71 | service?.registerOpenCountListener(iOpenCountListener)
72 | }
73 |
74 | override fun unregisterOpenCountListener(iOpenCountListener: IOpenCountListener) {
75 | service?.unregisterOpenCountListener(iOpenCountListener)
76 | }
77 |
78 | override fun openAppList() {
79 | service?.openAppList()
80 | }
81 |
82 | override fun currentToWindow() {
83 | service?.currentToWindow()
84 | }
85 |
86 | override fun resetAllWindow() {
87 | service?.resetAllWindow()
88 | }
89 |
90 | override fun launchSideBar() {
91 | service?.launchSideBar()
92 | }
93 |
94 | override fun killSideBar() {
95 | service?.killSideBar()
96 | }
97 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/ui/CurrentToFloatingActivity.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.ui
2 |
3 | import android.app.Activity
4 | import android.os.Bundle
5 | import android.util.Log
6 | import com.mja.reyamf.manager.services.YAMFManagerProxy
7 |
8 |
9 | class CurrentToFloatingActivity : Activity() {
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | finish()
13 |
14 | // val intent = Intent(this, CurrentToFloatingService::class.java)
15 | // intent.setAction(Intent.ACTION_ASSIST)
16 |
17 | // val intent = Intent()
18 | // intent.action = "com.mja.reyamf.action.ACTION_OPEN_IN_YAMF"
19 | // intent.addCategory(Intent.CATEGORY_DEFAULT)
20 | // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
21 |
22 | Log.d("reYAMFWOO", "long pressed")
23 |
24 | // startService(intent)
25 | // sendBroadcast(intent)
26 |
27 | YAMFManagerProxy.currentToWindow()
28 |
29 | // finish()
30 | }
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/ui/main/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.ui.main
2 |
3 | import android.content.Intent
4 | import android.os.Build
5 | import android.os.Bundle
6 | import android.os.Handler
7 | import android.os.Looper
8 | import android.util.Log
9 | import android.util.TypedValue
10 | import android.view.Menu
11 | import android.view.MenuItem
12 | import android.view.View
13 | import androidx.activity.enableEdgeToEdge
14 | import androidx.appcompat.app.AppCompatActivity
15 | import androidx.core.net.toUri
16 | import androidx.core.view.ViewCompat
17 | import androidx.core.view.WindowInsetsCompat
18 | import com.bumptech.glide.Glide
19 | import com.google.android.material.color.MaterialColors
20 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
21 | import com.google.android.material.slider.Slider
22 | import com.mja.reyamf.BuildConfig
23 | import com.mja.reyamf.R
24 | import com.mja.reyamf.common.getAttr
25 | import com.mja.reyamf.common.gson
26 | import com.mja.reyamf.common.model.Config
27 | import com.mja.reyamf.common.runMain
28 | import com.mja.reyamf.databinding.ActivityMainBinding
29 | import com.mja.reyamf.manager.services.YAMFManagerProxy
30 | import com.mja.reyamf.manager.sidebar.SideBar
31 | import com.mja.reyamf.manager.ui.setting.SettingActivity
32 | import com.mja.reyamf.manager.utils.TipUtil
33 | import com.mja.reyamf.xposed.IOpenCountListener
34 | import com.mja.reyamf.xposed.utils.log
35 | import kotlinx.coroutines.CoroutineScope
36 | import kotlinx.coroutines.Dispatchers
37 | import kotlinx.coroutines.delay
38 | import kotlinx.coroutines.launch
39 |
40 | class MainActivity : AppCompatActivity() {
41 |
42 | private var _binding: ActivityMainBinding? = null
43 | private val binding get() = _binding
44 | lateinit var config: Config
45 |
46 | companion object {
47 | const val TAG = "reYAMF_MainActivity"
48 | }
49 |
50 | private val openCountListener = object : IOpenCountListener.Stub() {
51 | override fun onUpdate(count: Int) {
52 | runMain {
53 | binding?.tvOpenCount?.text = count.toString()
54 | }
55 | }
56 | }
57 |
58 | override fun onCreate(savedInstanceState: Bundle?) {
59 | super.onCreate(savedInstanceState)
60 | enableEdgeToEdge()
61 | _binding = ActivityMainBinding.inflate(layoutInflater)
62 | setContentView(binding?.root)
63 | ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
64 | val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
65 | v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
66 | insets
67 | }
68 | val typedValue = TypedValue()
69 | this@MainActivity.theme.resolveAttribute(android.R.attr.textColor, typedValue, true)
70 | binding?.toolbar?.overflowIcon?.setTint(typedValue.data)
71 |
72 | setSupportActionBar(binding?.toolbar)
73 | supportActionBar?.setDisplayShowTitleEnabled(false)
74 |
75 | YAMFManagerProxy.registerOpenCountListener(openCountListener)
76 | initUi()
77 | }
78 |
79 | private fun initUi() {
80 | config = gson.fromJson(YAMFManagerProxy.configJson, Config::class.java)
81 | val buildTime = YAMFManagerProxy.buildTime
82 | when(buildTime) {
83 | 0L -> {
84 | binding?.apply {
85 | ivIcon.setImageResource(R.drawable.ic_error_outline_24)
86 | tvActive.setText(R.string.not_activated)
87 | tvVersion.visibility = View.GONE
88 | val colorError = theme.getAttr(com.google.android.material.R.attr.colorError).data
89 | val colorOnError = theme.getAttr(com.google.android.material.R.attr.colorOnError).data
90 | mcvStatus.setCardBackgroundColor(colorError)
91 | mcvStatus.outlineAmbientShadowColor = colorError
92 | mcvStatus.outlineSpotShadowColor = colorError
93 | tvActive.setTextColor(colorOnError)
94 | tvVersion.setTextColor(colorOnError)
95 | mcvInfo.visibility = View.GONE
96 | mcvSideBar.visibility = View.GONE
97 | }
98 | }
99 | BuildConfig.BUILD_TIME -> {
100 | binding?.apply {
101 | ivIcon.setImageResource(R.drawable.ic_round_check_circle_24)
102 | tvActive.setText(R.string.activated)
103 | tvVersion.text = buildString {
104 | append(YAMFManagerProxy.versionName)
105 | append(" (${YAMFManagerProxy.versionCode})")
106 | }
107 | }
108 | }
109 | else -> {
110 | binding?.apply {
111 | ivIcon.setImageResource(R.drawable.ic_warning_amber_24)
112 | tvActive.setText(R.string.need_reboot)
113 | tvVersion.text = buildString {
114 | append("system: ${YAMFManagerProxy.versionName} (${YAMFManagerProxy.versionCode})\n")
115 | append("module: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
116 | }
117 | mcvStatus.setCardBackgroundColor(MaterialColors.harmonizeWithPrimary(this@MainActivity, getColor(R.color.color_warning)))
118 | mcvStatus.setOnClickListener {
119 | MaterialAlertDialogBuilder(this@MainActivity)
120 | .setTitle(R.string.need_reboot)
121 | .setMessage(R.string.need_reboot_message)
122 | .setPositiveButton(R.string.reboot) { _, _->
123 | TipUtil.showTip(this@MainActivity, "do it yourself")
124 | }
125 | .show()
126 | }
127 | sliderTransparency.value = config.sidebarTransparency.toFloat()
128 | tvTransparencyValue.text = "${config.sidebarTransparency}"
129 | }
130 | }
131 | }
132 |
133 | if (Build.VERSION.PREVIEW_SDK_INT != 0) {
134 | binding?.systemVersion?.text = buildString {
135 | append(Build.VERSION.CODENAME)
136 | append("Preview (API ${Build.VERSION.SDK_INT})")
137 | }
138 | } else {
139 | binding?.systemVersion?.text = buildString {
140 | append(Build.VERSION.RELEASE)
141 | append("(API ${Build.VERSION.SDK_INT})")
142 | }
143 | }
144 | binding?.tvBuildType?.text = BuildConfig.BUILD_TYPE
145 |
146 | binding?.apply {
147 | btLaunchSideBar.setOnClickListener {
148 | YAMFManagerProxy.launchSideBar()
149 | }
150 |
151 | msSideBar.isChecked = config.launchSideBarAtBoot
152 | msSideBar.setOnCheckedChangeListener { _, isChecked ->
153 | config.launchSideBarAtBoot = isChecked
154 | YAMFManagerProxy.updateConfig(gson.toJson(config))
155 | }
156 |
157 | msSideBarPosition.isChecked = config.sidebarPosition
158 | msSideBarPosition.setOnCheckedChangeListener { _, isChecked ->
159 | config.sidebarPosition = isChecked
160 | YAMFManagerProxy.updateConfig(gson.toJson(config))
161 | CoroutineScope(Dispatchers.IO).launch {
162 | YAMFManagerProxy.killSideBar()
163 | delay(1000)
164 | YAMFManagerProxy.launchSideBar()
165 | }
166 | }
167 |
168 | ivDemo.let {
169 | Glide.with(this@MainActivity)
170 | .load(R.drawable.demo)
171 | .into(it)
172 | }
173 |
174 | if (config.enableSidebar) {
175 | innerClSidebar.visibility = View.VISIBLE
176 | } else {
177 | innerClSidebar.visibility = View.GONE
178 | }
179 |
180 | msEnableSideBar.isChecked = config.enableSidebar
181 |
182 | msEnableSideBar.setOnCheckedChangeListener { _, isChecked ->
183 | if (isChecked) {
184 | innerClSidebar.visibility = View.VISIBLE
185 | } else {
186 | innerClSidebar.visibility = View.GONE
187 | }
188 |
189 | config.enableSidebar = isChecked
190 | YAMFManagerProxy.updateConfig(gson.toJson(config))
191 | }
192 |
193 | sliderTransparency.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
194 | override fun onStartTrackingTouch(slider: Slider) {}
195 |
196 | override fun onStopTrackingTouch(slider: Slider) {
197 | tvTransparencyValue.text = "${slider.value.toInt()}"
198 | config.sidebarTransparency = slider.value.toInt()
199 | YAMFManagerProxy.updateConfig(gson.toJson(config))
200 | YAMFManagerProxy.killSideBar()
201 |
202 | Handler(Looper.getMainLooper()).postDelayed({
203 | try {
204 | Log.d(SideBar.TAG, "updateConfig: restart")
205 | YAMFManagerProxy.launchSideBar()
206 | } catch (e: Exception) {
207 | log(SideBar.TAG, "Failed restart sidebar")
208 | }
209 | }, 500)
210 | }
211 | })
212 | }
213 | }
214 |
215 | override fun onCreateOptionsMenu(menu: Menu?): Boolean {
216 | menuInflater.inflate(R.menu.menu_main, menu)
217 | return true
218 | }
219 |
220 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
221 | return when(item.itemId) {
222 | R.id.new_window -> {
223 | YAMFManagerProxy.createWindow()
224 | true
225 | }
226 | R.id.channel -> {
227 | startActivity(Intent(Intent.ACTION_VIEW).apply {
228 | data = "https://t.me/+HjGegWE9jBM0N2Rl".toUri()
229 | })
230 | true
231 | }
232 | R.id.open_app_list -> {
233 | YAMFManagerProxy.openAppList()
234 | true
235 | }
236 | R.id.settings -> {
237 | startActivity(Intent(this, SettingActivity::class.java))
238 | true
239 | }
240 | R.id.github -> {
241 | startActivity(Intent(Intent.ACTION_VIEW).apply {
242 | data = "https://github.com/JuanArton/reYAMF".toUri()
243 | })
244 | true
245 | }
246 | R.id.donate -> {
247 | startActivity(Intent(Intent.ACTION_VIEW).apply {
248 | data = "https://duzhaokun123.github.io/donate.html".toUri()
249 | })
250 | true
251 | }
252 | R.id.current_to_window -> {
253 | YAMFManagerProxy.currentToWindow()
254 | true
255 | }
256 | else -> false
257 | }
258 | }
259 |
260 | override fun onDestroy() {
261 | super.onDestroy()
262 | YAMFManagerProxy.unregisterOpenCountListener(openCountListener)
263 | }
264 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/ui/setting/SettingActivity.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.ui.setting
2 |
3 | import android.content.Intent
4 | import android.content.SharedPreferences
5 | import android.content.res.ColorStateList
6 | import android.graphics.Color
7 | import android.os.Build
8 | import android.os.Bundle
9 | import android.os.Handler
10 | import android.os.Looper
11 | import android.util.Log
12 | import androidx.activity.enableEdgeToEdge
13 | import androidx.appcompat.app.AppCompatActivity
14 | import androidx.appcompat.widget.PopupMenu
15 | import androidx.core.content.ContextCompat
16 | import androidx.core.net.toUri
17 | import androidx.core.view.ViewCompat
18 | import androidx.core.view.WindowInsetsCompat
19 | import androidx.preference.PreferenceManager
20 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
21 | import com.google.android.material.slider.Slider
22 | import com.mja.reyamf.R
23 | import com.mja.reyamf.common.gson
24 | import com.mja.reyamf.databinding.ActivitySettingBinding
25 | import com.mja.reyamf.manager.services.YAMFManagerProxy
26 | import com.mja.reyamf.manager.sidebar.SideBar
27 | import com.mja.reyamf.xposed.utils.log
28 | import com.mja.reyamf.common.model.Config as YAMFConfig
29 |
30 | class SettingActivity : AppCompatActivity() {
31 |
32 | private var _binding: ActivitySettingBinding? = null
33 | private val binding get() = _binding
34 |
35 | companion object {
36 | val flags = listOf(
37 | "VIRTUAL_DISPLAY_FLAG_PUBLIC", // 1 << 0
38 | "VIRTUAL_DISPLAY_FLAG_PRESENTATION", // 1 << 1
39 | "VIRTUAL_DISPLAY_FLAG_SECURE", // 1 << 2
40 | "VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY", // 1 << 3
41 | "VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR", // 1 << 4
42 | "VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD", // 1 << 5
43 | "VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH", // 1 << 6
44 | "VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT", // 1 << 7
45 | "VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL", // 1 << 8
46 | "VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS", // 1 << 9
47 | "VIRTUAL_DISPLAY_FLAG_TRUSTED", // 1 << 10
48 | "VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP", // 1 << 11
49 | "VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED", // 1 << 12
50 | "VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED", // 1 << 13
51 | )
52 | }
53 |
54 | lateinit var config: YAMFConfig
55 | private val preference: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
56 |
57 | override fun onCreate(savedInstanceState: Bundle?) {
58 | super.onCreate(savedInstanceState)
59 | enableEdgeToEdge()
60 | _binding = ActivitySettingBinding.inflate(layoutInflater)
61 | setContentView(binding?.root)
62 | ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
63 | val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
64 | v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
65 | insets
66 | }
67 |
68 | initData()
69 | }
70 |
71 | private fun initData() {
72 | binding?.apply {
73 | config = gson.fromJson(YAMFManagerProxy.configJson, YAMFConfig::class.java)
74 | etReduceDPI.setText(config.reduceDPI.toString())
75 | btnFlags.text = config.flags.toString()
76 | sColoerd.isChecked = config.coloredController
77 | sBackHome.isChecked = config.recentBackHome
78 | sShowIMEinWindow.isChecked = config.showImeInWindow
79 | etSizeH.setText(config.defaultWindowHeight.toString())
80 | etSizeW.setText(config.defaultWindowWidth.toString())
81 | sHookLauncherHookRecents.isChecked = config.hookLauncher.hookRecents
82 | sHookLauncherHookTaskbar.isChecked = config.hookLauncher.hookTaskbar
83 | sHookLauncherHookPopup.isChecked = config.hookLauncher.hookPopup
84 | sHookLauncherHookTransientTaskbar.isChecked = config.hookLauncher.hookTransientTaskbar
85 | sUseAppList.isChecked = preference.getBoolean("useAppList", true)
86 | sForceShowIME.isChecked = config.showForceShowIME
87 | sliderRounded.value = config.windowRoundedCorner.toFloat()
88 | tvRoundedValue.text = "${config.windowRoundedCorner}"
89 |
90 | btnSurface.text = when (config.surfaceView) {
91 | 0 -> {
92 | "Texture View"
93 | }
94 | 1 -> {
95 | "Surface View"
96 | }
97 | else -> {
98 | Log.d("reYAMF", "surfaceView: " + config.surfaceView.toString())
99 | "Unavailable"
100 | }
101 | }
102 |
103 | btnWindowsfy.text = when (config.windowfy) {
104 | 0 -> {
105 | "Move Task"
106 | }
107 | 1 -> {
108 | "Start Activity"
109 | }
110 | 2 -> {
111 | "Hybrid"
112 | }
113 | else -> {
114 | Log.d("reYAMF", "windowfy: " + config.windowfy.toString())
115 | "Unavailable"
116 | }
117 | }
118 |
119 | btnFlags.setOnClickListener {
120 | val checks = BooleanArray(flags.size) { i ->
121 | config.flags and (1 shl i) != 0
122 | }
123 | MaterialAlertDialogBuilder(this@SettingActivity)
124 | .setMultiChoiceItems(flags.toTypedArray(), checks) { _, i, c ->
125 | checks[i] = c
126 | btnFlags.text = checks.foldIndexed(0) { i, f, b ->
127 | if (b)
128 | f + (1 shl i)
129 | else
130 | f
131 | }.toString()
132 | }
133 | .setPositiveButton("about") { _, _ ->
134 | startActivity(Intent(Intent.ACTION_VIEW).apply {
135 | data = "https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/hardware/display/DisplayManager.java".toUri()
136 | })
137 | }
138 | .show()
139 | }
140 | btnWindowsfy.setOnClickListener {
141 | PopupMenu(this@SettingActivity, btnWindowsfy).apply {
142 | listOf("Move Task", "Start Activity", "Hybrid").forEach { i ->
143 | menu.add(i).setOnMenuItemClickListener {
144 | btnWindowsfy.text = i
145 | true
146 | }
147 | }
148 | }.show()
149 | }
150 | btnSurface.setOnClickListener {
151 | PopupMenu(this@SettingActivity, btnSurface).apply {
152 | listOf("Texture View", "Surface View").forEach { i ->
153 | menu.add(i).setOnMenuItemClickListener {
154 | btnSurface.text = i
155 | true
156 | }
157 | }
158 | }.show()
159 | }
160 | sliderRounded.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
161 | override fun onStartTrackingTouch(slider: Slider) {}
162 |
163 | override fun onStopTrackingTouch(slider: Slider) {
164 | tvRoundedValue.text = "${slider.value.toInt()}"
165 | config.windowRoundedCorner = slider.value.toInt()
166 | YAMFManagerProxy.updateConfig(gson.toJson(config))
167 | }
168 | })
169 | }
170 | }
171 |
172 | override fun onDestroy() {
173 | super.onDestroy()
174 | binding?.apply {
175 | config.reduceDPI = etReduceDPI.text.toString().toIntOrNull() ?: config.reduceDPI
176 | config.flags = btnFlags.text.toString().toIntOrNull() ?: config.flags
177 | config.surfaceView = when (val surface = btnSurface.text.toString()) {
178 | "Texture View" -> {
179 | 0
180 | }
181 | "Surface View" -> {
182 | 1
183 | }
184 | else -> {
185 | Log.d("YAMF", "surface value: $surface")
186 | 0
187 | }
188 | }
189 |
190 | config.windowfy = when (val window = btnWindowsfy.text.toString()) {
191 | "Move Task" -> {
192 | 0
193 | }
194 | "Start Activity" -> {
195 | 1
196 | }
197 | "Hybrid" -> {
198 | 2
199 | }
200 | else -> {
201 | Log.d("reYAMF", "window value: $window")
202 | 0
203 | }
204 | }
205 | config.coloredController = sColoerd.isChecked
206 | config.recentBackHome = sBackHome.isChecked
207 | config.showImeInWindow = sShowIMEinWindow.isChecked
208 | config.defaultWindowHeight = etSizeH.text.toString().toIntOrNull() ?: config.defaultWindowHeight
209 | config.defaultWindowWidth = etSizeW.text.toString().toIntOrNull() ?: config.defaultWindowWidth
210 | config.hookLauncher.hookRecents = sHookLauncherHookRecents.isChecked
211 | config.hookLauncher.hookTaskbar = sHookLauncherHookTaskbar.isChecked
212 | config.hookLauncher.hookPopup = sHookLauncherHookPopup.isChecked
213 | config.hookLauncher.hookTransientTaskbar = sHookLauncherHookTransientTaskbar.isChecked
214 | config.showForceShowIME = sForceShowIME.isChecked
215 | preference.edit().putBoolean("useAppList", sUseAppList.isChecked).apply()
216 | YAMFManagerProxy.updateConfig(gson.toJson(config))
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/utils/AppContext.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 |
6 | @SuppressLint("StaticFieldLeak")
7 | object AppContext {
8 | lateinit var context: Context
9 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/utils/TipUtil.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.utils
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.widget.TextView
6 | import android.widget.Toast
7 | import androidx.annotation.StringRes
8 | import androidx.coordinatorlayout.widget.CoordinatorLayout
9 | import androidx.core.view.isVisible
10 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
11 | import com.google.android.material.snackbar.BaseTransientBottomBar
12 | import com.google.android.material.snackbar.Snackbar
13 | import com.mja.reyamf.R
14 | import com.mja.reyamf.common.runMain
15 | import com.mja.reyamf.manager.application
16 |
17 | object TipUtil {
18 | private val map = mutableMapOf()
19 |
20 | fun registerCoordinatorLayout(context: Context, coordinatorLayout: CoordinatorLayout?) {
21 | coordinatorLayout?.let { map[context.hashCode()] = it }
22 | }
23 |
24 | fun unregisterCoordinatorLayout(context: Context) {
25 | map.remove(context.hashCode())
26 | }
27 |
28 | fun showToast(msg: CharSequence?) {
29 | runMain {
30 | Toast.makeText(application, "$msg", Toast.LENGTH_LONG).show()
31 | }
32 | }
33 |
34 | fun showToast(@StringRes resId: Int) =
35 | showToast(application.getText(resId))
36 |
37 | private fun showSnackbar(coordinatorLayout: CoordinatorLayout, msg: CharSequence?) {
38 | runMain {
39 | Snackbar.make(coordinatorLayout, "$msg", BaseTransientBottomBar.LENGTH_LONG).show()
40 | }
41 | }
42 |
43 | fun showSnackbar(coordinatorLayout: CoordinatorLayout, @StringRes resId: Int) =
44 | showSnackbar(coordinatorLayout, application.getText(resId))
45 |
46 | private fun showSnackbar(coordinatorLayout: CoordinatorLayout, t: Throwable) {
47 | runMain {
48 | val msg = t.localizedMessage ?: t.message ?: application.getString(R.string.unknown_error)
49 | Snackbar.make(coordinatorLayout, msg, BaseTransientBottomBar.LENGTH_LONG)
50 | .setAction(R.string.details) {
51 | MaterialAlertDialogBuilder(coordinatorLayout.context)
52 | .setTitle(msg)
53 | .setMessage("${t.message}\n${t.stackTraceToString()}")
54 | .show()
55 | .findViewById(android.R.id.message)
56 | ?.setTextIsSelectable(true)
57 | }.show()
58 | }
59 | }
60 |
61 | fun showTip(context: Context?, t: Throwable) {
62 | val msg = t.localizedMessage ?: t.message ?: "Unknown Error"
63 | if (context == null || (context is Activity && context.window.decorView.isVisible.not())) {
64 | showToast(msg)
65 | return
66 | }
67 | map[context.hashCode()]?.let {
68 | showSnackbar(it, t)
69 | return
70 | }
71 | showToast(msg)
72 | }
73 |
74 | fun showTip(context: Context?, msg: CharSequence?) {
75 | if (context == null || (context is Activity && context.window.decorView.isVisible.not())) {
76 | showToast(msg)
77 | return
78 | }
79 | map[context.hashCode()]?.let {
80 | showSnackbar(it, msg)
81 | return
82 | }
83 | showToast(msg)
84 | }
85 |
86 | fun showTip(context: Context?, @StringRes resId: Int) =
87 | showTip(context, application.getText(resId))
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/manager/utils/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.manager.utils
2 |
3 | import androidx.core.view.WindowInsetsCompat
4 |
5 | val WindowInsetsCompat.maxSystemBarsDisplayCutout
6 | get() = getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
7 |
8 | val WindowInsetsCompat.maxSystemBarsDisplayCutoutIme
9 | get() = getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() or WindowInsetsCompat.Type.ime())
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/hook/HookPermission.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.hook
2 |
3 | import android.app.AndroidAppHelper
4 | import android.app.Application
5 | import android.content.ComponentName
6 | import android.content.Context
7 | import android.content.Intent
8 | import android.os.Bundle
9 | import android.util.Log
10 | import com.mja.reyamf.manager.services.YAMFManagerProxy
11 | import com.mja.reyamf.xposed.utils.Instances.systemContext
12 | import de.robv.android.xposed.IXposedHookLoadPackage
13 | import de.robv.android.xposed.XC_MethodHook
14 | import de.robv.android.xposed.XposedBridge
15 | import de.robv.android.xposed.XposedHelpers
16 | import de.robv.android.xposed.callbacks.XC_LoadPackage
17 |
18 | class HookPermission : IXposedHookLoadPackage {
19 | private var classLoader: ClassLoader? = null
20 |
21 |
22 | override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
23 | if (lpparam.packageName !="com.google.android.permissioncontroller") {
24 | return
25 | }
26 |
27 | XposedHelpers.findAndHookMethod(Application::class.java, "attach", Context::class.java, object : XC_MethodHook() {
28 | override fun afterHookedMethod(param: MethodHookParam) {
29 | classLoader = (param.thisObject as Application).classLoader
30 | XposedBridge.log("Hooked into ${lpparam.packageName}")
31 | intentHook()
32 | }
33 | })
34 | }
35 |
36 | private fun intentHook() {
37 | try {
38 |
39 | XposedHelpers.findAndHookMethod(
40 | "com.android.permissioncontroller.permission.ui.GrantPermissionsActivity",
41 | classLoader,
42 | "onCreate",
43 | Bundle::class.java,
44 | object : XC_MethodHook() {
45 | override fun beforeHookedMethod(param: MethodHookParam) {
46 |
47 | val serviceIntent = Intent().apply {
48 | setComponent(
49 | ComponentName(
50 | "com.mja.reyamf",
51 | "com.mja.reyamf.manager.services.SidebarHiderService"
52 | )
53 | )
54 | putExtra("act", "KILL")
55 | }
56 | AndroidAppHelper.currentApplication().startService(serviceIntent)
57 | }
58 | }
59 | )
60 |
61 | XposedHelpers.findAndHookMethod(
62 | "com.android.permissioncontroller.permission.ui.GrantPermissionsActivity",
63 | classLoader,
64 | "onDestroy",
65 | object : XC_MethodHook() {
66 | override fun afterHookedMethod(param: MethodHookParam) {
67 |
68 | val serviceIntent = Intent().apply {
69 | setComponent(
70 | ComponentName(
71 | "com.mja.reyamf",
72 | "com.mja.reyamf.manager.services.SidebarHiderService"
73 | )
74 | )
75 | putExtra("act", "LAUNCH")
76 | }
77 | AndroidAppHelper.currentApplication().startService(serviceIntent)
78 | }
79 | }
80 | )
81 | } catch (e: Throwable) {
82 | XposedBridge.log(e)
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/hook/HookPermissionDefault.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.hook
2 |
3 | import android.app.AndroidAppHelper
4 | import android.app.Application
5 | import android.content.ComponentName
6 | import android.content.Context
7 | import android.content.Intent
8 | import android.os.Bundle
9 | import de.robv.android.xposed.IXposedHookLoadPackage
10 | import de.robv.android.xposed.XC_MethodHook
11 | import de.robv.android.xposed.XposedBridge
12 | import de.robv.android.xposed.XposedHelpers
13 | import de.robv.android.xposed.callbacks.XC_LoadPackage
14 |
15 | class HookPermissionDefault : IXposedHookLoadPackage {
16 | private var classLoader: ClassLoader? = null
17 |
18 |
19 | override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
20 | if (lpparam.packageName !="com.android.permissioncontroller") {
21 | return
22 | }
23 |
24 | XposedHelpers.findAndHookMethod(Application::class.java, "attach", Context::class.java, object : XC_MethodHook() {
25 | override fun afterHookedMethod(param: MethodHookParam) {
26 | classLoader = (param.thisObject as Application).classLoader
27 | XposedBridge.log("Hooked into ${lpparam.packageName}")
28 | intentHook()
29 | }
30 | })
31 | }
32 |
33 | private fun intentHook() {
34 | try {
35 |
36 | XposedHelpers.findAndHookMethod(
37 | "com.android.permissioncontroller.permission.ui.GrantPermissionsActivity",
38 | classLoader,
39 | "onCreate",
40 | Bundle::class.java,
41 | object : XC_MethodHook() {
42 | override fun beforeHookedMethod(param: MethodHookParam) {
43 |
44 | val serviceIntent = Intent().apply {
45 | setComponent(
46 | ComponentName(
47 | "com.mja.reyamf",
48 | "com.mja.reyamf.manager.services.SidebarHiderService"
49 | )
50 | )
51 | putExtra("act", "KILL")
52 | }
53 | AndroidAppHelper.currentApplication().startService(serviceIntent)
54 | }
55 | }
56 | )
57 |
58 | XposedHelpers.findAndHookMethod(
59 | "com.android.permissioncontroller.permission.ui.GrantPermissionsActivity",
60 | classLoader,
61 | "onDestroy",
62 | object : XC_MethodHook() {
63 | override fun afterHookedMethod(param: MethodHookParam) {
64 |
65 | val serviceIntent = Intent().apply {
66 | setComponent(
67 | ComponentName(
68 | "com.mja.reyamf",
69 | "com.mja.reyamf.manager.services.SidebarHiderService"
70 | )
71 | )
72 | putExtra("act", "LAUNCH")
73 | }
74 | AndroidAppHelper.currentApplication().startService(serviceIntent)
75 | }
76 | }
77 | )
78 | } catch (e: Throwable) {
79 | XposedBridge.log(e)
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/hook/HookSystem.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.hook
2 |
3 | import android.content.Intent
4 | import android.content.pm.IPackageManager
5 | import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
6 | import com.github.kyuubiran.ezxhelper.utils.findMethod
7 | import com.github.kyuubiran.ezxhelper.utils.hookAfter
8 | import com.github.kyuubiran.ezxhelper.utils.hookBefore
9 | import com.mja.reyamf.BuildConfig
10 | import com.mja.reyamf.xposed.services.UserService
11 | import com.mja.reyamf.xposed.services.YAMFManager
12 | import com.mja.reyamf.xposed.utils.log
13 | import com.qauxv.util.Initiator
14 | import de.robv.android.xposed.IXposedHookLoadPackage
15 | import de.robv.android.xposed.IXposedHookZygoteInit
16 | import de.robv.android.xposed.XC_MethodHook
17 | import de.robv.android.xposed.callbacks.XC_LoadPackage
18 | import kotlin.concurrent.thread
19 |
20 |
21 | class HookSystem : IXposedHookZygoteInit, IXposedHookLoadPackage {
22 | companion object {
23 | private const val TAG = "reYAMF_HookSystem"
24 | }
25 |
26 | override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
27 | EzXHelperInit.initZygote(startupParam)
28 | }
29 |
30 | override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
31 | if (lpparam.packageName != "android") return
32 | log(TAG, "xposed init")
33 | log(TAG, "buildtype: ${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE}) ${BuildConfig.BUILD_TYPE}")
34 | EzXHelperInit.initHandleLoadPackage(lpparam)
35 | Initiator.init(lpparam.classLoader)
36 |
37 | var serviceManagerHook: XC_MethodHook.Unhook? = null
38 | serviceManagerHook = findMethod("android.os.ServiceManager") {
39 | name == "addService"
40 | }.hookBefore { param ->
41 | if (param.args[0] == "package") {
42 | serviceManagerHook?.unhook()
43 | val pms = param.args[1] as IPackageManager
44 | log(TAG, "Got pms: $pms")
45 | thread {
46 | runCatching {
47 | UserService.register(pms)
48 | log(TAG, "UserService started")
49 | }.onFailure {
50 | log(TAG, "UserService failed to start", it)
51 | }
52 | }
53 | }
54 | }
55 |
56 | var activityManagerServiceSystemReadyHook: XC_MethodHook.Unhook? = null
57 | activityManagerServiceSystemReadyHook = findMethod("com.android.server.am.ActivityManagerService") {
58 | name == "systemReady"
59 | }.hookAfter {
60 | activityManagerServiceSystemReadyHook?.unhook()
61 | YAMFManager.activityManagerService = it.thisObject
62 | YAMFManager.systemReady()
63 | log(TAG, "system ready")
64 | }
65 |
66 | findMethod("com.android.server.am.ActivityManagerService") {
67 | name == "checkBroadcastFromSystem"
68 | }.hookBefore {
69 | val intent = it.args[0] as Intent
70 | if (intent.action == HookLauncher.ACTION_RECEIVE_LAUNCHER_CONFIG)
71 | it.result = Unit // bypass check
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/services/UserService.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.services
2 |
3 | import android.app.ActivityManagerHidden
4 | import android.content.AttributionSource
5 | import android.content.pm.IPackageManager
6 | import android.os.Bundle
7 | import android.os.ServiceManager
8 | import com.mja.reyamf.BuildConfig
9 | import com.mja.reyamf.xposed.utils.log
10 | import rikka.hidden.compat.ActivityManagerApis
11 | import rikka.hidden.compat.adapter.UidObserverAdapter
12 |
13 | object UserService {
14 | const val TAG = "reYAMFUserService"
15 | const val PROVIDER_AUTHORITY = "com.mja.reyamf.ServiceProvider"
16 |
17 | private var appUid = -1
18 |
19 | private val uidObserver = object : UidObserverAdapter() {
20 | override fun onUidActive(uid: Int) {
21 | if (uid != appUid) return
22 | try {
23 | val provider = ActivityManagerApis.getContentProviderExternal(
24 | PROVIDER_AUTHORITY,
25 | 0,
26 | null,
27 | null
28 | )
29 | if (provider == null) {
30 | log(TAG, "Failed to get content provider")
31 | return
32 | }
33 | val extras = Bundle()
34 | extras.putBinder("binder", YAMFManager)
35 | val attr = AttributionSource.Builder(1000).setPackageName("android").build()
36 | val reply = provider.call(attr, PROVIDER_AUTHORITY, "", null, extras)
37 | if (reply == null) {
38 | log(TAG, "Failed to send binder to app")
39 | return
40 | }
41 | log(TAG, "Send binder to app")
42 | } catch (e: Throwable) {
43 | log(TAG, "Failed to send binder to app", e)
44 | }
45 | }
46 | }
47 |
48 | fun register(pms: IPackageManager) {
49 | log(TAG, "Init YAMFService")
50 | appUid =
51 | pms.getPackageUid(BuildConfig.APPLICATION_ID, 0L, 0)
52 | log(TAG, "App uid: $appUid")
53 | log(TAG, "Register uid observer")
54 |
55 | waitSystemService("activity")
56 | ActivityManagerApis.registerUidObserver(
57 | uidObserver,
58 | ActivityManagerHidden.UID_OBSERVER_ACTIVE,
59 | ActivityManagerHidden.PROCESS_STATE_UNKNOWN,
60 | null
61 | )
62 | }
63 |
64 | private fun waitSystemService(name: String) {
65 | while (ServiceManager.getService(name) == null) {
66 | Thread.sleep(1000)
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/utils/AppInfoCache.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.utils
2 |
3 | import android.content.pm.ActivityInfo
4 | import android.graphics.drawable.Drawable
5 | import androidx.wear.widget.RoundedDrawable
6 |
7 | object AppInfoCache {
8 | fun getIconLabel(info: ActivityInfo): Pair {
9 | return Pair(
10 | RoundedDrawable().apply {
11 | isClipEnabled = true
12 | radius = 100
13 | drawable = info.loadIcon(Instances.packageManager)
14 | },
15 | info.loadLabel(Instances.packageManager)
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/utils/Instances.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.ActivityManager
5 | import android.app.IActivityTaskManager
6 | import android.content.Context
7 | import android.content.pm.IPackageManager
8 | import android.content.pm.PackageManager
9 | import android.hardware.display.DisplayManager
10 | import android.hardware.input.IInputManager
11 | import android.os.ServiceManager
12 | import android.os.UserManager
13 | import android.view.IWindowManager
14 | import android.view.WindowManager
15 | import android.widget.FrameLayout
16 | import androidx.constraintlayout.widget.ConstraintLayout
17 | import com.android.internal.statusbar.IStatusBarService
18 | import com.github.kyuubiran.ezxhelper.utils.getObjectAs
19 |
20 | @SuppressLint("StaticFieldLeak")
21 | object Instances {
22 | lateinit var windowManager: WindowManager
23 | private set
24 | lateinit var iWindowManager: IWindowManager
25 | private set
26 | lateinit var inputManager: IInputManager
27 | private set
28 | lateinit var displayManager: DisplayManager
29 | private set
30 | lateinit var activityTaskManager: IActivityTaskManager
31 | private set
32 | lateinit var packageManager: PackageManager
33 | private set
34 | lateinit var activityManager: ActivityManager
35 | private set
36 | lateinit var userManager: UserManager
37 | private set
38 | lateinit var iPackageManager: IPackageManager
39 | private set
40 | lateinit var iStatusBarService: IStatusBarService
41 | private set
42 | private lateinit var activityManagerService: Any
43 | private set
44 | lateinit var systemContext: Context
45 | private set
46 | val systemUiContext: Context
47 | get() = activityManagerService.getObjectAs("mUiContext")
48 |
49 |
50 | fun init(activityManagerService: Any) {
51 | Instances.activityManagerService = activityManagerService
52 | systemContext = activityManagerService.getObjectAs("mContext")
53 | windowManager = systemContext.getSystemService(WindowManager::class.java)
54 | iWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"))
55 | inputManager = IInputManager.Stub.asInterface(ServiceManager.getService("input"))
56 | displayManager = systemContext.getSystemService(DisplayManager::class.java)
57 | activityTaskManager =
58 | IActivityTaskManager.Stub.asInterface(ServiceManager.getService("activity_task"))
59 | packageManager = systemContext.packageManager
60 | activityManager = systemContext.getSystemService(ActivityManager::class.java)
61 | userManager = systemContext.getSystemService(UserManager::class.java)
62 | iPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
63 | iStatusBarService =
64 | IStatusBarService.Stub.asInterface(ServiceManager.getService("statusbar"))
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/utils/RunMainThreadQueue.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.utils
2 |
3 | import com.mja.reyamf.common.runMain
4 | import kotlinx.coroutines.CoroutineScope
5 | import java.util.LinkedList
6 |
7 | object RunMainThreadQueue {
8 | private val queue = LinkedList Unit>()
9 |
10 | @Synchronized
11 | fun add(run: suspend CoroutineScope.() -> Unit) {
12 | queue.offer(run)
13 | if (queue.size == 1) {
14 | runMain {
15 | while (queue.isNotEmpty()) {
16 | queue.poll()?.invoke(this)
17 | }
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/utils/TipUtil.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.widget.Toast
5 |
6 | @SuppressLint("StaticFieldLeak")
7 | object TipUtil {
8 | fun showToast(msg: String) {
9 | Toast.makeText(Instances.systemContext, "[reYAMF] $msg", Toast.LENGTH_LONG).show()
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/mja/reyamf/xposed/utils/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf.xposed.utils
2 |
3 | import android.animation.Animator
4 | import android.animation.AnimatorListenerAdapter
5 | import android.animation.AnimatorSet
6 | import android.animation.ValueAnimator
7 | import android.annotation.SuppressLint
8 | import android.app.ActivityOptions
9 | import android.app.ActivityTaskManager
10 | import android.content.BroadcastReceiver
11 | import android.content.ComponentName
12 | import android.content.Context
13 | import android.content.ContextParams
14 | import android.content.Intent
15 | import android.content.pm.ActivityInfo
16 | import android.content.pm.IPackageManagerHidden
17 | import android.content.res.Resources
18 | import android.os.Bundle
19 | import android.os.UserHandle
20 | import android.os.VibrationEffect
21 | import android.os.Vibrator
22 | import android.provider.Settings
23 | import android.util.TypedValue
24 | import android.view.View
25 | import android.view.animation.AccelerateDecelerateInterpolator
26 | import android.view.animation.AlphaAnimation
27 | import android.view.animation.Animation
28 | import android.view.animation.ScaleAnimation
29 | import com.github.kyuubiran.ezxhelper.utils.Log
30 | import com.github.kyuubiran.ezxhelper.utils.argTypes
31 | import com.github.kyuubiran.ezxhelper.utils.args
32 | import com.github.kyuubiran.ezxhelper.utils.invokeMethod
33 | import com.github.kyuubiran.ezxhelper.utils.newInstance
34 | import com.mja.reyamf.common.model.StartCmd
35 | import com.mja.reyamf.common.onException
36 | import com.mja.reyamf.xposed.services.YAMFManager
37 | import net.bytebuddy.android.AndroidClassLoadingStrategy
38 | import java.io.File
39 | import de.robv.android.xposed.XposedBridge
40 |
41 | fun log(tag: String, message: String) {
42 | XposedBridge.log("[$tag] $message")
43 | }
44 |
45 | fun log(tag: String, message: String, t: Throwable) {
46 | XposedBridge.log("[$tag] $message")
47 | XposedBridge.log(t)
48 | }
49 |
50 | @SuppressLint("MissingPermission")
51 | fun moveTask(taskId: Int, displayId: Int) {
52 | Instances.activityTaskManager.moveRootTaskToDisplay(taskId, displayId)
53 | Instances.activityManager.moveTaskToFront(taskId, 0)
54 | }
55 |
56 | fun Number.dpToPx() =
57 | TypedValue.applyDimension(
58 | TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics
59 | )
60 |
61 | val emptyContextParams = ContextParams.Builder().build()
62 |
63 | fun Context.createContext() = createContext(emptyContextParams)
64 |
65 | fun startActivity(context: Context, componentName: ComponentName, userId: Int, displayId: Int) {
66 | context.invokeMethod(
67 | "startActivityAsUser",
68 | args(
69 | Intent().apply {
70 | addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
71 | component = componentName
72 | `package` = component!!.packageName
73 | action = Intent.ACTION_VIEW
74 | },
75 | ActivityOptions.makeBasic().apply {
76 | launchDisplayId = displayId
77 | this.invokeMethod("setCallerDisplayId", args(displayId), argTypes(Integer.TYPE))
78 | }.toBundle(),
79 | UserHandle::class.java.newInstance(
80 | args(userId),
81 | argTypes(Integer.TYPE)
82 | )
83 | ), argTypes(Intent::class.java, Bundle::class.java, UserHandle::class.java)
84 | )
85 | }
86 |
87 | fun moveToDisplay(context: Context, taskId: Int, componentName: ComponentName, userId: Int, displayId: Int) {
88 | when (YAMFManager.config.windowfy) {
89 | 0 -> {
90 | runCatching {
91 | moveTask(taskId, displayId)
92 | }.onException {
93 | TipUtil.showToast("Unable to move task $taskId")
94 | }
95 | }
96 | 1 -> {
97 | runCatching {
98 | startActivity(context, componentName, userId, displayId)
99 | }.onException {
100 | TipUtil.showToast("Unable to start activity $componentName")
101 | }
102 | }
103 | 2 -> {
104 | runCatching {
105 | moveTask(taskId, displayId)
106 | }.onException {
107 | TipUtil.showToast("Unable to move task $taskId")
108 | runCatching {
109 | startActivity(context, componentName, userId, displayId)
110 | }.onException {
111 | TipUtil.showToast("Unable to start activity $componentName")
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 | fun StartCmd.startAuto(displayId: Int) {
119 | when {
120 | canStartActivity && canMoveTask ->
121 | moveToDisplay(Instances.systemContext, taskId!!, componentName!!, userId!!, displayId)
122 | canMoveTask -> {
123 | runCatching {
124 | moveTask(taskId!!, displayId)
125 | }.onException {
126 | TipUtil.showToast("can't move task $taskId")
127 | }
128 | }
129 | canStartActivity -> {
130 | runCatching {
131 | startActivity(Instances.systemContext, componentName!!, userId!!, displayId)
132 | }.onException {
133 | TipUtil.showToast("can't start activity $componentName")
134 | }
135 | }
136 | }
137 | }
138 |
139 | fun getTopRootTask(displayId: Int): ActivityTaskManager.RootTaskInfo? {
140 | Instances.activityTaskManager.getAllRootTaskInfosOnDisplay(displayId).forEach { task ->
141 | if (task.visible)
142 | return task
143 | }
144 | return null
145 | }
146 |
147 | fun Context.registerReceiver(action: String, onReceive: BroadcastReceiver.(Context, Intent) -> Unit) {
148 | registerReceiver(object : BroadcastReceiver() {
149 | override fun onReceive(context: Context, intent: Intent) {
150 | onReceive(this, context, intent)
151 | }
152 | }, android.content.IntentFilter(action), Context.RECEIVER_EXPORTED)
153 | }
154 |
155 |
156 | val ActivityInfo.componentName: ComponentName
157 | get() = ComponentName(packageName, name)
158 |
159 | fun IPackageManagerHidden.getActivityInfoCompat(className: ComponentName, flags: Int, userId: Int): ActivityInfo =
160 | getActivityInfo(className, flags.toLong(), userId)
161 |
162 | fun vibratePhone(context: Context) {
163 | val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
164 | vibrator.vibrate(VibrationEffect.createOneShot(25, VibrationEffect.DEFAULT_AMPLITUDE))
165 | }
166 |
167 | fun animateResize(
168 | view: View,
169 | startWidth: Int,
170 | endWidth: Int,
171 | startHeight: Int,
172 | endHeight: Int,
173 | context: Context,
174 | baseDuration: Long = 300L,
175 | onEnd: (() -> Unit)? = null
176 | ) {
177 | val scale = try {
178 | Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE)
179 | } catch (e: Settings.SettingNotFoundException) {
180 | 1.0f // fallback to normal scale if not found
181 | }
182 |
183 | val adjustedDuration = (baseDuration * scale).toLong()
184 |
185 | val widthAnimator = ValueAnimator.ofInt(startWidth, endWidth).apply {
186 | addUpdateListener { animator ->
187 | val value = animator.animatedValue as Int
188 | val params = view.layoutParams
189 | params.width = value
190 | view.layoutParams = params
191 | }
192 | }
193 |
194 | val heightAnimator = ValueAnimator.ofInt(startHeight, endHeight).apply {
195 | addUpdateListener { animator ->
196 | val value = animator.animatedValue as Int
197 | val params = view.layoutParams
198 | params.height = value
199 | view.layoutParams = params
200 | }
201 | }
202 |
203 | AnimatorSet().apply {
204 | playTogether(widthAnimator, heightAnimator)
205 | duration = adjustedDuration
206 | interpolator = AccelerateDecelerateInterpolator()
207 | addListener(object : AnimatorListenerAdapter() {
208 | override fun onAnimationEnd(animation: Animator) {
209 | onEnd?.invoke()
210 | }
211 | })
212 | start()
213 | }
214 | }
215 |
216 | fun animateScaleThenResize(
217 | view: View,
218 | startX: Float,
219 | startY: Float,
220 | endX: Float,
221 | endY: Float,
222 | pivotX: Float,
223 | pivotY: Float,
224 | endWidth: Int,
225 | endHeight: Int,
226 | context: Context,
227 | baseDuration: Long = 300L,
228 | onEnd: (() -> Unit)? = null
229 | ) {
230 | val scale = try {
231 | Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE)
232 | } catch (e: Settings.SettingNotFoundException) {
233 | 1.0f
234 | }
235 |
236 | val adjustedDuration = (baseDuration * scale).toLong()
237 |
238 | val scaleAnimation = ScaleAnimation(
239 | startX, endX,
240 | startY, endY,
241 | Animation.RELATIVE_TO_SELF, pivotX,
242 | Animation.RELATIVE_TO_SELF, pivotY
243 | ).apply {
244 | duration = adjustedDuration
245 | fillAfter = false
246 | interpolator = AccelerateDecelerateInterpolator()
247 | setAnimationListener(object : Animation.AnimationListener {
248 | override fun onAnimationStart(animation: Animation?) {}
249 |
250 | override fun onAnimationEnd(animation: Animation?) {
251 | val params = view.layoutParams
252 | params.width = endWidth
253 | params.height = endHeight
254 | view.layoutParams = params
255 | onEnd?.invoke()
256 | }
257 |
258 | override fun onAnimationRepeat(animation: Animation?) {}
259 | })
260 | }
261 |
262 | view.startAnimation(scaleAnimation)
263 | }
264 |
265 |
266 | fun animateAlpha(view: View, startAlpha: Float, endAlpha: Float, onEnd: (() -> Unit)? = null) {
267 | if (endAlpha == 1F) view.visibility = View.VISIBLE
268 | val animation1 = AlphaAnimation(startAlpha, endAlpha)
269 | animation1.duration = 300
270 |
271 | animation1.setAnimationListener(object : Animation.AnimationListener {
272 | override fun onAnimationStart(animation: Animation?) {}
273 |
274 | override fun onAnimationEnd(animation: Animation?) {
275 | onEnd?.invoke()
276 | }
277 |
278 | override fun onAnimationRepeat(animation: Animation?) {}
279 | })
280 |
281 | view.startAnimation(animation1)
282 | if (endAlpha == 1F) view.visibility = View.VISIBLE else view.visibility = View.GONE
283 | }
284 |
285 | val byteBuddyStrategy = AndroidClassLoadingStrategy.Wrapping(File("/data/system/reYAMF").also { it.mkdirs() })
286 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qauxv/ui/CommonContextWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * QAuxiliary - An Xposed module for QQ/TIM
3 | * Copyright (C) 2019-2022 qwq233@qwq2333.top
4 | * https://github.com/cinit/QAuxiliary
5 | *
6 | * This software is non-free but opensource software: you can redistribute it
7 | * and/or modify it under the terms of the GNU Affero General Public License
8 | * as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version and our eula as published
10 | * by QAuxiliary contributors.
11 | *
12 | * This software is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * and eula along with this software. If not, see
19 | *
20 | * .
21 | */
22 |
23 | package com.qauxv.ui;
24 |
25 | import android.annotation.SuppressLint;
26 | import android.content.Context;
27 | import android.content.res.Configuration;
28 | import android.content.res.Resources;
29 | import android.content.res.TypedArray;
30 | import android.view.ContextThemeWrapper;
31 |
32 | import androidx.annotation.NonNull;
33 | import androidx.annotation.Nullable;
34 | import androidx.appcompat.app.AppCompatActivity;
35 |
36 | import com.github.kyuubiran.ezxhelper.init.EzXHelperInit;
37 | import com.mja.reyamf.R;
38 | import com.qauxv.util.SavedInstanceStatePatchedClassReferencer;
39 |
40 | import java.util.Objects;
41 |
42 | /**
43 | * If you just want to create a MaterialDialog or AppCompatDialog, see {@link #createMaterialDesignContext(Context)} and
44 | * {@link #createAppCompatContext(Context)}
45 | **/
46 | public class CommonContextWrapper extends ContextThemeWrapper {
47 |
48 | /**
49 | * Creates a new context wrapper with the specified theme with correct module ClassLoader.
50 | *
51 | * @param base the base context
52 | * @param theme the resource ID of the theme to be applied on top of the base context's theme
53 | */
54 | public CommonContextWrapper(@NonNull Context base, int theme) {
55 | this(base, theme, null);
56 | }
57 |
58 | /**
59 | * Creates a new context wrapper with the specified theme with correct module ClassLoader.
60 | *
61 | * @param base the base context
62 | * @param theme the resource ID of the theme to be applied on top of the base context's theme
63 | * @param configuration the configuration to override the base one
64 | */
65 | public CommonContextWrapper(@NonNull Context base, int theme,
66 | @Nullable Configuration configuration) {
67 | super(base, theme);
68 | if (configuration != null) {
69 | mOverrideResources = base.createConfigurationContext(configuration).getResources();
70 | }
71 | EzXHelperInit.INSTANCE.addModuleAssetPath(getResources());
72 | }
73 |
74 | private ClassLoader mXref = null;
75 | private Resources mOverrideResources;
76 |
77 | @NonNull
78 | @Override
79 | public ClassLoader getClassLoader() {
80 | if (mXref == null) {
81 | mXref = new SavedInstanceStatePatchedClassReferencer(
82 | CommonContextWrapper.class.getClassLoader());
83 | }
84 | return mXref;
85 | }
86 |
87 | @Nullable
88 | private static Configuration recreateNighModeConfig(@NonNull Context base, int uiNightMode) {
89 | Objects.requireNonNull(base, "base is null");
90 | Configuration baseConfig = base.getResources().getConfiguration();
91 | if ((baseConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == uiNightMode) {
92 | // config for base context is already what we want,
93 | // just return null to avoid unnecessary override
94 | return null;
95 | }
96 | Configuration conf = new Configuration();
97 | conf.uiMode = uiNightMode | (baseConfig.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
98 | return conf;
99 | }
100 |
101 | @NonNull
102 | @Override
103 | public Resources getResources() {
104 | if (mOverrideResources == null) {
105 | return super.getResources();
106 | } else {
107 | return mOverrideResources;
108 | }
109 | }
110 |
111 | public static boolean isAppCompatContext(@NonNull Context context) {
112 | if (!checkContextClassLoader(context)) {
113 | return false;
114 | }
115 | TypedArray a = context.obtainStyledAttributes(androidx.appcompat.R.styleable.AppCompatTheme);
116 | try {
117 | return a.hasValue(androidx.appcompat.R.styleable.AppCompatTheme_windowActionBar);
118 | } finally {
119 | a.recycle();
120 | }
121 | }
122 |
123 | private static final int[] MATERIAL_CHECK_ATTRS = {com.google.android.material.R.attr.colorPrimaryVariant};
124 |
125 | public static boolean isMaterialDesignContext(@NonNull Context context) {
126 | if (!isAppCompatContext(context)) {
127 | return false;
128 | }
129 | @SuppressLint("ResourceType") TypedArray a = context.obtainStyledAttributes(MATERIAL_CHECK_ATTRS);
130 | try {
131 | return a.hasValue(0);
132 | } finally {
133 | a.recycle();
134 | }
135 | }
136 |
137 | public static boolean checkContextClassLoader(@NonNull Context context) {
138 | try {
139 | ClassLoader cl = context.getClassLoader();
140 | if (cl == null) {
141 | return false;
142 | }
143 | return cl.loadClass(AppCompatActivity.class.getName()) == AppCompatActivity.class;
144 | } catch (ClassNotFoundException e) {
145 | return false;
146 | }
147 | }
148 |
149 | @NonNull
150 | public static Context createAppCompatContext(@NonNull Context base) {
151 | if (isAppCompatContext(base)) {
152 | return base;
153 | }
154 | return new CommonContextWrapper(base, R.style.Base_Theme_Reyamf,
155 | recreateNighModeConfig(base, base.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK));
156 | }
157 |
158 | @NonNull
159 | public static Context createMaterialDesignContext(@NonNull Context base) {
160 | if (isMaterialDesignContext(base)) {
161 | return base;
162 | }
163 | // currently all themes by createAppCompatContext are material themes
164 | // change this if you have a AppCompat theme that is not material theme
165 | return createAppCompatContext(base);
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qauxv/util/Initiator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * QAuxiliary - An Xposed module for QQ/TIM
3 | * Copyright (C) 2019-2022 qwq233@qwq2333.top
4 | * https://github.com/cinit/QAuxiliary
5 | *
6 | * This software is non-free but opensource software: you can redistribute it
7 | * and/or modify it under the terms of the GNU Affero General Public License
8 | * as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version and our eula as published
10 | * by QAuxiliary contributors.
11 | *
12 | * This software is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * and eula along with this software. If not, see
19 | *
20 | * .
21 | */
22 | package com.qauxv.util;
23 |
24 | public class Initiator {
25 | private static ClassLoader sHostClassLoader;
26 |
27 | private Initiator() {
28 | throw new AssertionError("No instance for you!");
29 | }
30 |
31 | public static void init(ClassLoader classLoader) {
32 | sHostClassLoader = classLoader;
33 | }
34 |
35 | public static ClassLoader getPluginClassLoader() {
36 | return Initiator.class.getClassLoader();
37 | }
38 |
39 | public static ClassLoader getHostClassLoader() {
40 | return sHostClassLoader;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qauxv/util/SavedInstanceStatePatchedClassReferencer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * QAuxiliary - An Xposed module for QQ/TIM
3 | * Copyright (C) 2019-2022 qwq233@qwq2333.top
4 | * https://github.com/cinit/QAuxiliary
5 | *
6 | * This software is non-free but opensource software: you can redistribute it
7 | * and/or modify it under the terms of the GNU Affero General Public License
8 | * as published by the Free Software Foundation; either
9 | * version 3 of the License, or any later version and our eula as published
10 | * by QAuxiliary contributors.
11 | *
12 | * This software is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * and eula along with this software. If not, see
19 | *
20 | * .
21 | */
22 |
23 | package com.qauxv.util;
24 |
25 | import android.content.Context;
26 |
27 | import java.util.Objects;
28 |
29 | public class SavedInstanceStatePatchedClassReferencer extends ClassLoader {
30 |
31 | private static final ClassLoader mBootstrap = Context.class.getClassLoader();
32 | private final ClassLoader mBaseReferencer;
33 | private final ClassLoader mHostReferencer;
34 |
35 | public SavedInstanceStatePatchedClassReferencer(ClassLoader referencer) {
36 | super(mBootstrap);
37 | mBaseReferencer = Objects.requireNonNull(referencer);
38 | mHostReferencer = Initiator.getHostClassLoader();
39 | }
40 |
41 | @Override
42 | protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
43 | try {
44 | return mBootstrap.loadClass(name);
45 | } catch (ClassNotFoundException ignored) {}
46 | if (mHostReferencer != null) {
47 | try {
48 | //start: overloaded
49 | if ("androidx.lifecycle.ReportFragment".equals(name)) {
50 | return mHostReferencer.loadClass(name);
51 | }
52 | } catch (ClassNotFoundException ignored) {}
53 | }
54 | //with ClassNotFoundException
55 | return mBaseReferencer.loadClass(name);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/a_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bar_corners_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_apps_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_keyboard_double_arrow_left_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/baseline_restart_alt_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/drawable/demo.gif
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_close_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_error_outline_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_maximize.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_minimize.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_picture_in_picture_alt_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_round_check_circle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning_amber_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/menu_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/three_dot_horiz.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/work_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-land/sidebar_itemview.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_app.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sidebar_itemview.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sidebar_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
26 |
27 |
36 |
37 |
46 |
47 |
59 |
60 |
70 |
71 |
81 |
82 |
98 |
99 |
111 |
112 |
113 |
114 |
126 |
127 |
128 |
129 |
139 |
140 |
144 |
145 |
153 |
154 |
163 |
164 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/window_app.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
23 |
24 |
32 |
38 |
39 |
40 |
50 |
51 |
58 |
59 |
66 |
67 |
75 |
76 |
86 |
87 |
98 |
99 |
111 |
112 |
122 |
123 |
124 |
125 |
135 |
136 |
137 |
138 |
144 |
145 |
155 |
156 |
164 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/window_app_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
32 |
33 |
41 |
42 |
49 |
50 |
55 |
56 |
57 |
68 |
69 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
14 |
18 |
22 |
26 |
31 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #20FFFFFF
4 | #60FFFFFF
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | reYAMF
3 | 详情
4 | 未知错误
5 | 模块已激活
6 | 模块已更新,需要重启
7 | 模块未激活
8 | 现有窗口可以正常使用\n但新窗口可能导致系统崩溃
9 | 重启
10 | 设置
11 | 打开次数
12 | 新建窗口
13 | 打开应用列表
14 | Telegram 频道
15 | 捐赠
16 | 返回
17 | 最小化
18 | 调整窗口大小
19 | 最大化
20 | 关闭
21 | 为类 AOSP 系统提供自由窗口
22 | 系统版本
23 | 自由窗口
24 | 进入窗口
25 | 构建类型
26 | 重置所有窗口
27 | x
28 | 默认窗口大小
29 | 在窗口中显示输入法\n必须启用 VIRTUAL_DISPLAY_FLAG_PUBLIC
30 | 保持 reYAMF 在后台运行
31 | 折叠视图的应用图标
32 | 哇!\n空荡荡~
33 | 启用侧边栏
34 | 开机自启
35 | 注意:
36 | 如果你无法接受任何应用的权限请求, 这是因为侧边栏覆盖了屏幕
37 | 点击侧边栏上的此按钮关闭侧边栏
38 | 或点击此按钮临时关闭侧边栏,侧边栏会在5秒后重新出现
39 | reYAMF
40 | a YAMF fork
41 | 视图类型
42 | DPI 密度
43 | 高级参数
44 | 彩色控制按钮
45 | 启动方式
46 | 最近任务返回主页
47 | 支持在最近任务界面启动小窗
48 | 支持任务栏启动小窗
49 | 支持长按应用启动小窗
50 | 支持临时任务栏启动小窗
51 | 使用应用列表
52 | 强制显示输入法
53 | * 桌面启动器可能需要重启两次才能生效
54 | 将当前应用切换为小窗
55 | 启动侧边栏
56 | DPI 缩减
57 | 侧边栏透明度
58 | 80
59 | 窗口圆角大小
60 | 20
61 | 右置侧边栏
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - android
5 | - com.motorola.launcher3
6 | - com.android.launcher3
7 | - com.google.android.apps.nexuslauncher
8 | - com.google.android.permissioncontroller
9 | - com.android.permissioncontroller
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FBC02D
4 | #FF000000
5 |
6 | //dark theme
7 | #cdcccc
8 | #20000000
9 | #60000000
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0dp
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | reYAMF
3 | Details
4 | Unknown Error
5 | Module Is Activated!
6 | Version change, reboot required
7 | Module is not activated.
8 | Existing windows are fine\nBut new window may make system crash
9 | Reboot
10 | Settings
11 | Open Count
12 | New window
13 | Open app list
14 | Telegram channel
15 | donate
16 | back
17 | minimize
18 | resize window
19 | maximize
20 | close
21 | Freeform window for AOSP-like systems
22 | System version
23 | Freeform
24 | enter window
25 | Build Type
26 | reset all window
27 | x
28 | Default Window Size
29 | Show IME in window\nVIRTUAL_DISPLAY_FLAG_PUBLIC must be true
30 | Keeps reYAMF alive in the background
31 | app icon for collapsed view
32 | Wow! \nSuch empty
33 | Enable Sidebar
34 | Launch at startup
35 | Note :
36 | IF YOU CAN\'T ACCEPT ANY APP PERMISSION REQUEST. That\'s because the sidebar is overlaying the screen.
37 | Close the sidebar using this button on the sidebar
38 | Or use this button to close sidebar for 5 seconds. Sidebar will reappaer automatically
39 | reYAMF
40 | a YAMF fork
41 | View Type
42 | DPI Density
43 | Flags
44 | Colored Controller
45 | Launch Method
46 | Recents Back Home
47 | Recents App Icon Hook
48 | Taskbar Hook
49 | App Long Press Hook
50 | Transient Taskbar Hook
51 | Use App List
52 | Force Show IME
53 | * Launcher might need to be restarted twice for hooks to take effect
54 | Current to window
55 | Launch sidebar
56 | Reduce DPI
57 | Sidebar Transparency
58 | 80
59 | Window Rounded Corner
60 | 20
61 | Sidebar Position
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/accessibility_service_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/com/mja/reyamf/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.mja.reyamf
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | alias(libs.plugins.android.application) apply false
4 | alias(libs.plugins.kotlin.android) apply false
5 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. For more details, visit
12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | activityCompose = "1.9.3"
3 | agp = "8.5.1"
4 | annotation = "1.8.0"
5 | dynamicanimationKtx = "1.0.0-alpha03"
6 | flexbox = "3.0.0"
7 | glide = "4.13.2"
8 | gson = "2.10.1"
9 | lifecycle = "2.8.3"
10 | lifecycleRuntimeKtx = "2.8.7"
11 | materialVersion = "1.7.6"
12 | ui = "1.7.6"
13 | uiToolingPreview = "1.7.6"
14 | xposed = "82"
15 | ezxhelper = "1.0.3"
16 | preferenceKtx = "1.2.1"
17 | rikkaDevTools = "4.4.0"
18 | kotlin = "1.9.23"
19 | coreKtx = "1.13.1"
20 | junit = "4.13.2"
21 | junitVersion = "1.2.1"
22 | espressoCore = "3.6.1"
23 | appcompat = "1.7.0"
24 | material = "1.12.0"
25 | activity = "1.9.0"
26 | constraintlayout = "2.1.4"
27 | rikka-hidden = "4.2.0"
28 | wear = "1.3.0"
29 |
30 | [libraries]
31 | androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
32 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
33 | androidx-dynamicanimation-ktx = { module = "androidx.dynamicanimation:dynamicanimation-ktx", version.ref = "dynamicanimationKtx" }
34 | androidx-lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycle" }
35 | androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
36 | androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preferenceKtx" }
37 | flexbox = { module = "com.google.android.flexbox:flexbox", version.ref = "flexbox" }
38 | glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
39 | gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
40 | xposed-api = { module = "de.robv.android.xposed:api", version.ref = "xposed" }
41 | ezxhelper = { module = "com.github.kyuubiran:EzXHelper", version.ref = "ezxhelper" }
42 | rikka-annotation = { module = "dev.rikka.tools.refine:annotation", version.ref = "rikkaDevTools" }
43 | rikka-annotation-processor = { module = "dev.rikka.tools.refine:annotation-processor", version.ref = "rikkaDevTools" }
44 | junit = { group = "junit", name = "junit", version.ref = "junit" }
45 | androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
46 | androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
47 | androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
48 | material = { group = "com.google.android.material", name = "material", version.ref = "material" }
49 | androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
50 | androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
51 | rikka-hidden-stub = { module = "dev.rikka.hidden:stub", version.ref = "rikka-hidden" }
52 | rikka-hidden-compat = { module = "dev.rikka.hidden:compat", version.ref = "rikka-hidden" }
53 | androidx-wear = { group = "androidx.wear", name = "wear", version.ref = "wear" }
54 | byte-buddy-android = { module = "net.bytebuddy:byte-buddy-android", version = "1.17.5" }
55 |
56 | [plugins]
57 | android-application = { id = "com.android.application", version.ref = "agp" }
58 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
59 | rikka-tools-refine = { id = "dev.rikka.tools.refine", version.ref = "rikkaDevTools" }
60 |
61 |
62 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuanArton/reYAMF/7304df7dbb912f560876e2cdf86b5d8fa22851a0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Jul 14 23:32:50 WIB 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | pluginManagement {
4 | repositories {
5 | google {
6 | content {
7 | includeGroupByRegex("com\\.android.*")
8 | includeGroupByRegex("com\\.google.*")
9 | includeGroupByRegex("androidx.*")
10 | }
11 | }
12 | mavenCentral()
13 | gradlePluginPortal()
14 | }
15 | }
16 | dependencyResolutionManagement {
17 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
18 | repositories {
19 | google()
20 | mavenCentral()
21 | maven("https://jitpack.io")
22 | maven("https://api.xposed.info")
23 | maven("https://mvnrepository.com/artifact")
24 | }
25 | }
26 |
27 | rootProject.name = "reYAMF"
28 | include(":app", ":android-stub")
29 |
--------------------------------------------------------------------------------