├── .gitattributes
├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── compiler.xml
├── gradle.xml
├── jarRepositories.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── adb_process
│ ├── .idea
│ │ ├── artifacts
│ │ │ └── adb_process_jar.xml
│ │ ├── compiler.xml
│ │ ├── description.html
│ │ ├── encodings.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── vcs.xml
│ │ └── workspace.xml
│ ├── help.md
│ ├── jar
│ │ ├── adb_process.dex
│ │ └── adb_process.jar
│ ├── out
│ │ └── production
│ │ │ └── adb_process
│ │ │ └── META-INF
│ │ │ └── MANIFEST.MF
│ ├── src
│ │ ├── META-INF
│ │ │ └── MANIFEST.MF
│ │ ├── Main.java
│ │ └── shell
│ │ │ ├── GlobalState.java
│ │ │ ├── KeepShell.java
│ │ │ ├── KeepShellPublic.java
│ │ │ ├── RemoteAPI.java
│ │ │ ├── ScreenColor.java
│ │ │ └── ShellExecutor.java
│ └── steps.txt
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── omarea
│ │ └── gesture
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── adb_process.dex
│ │ └── up.sh
│ ├── java
│ │ └── com
│ │ │ └── omarea
│ │ │ └── gesture
│ │ │ ├── AccessibilityServiceGesture.java
│ │ │ ├── ActionModel.java
│ │ │ ├── AdbProcessExtractor.java
│ │ │ ├── AppSwitchActivity.java
│ │ │ ├── BatteryReceiver.java
│ │ │ ├── DialogAppSwitchExclusive.java
│ │ │ ├── DialogFrequentlyAppEdit.java
│ │ │ ├── DialogHandlerEX.java
│ │ │ ├── EnhancedModeGuide.java
│ │ │ ├── FixAppSwitchDelay.java
│ │ │ ├── Gesture.java
│ │ │ ├── SettingsActivity.java
│ │ │ ├── SpfConfig.java
│ │ │ ├── SpfConfigEx.java
│ │ │ ├── StartActivity.java
│ │ │ ├── WhiteBarColor.java
│ │ │ ├── fragments
│ │ │ ├── Fragment3Section.java
│ │ │ ├── FragmentBasic.java
│ │ │ ├── FragmentOther.java
│ │ │ ├── FragmentSettingsBase.java
│ │ │ ├── FragmentSimple.java
│ │ │ └── FragmentWhiteBar.java
│ │ │ ├── remote
│ │ │ └── RemoteAPI.java
│ │ │ ├── shell
│ │ │ ├── KeepShell.java
│ │ │ ├── KeepShellPublic.java
│ │ │ └── ShellExecutor.java
│ │ │ ├── ui
│ │ │ ├── QuickPanel.java
│ │ │ ├── ReTouchHelper.java
│ │ │ ├── SideGestureBar.java
│ │ │ ├── ThreeSectionView.java
│ │ │ ├── TouchBarView.java
│ │ │ ├── TouchIconCache.java
│ │ │ ├── VisualFeedbackView.java
│ │ │ ├── iOSTouchBarView.java
│ │ │ └── iOSWhiteBar.java
│ │ │ └── util
│ │ │ ├── AppInfo.java
│ │ │ ├── AppLauncher.java
│ │ │ ├── AppListHelper.java
│ │ │ ├── AppWindowed.java
│ │ │ ├── BatteryUtils.java
│ │ │ ├── GlobalState.java
│ │ │ ├── Handlers.java
│ │ │ ├── Memory.java
│ │ │ ├── ReceiverLock.java
│ │ │ ├── ReceiverLockHandler.java
│ │ │ ├── Recents.java
│ │ │ ├── ResumeNavBar.java
│ │ │ ├── ScreenState.java
│ │ │ ├── SystemProperty.java
│ │ │ └── UITools.java
│ └── res
│ │ ├── anim
│ │ ├── gesture_app_exit.xml
│ │ ├── gesture_app_exit_2.xml
│ │ ├── gesture_app_open_enter.xml
│ │ ├── gesture_app_open_exit.xml
│ │ ├── gesture_back_home.xml
│ │ ├── gesture_back_home_2.xml
│ │ ├── gesture_next_enter.xml
│ │ ├── gesture_next_enter_2.xml
│ │ ├── gesture_next_enter_basic.xml
│ │ ├── gesture_next_enter_fast.xml
│ │ ├── gesture_next_exit.xml
│ │ ├── gesture_next_exit_2.xml
│ │ ├── gesture_next_exit_basic.xml
│ │ ├── gesture_next_exit_fast.xml
│ │ ├── gesture_prev_enter.xml
│ │ ├── gesture_prev_enter_2.xml
│ │ ├── gesture_prev_enter_basic.xml
│ │ ├── gesture_prev_enter_fast.xml
│ │ ├── gesture_prev_exit.xml
│ │ ├── gesture_prev_exit_2.xml
│ │ ├── gesture_prev_exit_basic.xml
│ │ ├── gesture_prev_exit_fast.xml
│ │ ├── gesture_quick_panel_bottom_in.xml
│ │ ├── gesture_quick_panel_bottom_out.xml
│ │ ├── gesture_quick_panel_left_in.xml
│ │ ├── gesture_quick_panel_left_out.xml
│ │ ├── gesture_quick_panel_right_in.xml
│ │ └── gesture_quick_panel_right_out.xml
│ │ ├── drawable
│ │ ├── adb_off.png
│ │ ├── adb_on.png
│ │ ├── bar_background.xml
│ │ ├── color_picker_alpha_gradient.xml
│ │ ├── color_picker_bg_gradient.xml
│ │ ├── color_picker_blue_gradient.xml
│ │ ├── color_picker_green_gradient.xml
│ │ ├── color_picker_red_gradient.xml
│ │ ├── color_picker_seekbar_thumb.xml
│ │ ├── frequently_edit_bg.xml
│ │ ├── gesture_card_view.xml
│ │ ├── gesture_card_view_bottom.xml
│ │ ├── gesture_card_view_top.xml
│ │ ├── gesture_copy.png
│ │ ├── gesture_icon_add.png
│ │ ├── gesture_icon_edit.png
│ │ ├── gesture_icon_ok.png
│ │ ├── gesture_logo.png
│ │ ├── gesture_quick_question.png
│ │ ├── gesture_tab_apple.png
│ │ ├── gesture_tab_edge.png
│ │ ├── gesture_tab_lab.png
│ │ ├── gesture_tab_settings.png
│ │ ├── gesture_tab_switch.png
│ │ ├── icon_question.png
│ │ ├── landscape_bar_background.xml
│ │ ├── power_switch_off.xml
│ │ ├── power_switch_on.xml
│ │ ├── power_switch_style.xml
│ │ ├── quick_panel_bg.xml
│ │ ├── quick_panel_bg_bottom.xml
│ │ ├── quick_panel_bg_left.xml
│ │ ├── quick_panel_bg_right.xml
│ │ ├── seekbar_progress_drawable.xml
│ │ ├── seekbar_thumb.xml
│ │ ├── switch_thumb.xml
│ │ ├── switch_track.xml
│ │ ├── switch_track_close.xml
│ │ ├── switch_track_open.xml
│ │ ├── thumb.xml
│ │ ├── touch_app.png
│ │ ├── touch_app_window.png
│ │ ├── touch_arrow_left.png
│ │ ├── touch_arrow_right.png
│ │ ├── touch_grid.png
│ │ ├── touch_home.png
│ │ ├── touch_info.png
│ │ ├── touch_jump_next.png
│ │ ├── touch_jump_previous.png
│ │ ├── touch_lock.png
│ │ ├── touch_notice.png
│ │ ├── touch_power.png
│ │ ├── touch_screenshot.png
│ │ ├── touch_settings.png
│ │ ├── touch_shell.png
│ │ ├── touch_split.png
│ │ ├── touch_switch.png
│ │ ├── touch_tasks.png
│ │ └── touch_window.png
│ │ ├── layout
│ │ ├── enhanced_mode.xml
│ │ ├── gesture_color_picker.xml
│ │ ├── gesture_fw_ios_touch_bar.xml
│ │ ├── gesture_fw_three_section.xml
│ │ ├── gesture_fw_vitual_touch_bar.xml
│ │ ├── gesture_layout_action_option.xml
│ │ ├── gesture_layout_app_option.xml
│ │ ├── gesture_layout_app_option2.xml
│ │ ├── gesture_layout_ex_shell.xml
│ │ ├── gesture_layout_quick_panel_item.xml
│ │ ├── gesture_settings.xml
│ │ ├── gesture_settings_3section.xml
│ │ ├── gesture_settings_basic.xml
│ │ ├── gesture_settings_other.xml
│ │ ├── gesture_settings_simple.xml
│ │ ├── gesture_settings_white_bar.xml
│ │ ├── gesture_switch_options.xml
│ │ ├── layout_enhanced_mode_guide.xml
│ │ ├── layout_frequently_app_edit.xml
│ │ ├── layout_quick_panel.xml
│ │ ├── layout_quick_panel_add.xml
│ │ └── layout_quick_panel_landscape.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── config.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ ├── xml-v24
│ │ └── keyevent_accessibility.xml
│ │ └── xml
│ │ └── keyevent_accessibility.xml
│ └── test
│ └── java
│ └── com
│ └── omarea
│ └── gesture
│ └── ExampleUnitTest.java
├── build.gradle
├── color-polling-apps.txt
├── docs
├── EnhancedMode.md
├── FAQ.md
├── adb_shell.jpg
├── dev-settings.jpg
├── dev-settings2.jpg
├── shell_window.jpg
└── success.jpg
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── updateLog.log
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | app/release_mini/*
10 | app/release/*
11 | .externalNativeBuild
12 | *.class
13 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | xmlns:android
32 |
33 | ^$
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | xmlns:.*
43 |
44 | ^$
45 |
46 |
47 | BY_NAME
48 |
49 |
50 |
51 |
52 |
53 |
54 | .*:id
55 |
56 | http://schemas.android.com/apk/res/android
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | .*:name
66 |
67 | http://schemas.android.com/apk/res/android
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | name
77 |
78 | ^$
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | style
88 |
89 | ^$
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | .*
99 |
100 | ^$
101 |
102 |
103 | BY_NAME
104 |
105 |
106 |
107 |
108 |
109 |
110 | .*
111 |
112 | http://schemas.android.com/apk/res/android
113 |
114 |
115 | ANDROID_ATTRIBUTE_ORDER
116 |
117 |
118 |
119 |
120 |
121 |
122 | .*
123 |
124 | .*
125 |
126 |
127 | BY_NAME
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.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 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.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 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 【1.2.0】
2 | - 增加横竖屏使用小白条的开关,以及动作和外观自定义选项
3 | - emmm,越来越臃肿了~
4 |
5 | 【1.1.10】
6 | - 增加横屏时手势区域更换成小白条选项
7 |
8 | 【1.1.9】
9 | - 横屏时缩小底部手势区域降低游戏误触几率
10 |
11 | 【1.1.8】
12 | - 增加三星OneUI独有的优化提示
13 |
14 | 【1.1.7 更新日志】
15 | - 修复了发现的问题
16 | 【1.1.6更新日志】
17 |
18 | - 大幅(35%~90%)降低内存占用
19 |
20 |
21 |
22 | 【1.1.5更新日志】
23 |
24 | - 震动反馈调节加入,根据自己的喜好调节震动强度,把马达耍起来吧!
25 |
26 |
27 |
28 | 【1.1.4 更新日志】
29 |
30 | - 修复 底部热区高度调为0会遮挡全屏的问题
31 |
32 | - 修复 手势动作设置项错位
33 |
34 | - 增加悬停手势触发时长选项
35 |
36 |
37 |
38 | 【1.1.3 更新日志】
39 |
40 | - 诈尸的一天,增加热区灵敏度
41 |
42 | - 允许调整底部热区宽度
43 |
44 | - 进入设置界面时热区高亮显示
45 |
46 |
47 |
48 | 【1.1.2 更新日志】
49 |
50 | - 修复了一些动画细节问题。emmm,似乎对于一款追求轻量的软件来说,差不多可以结束更新了,如果没有重大bug出现的话
51 |
52 |
53 |
54 | 【1.1.0 更新日志】
55 |
56 | - 终于开始做自定义选项了,时间仓促 界面和细节略粗糙,见谅~
57 |
58 | - 为了方便部分用户锁定后台,改为默认显示桌面图标
59 |
60 |
61 |
62 |
63 |
64 | 【1.0.6 极致精简版 更新日志】
65 |
66 | - 修复在部分设备上偶现的底部手势热区变大
67 |
68 | - 优化悬停手势震动反馈
69 |
70 |
71 |
72 | 【1.0.5 更新日志】
73 |
74 | - 修复在5.0系统上启动失败
75 |
76 |
77 |
78 | 【1.0.4 更新日志】
79 |
80 | - 大幅压缩软件体积
81 |
82 |
83 |
84 | 【1.0.3 更新日志】
85 |
86 | - 为了方便大家锁定后台,增加一个切换启动图标的选项(默认还是不显示启动图标,从辅助服务界面的设置进去,不懂的可以看截图)
87 |
88 |
89 |
90 | 【1.0.2 更新日志】
91 |
92 | - 修复手势动画顶部被截断的问题
93 |
94 |
95 |
96 | 【1.0.1 更新日志】
97 |
98 | - 降低系统版本要求到 Android 5.0
99 |
100 | - 优化手势震动为 仅滑动悬停才震动
101 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /app/release
3 | /app/release/*
--------------------------------------------------------------------------------
/app/adb_process/.idea/artifacts/adb_process_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/jar
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/adb_process/.idea/compiler.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 |
--------------------------------------------------------------------------------
/app/adb_process/.idea/description.html:
--------------------------------------------------------------------------------
1 | Simple Java application that includes a class with main()
method
--------------------------------------------------------------------------------
/app/adb_process/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/adb_process/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/adb_process/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/adb_process/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/adb_process/help.md:
--------------------------------------------------------------------------------
1 | Demo:https://github.com/zgj224/Android-Demo/tree/master/app_process_exec_java_demo
2 | 栗子:
3 | # am start -n com.android.browser/com.android.browser.BrowserActivity
4 | 这里的am命令是一个可执行文件,查看系统am可以发现其实里面调用的是app_process
5 | # adb root
6 | # adb shell cat /system/bin/am
7 |
8 | #!/system/bin/sh
9 | base=/system
10 | export CLASSPATH=$base/framework/am.jar
11 | exec app_process $base/bin com.android.commands.am.Am "$@"
12 |
13 |
14 | 1.执行jar包里的java可执行文件
15 | 使用app_process启动java文件,其中java里必须有main()方法,这是函数入口。
16 | # adb shell CLASSPATH=/system/framework/Demo.jar exec app_process /system/bin com.example.Demo
17 |
18 | 或在apk里启动一个可执行com.example.helloworld.Console里的main()
19 | # adb shell CLASSPATH=/data/app/com.example.helloworld-1.apk exec app_process /system/bin com.example.helloworld.Console
20 | 注意:/system/bin这个目录可以替换为任意目录
21 |
22 | 2.执行java文件
23 | <1>.Hello.java
24 | public static class Hello {
25 | public void main(String args[]){
26 | System.out.println("Hello Android");
27 | }
28 | }
29 |
30 | <2>.编译
31 | # javac Hello.java
32 | 编译出Hello.class文件可以在普通的jvm上运行,要放到android下还需要转换成dex,需要用android sdk中的dx工具进行转换
33 | > 如果出现“错误: 编码GBK的不可映射字符”提示,可使用 `javac Hello.java -encoding UTF-8` 命令编译
34 |
35 | # cd SDK/build-tools //SDK为自己下载的android sdk(例如C:\Users\用户名\AppData\Local\Android\Sdk\build-tools\29.0.2)
36 | # dx --dex --output=Hello.dex Hello.class
37 | 得到Hello.dex
38 |
39 | <3>.Hello.dex push到/sdcard
40 | # adb push Hello.dex /sdcard
41 |
42 | <4>.使用app_process 运行hello.dex
43 | # app_process -Djava.class.path=/sdcard/Hello.dex /sdcard Hello
44 | ————————————————
45 | 版权声明:本文为CSDN博主「慢慢的燃烧」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
46 | 原文链接:https://blog.csdn.net/u010164190/article/details/81335727
--------------------------------------------------------------------------------
/app/adb_process/jar/adb_process.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/adb_process/jar/adb_process.dex
--------------------------------------------------------------------------------
/app/adb_process/jar/adb_process.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/adb_process/jar/adb_process.jar
--------------------------------------------------------------------------------
/app/adb_process/out/production/adb_process/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: Main
3 |
4 |
--------------------------------------------------------------------------------
/app/adb_process/src/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: Main
3 |
4 |
--------------------------------------------------------------------------------
/app/adb_process/src/Main.java:
--------------------------------------------------------------------------------
1 | import shell.RemoteAPI;
2 |
3 | public class Main {
4 | static final Object lock = new Object();
5 |
6 | public static void main(String[] args) {
7 | /*
8 | try {
9 | new ScreenColor().autoBarColor();
10 | // System.out.println(KeepShellPublic.doCmdSync("dumpsys activity r | grep mActivityComponent | cut -f2 -d '=' | cut -f1 -d '/'"));
11 | // System.out.println(KeepShellPublic.doCmdSync("screencap > /sdcard/screen"));
12 | } catch (Exception ex) {
13 | System.out.println("错误!" + ex.getMessage());
14 | }
15 |
16 | if (KeepShellPublic.doCmdSync("pm list packages com.omarea.gesture").contains("com.omarea.gesture")) {
17 | new Thread(new Runnable() {
18 | @Override
19 | public void run() {
20 | try {
21 | wait(2000);
22 | } catch (Exception ignored) {
23 | }
24 | KeepShellPublic.doCmdSync("am broadcast -a com.omarea.gesture.ConfigChanged");
25 | }
26 | }).start();
27 | }
28 | */
29 |
30 | // System.out.println("Gesture ADB Process!");
31 |
32 | RemoteAPI remoteAPI = new RemoteAPI();
33 | remoteAPI.start();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/adb_process/src/shell/GlobalState.java:
--------------------------------------------------------------------------------
1 | package shell;
2 |
3 | public class GlobalState {
4 | public static int displayHeight = 2340;
5 | public static int displayWidth = 1080;
6 | public static int lastBarColor = Integer.MIN_VALUE;
7 | public static boolean onBarColorGeting = false;
8 | }
--------------------------------------------------------------------------------
/app/adb_process/src/shell/KeepShell.java:
--------------------------------------------------------------------------------
1 | package shell;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.io.OutputStream;
6 | import java.nio.charset.Charset;
7 | import java.util.UUID;
8 | import java.util.concurrent.locks.ReentrantLock;
9 |
10 | /**
11 | * Created by Hello on 2018/01/23.
12 | */
13 | public class KeepShell {
14 | private Process p = null;
15 | private OutputStream out = null;
16 | private BufferedReader reader = null;
17 | private ReentrantLock mLock = new ReentrantLock();
18 | private long LOCK_TIMEOUT = 10000L;
19 | private long enterLockTime = 0L;
20 | private byte[] br = "\n\n".getBytes(Charset.defaultCharset());
21 |
22 | public KeepShell() {
23 | }
24 |
25 | //尝试退出命令行程序
26 | public void tryExit() {
27 | try {
28 | if (out != null)
29 | out.close();
30 | if (reader != null)
31 | reader.close();
32 | } catch (Exception ex) {
33 | }
34 | try {
35 | p.destroy();
36 | } catch (Exception ex) {
37 | }
38 | enterLockTime = 0L;
39 | out = null;
40 | reader = null;
41 | p = null;
42 | }
43 |
44 | private void getRuntimeShell() {
45 | if (p != null)
46 | return;
47 | Thread getSu = new Thread(new Runnable() {
48 | @Override
49 | public void run() {
50 | try {
51 | mLock.lockInterruptibly();
52 | enterLockTime = System.currentTimeMillis();
53 | p = ShellExecutor.getRuntime();
54 | out = p.getOutputStream();
55 | reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
56 | new Thread(new Runnable() {
57 | @Override
58 | public void run() {
59 | try {
60 | BufferedReader errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
61 | while (true) {
62 | errorReader.readLine();
63 | }
64 | } catch (Exception ex) {
65 | // System.out.println("Gesture ADB Error " + ex.getMessage());
66 | }
67 | }
68 | }).start();
69 | } catch (Exception ex) {
70 | } finally {
71 | enterLockTime = 0L;
72 | mLock.unlock();
73 | }
74 | }
75 | });
76 | getSu.start();
77 | try {
78 | getSu.join(10000);
79 | } catch (InterruptedException e) {
80 | e.printStackTrace();
81 | }
82 | if (p == null && getSu.getState() != Thread.State.TERMINATED) {
83 | enterLockTime = 0L;
84 | getSu.interrupt();
85 | }
86 | }
87 |
88 | //执行脚本
89 | public String doCmdSync(String cmd) {
90 | if (mLock.isLocked() && enterLockTime > 0 && System.currentTimeMillis() - enterLockTime > LOCK_TIMEOUT) {
91 | tryExit();
92 | }
93 | CharSequence uuid = UUID.randomUUID().toString().subSequence(0, 8);
94 | getRuntimeShell();
95 | if (out != null) {
96 | String startTag = "--start--" + uuid + "--";
97 | String endTag = "--end--" + uuid + "--";
98 | // Log.e("shell-lock", cmd)
99 | try {
100 | try {
101 | mLock.lockInterruptibly();
102 | } catch (InterruptedException e) {
103 | e.printStackTrace();
104 | return "error";
105 | }
106 |
107 | OutputStream out = p.getOutputStream();
108 | if (out != null) {
109 | try {
110 | out.write(br);
111 | out.write(("echo '" + startTag + "'").getBytes(Charset.defaultCharset()));
112 | out.write(br);
113 | out.write(cmd.getBytes(Charset.defaultCharset()));
114 | out.write(br);
115 | out.write("echo \"\"".getBytes(Charset.defaultCharset()));
116 | out.write(br);
117 | out.write(("echo '" + endTag + "'").getBytes(Charset.defaultCharset()));
118 | out.write(br);
119 | out.flush();
120 | } catch (Exception ex) {
121 | }
122 |
123 | StringBuilder results = new StringBuilder();
124 | boolean unstart = true;
125 | while (reader != null) {
126 | String line = reader.readLine();
127 | if (line == null || line.contains("--end--")) {
128 | break;
129 | } else if (line.equals(startTag)) {
130 | unstart = false;
131 | } else if (!unstart) {
132 | results.append(line);
133 | results.append("\n");
134 | }
135 | }
136 | // Log.e("shell-unlock", cmd)
137 | // Log.d("Shell", cmd.toString() + "\n" + "Result:"+results.toString().trim())
138 | return results.toString().trim();
139 | } else {
140 | return "error";
141 | }
142 | } catch (Exception e) {
143 | tryExit();
144 | return "error";
145 | } finally {
146 | enterLockTime = 0L;
147 | mLock.unlock();
148 | }
149 | } else {
150 | tryExit();
151 | return "error";
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/app/adb_process/src/shell/KeepShellPublic.java:
--------------------------------------------------------------------------------
1 | package shell;
2 |
3 | /**
4 | * Created by Hello on 2018/01/23.
5 | */
6 | public class KeepShellPublic {
7 | private static KeepShell keepShell = null;
8 |
9 | //执行脚本
10 | public static String doCmdSync(String cmd) {
11 | if (keepShell == null) {
12 | keepShell = new KeepShell();
13 | }
14 | return keepShell.doCmdSync(cmd);
15 | }
16 |
17 | public static void tryExit() {
18 | if (keepShell != null) {
19 | keepShell.tryExit();
20 | keepShell = null;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/adb_process/src/shell/ShellExecutor.java:
--------------------------------------------------------------------------------
1 | package shell;
2 |
3 | import java.io.IOException;
4 |
5 | public class ShellExecutor {
6 | private static Process getProcess(String run) throws IOException {
7 | Runtime runtime = Runtime.getRuntime();
8 | return runtime.exec(run);
9 | }
10 |
11 | public static Process getRuntime() throws IOException {
12 | return getProcess("sh");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/adb_process/steps.txt:
--------------------------------------------------------------------------------
1 | C:\Users\helloklf\AppData\Local\Android\Sdk\build-tools\28.0.3\dx --dex --output=./jar/adb_process.dex ./jar/adb_process.jar
2 |
3 | adb push ./jar/adb_process.dex /sdcard/adb_process.dex
4 |
5 | adb shell dalvikvm -cp /sdcard/adb_process.dex Main || app_process -Djava.class.path=/sdcard/adb_process.dex /sdcard Main
6 |
7 |
8 | # 直接启动jar也是可以的,但是dalvikvm也可以启动dex文件
9 | adb push ./jar/adb_process.dex /sdcard/adb_process.jar
10 | adb shell dalvikvm -cp /sdcard/adb_process.jar Main
11 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | signingConfigs {
6 | omarea_Signing {
7 | keyAlias 'omarea.com'
8 | keyPassword 'asdf1234'
9 | storeFile file('D:/omoarea.jks')
10 | storePassword 'asdf1234'
11 | }
12 | }
13 | defaultConfig {
14 | resConfigs "zh"
15 | applicationId "com.omarea.gesture"
16 | minSdkVersion 21
17 | targetSdkVersion 29
18 | versionCode 104
19 | versionName "1.6.4"
20 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
21 | }
22 | buildTypes {
23 | release_mini {
24 | shrinkResources true
25 | minifyEnabled true
26 | // debuggable true
27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
28 | }
29 | release {
30 | debuggable true
31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
32 | }
33 | debug {
34 | // signingConfig signingConfigs.omarea_Signing
35 | minifyEnabled false
36 | debuggable true
37 | jniDebuggable = false
38 | }
39 | }
40 | lintOptions {
41 | checkReleaseBuilds false
42 | // Or, if you prefer, you can continue to check for errors in release builds,
43 | // but continue the build even when errors are found:
44 | abortOnError false
45 | }
46 | }
47 |
48 | dependencies {
49 | implementation fileTree(include: ['*.jar'], dir: 'libs')
50 | testImplementation 'junit:junit:4.13.1'
51 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
52 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
53 | }
54 | repositories {
55 | mavenCentral()
56 | }
57 |
--------------------------------------------------------------------------------
/app/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
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/omarea/gesture/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.content.Context;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import androidx.test.ext.junit.runners.AndroidJUnit4;
9 | import androidx.test.platform.app.InstrumentationRegistry;
10 |
11 | import static org.junit.Assert.assertEquals;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getTargetContext();
24 |
25 | assertEquals("com.omarea.sesture", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
12 |
15 |
18 |
19 |
20 |
21 |
22 |
32 |
36 |
37 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/app/src/main/assets/adb_process.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/assets/adb_process.dex
--------------------------------------------------------------------------------
/app/src/main/assets/up.sh:
--------------------------------------------------------------------------------
1 | file_name="adb_process.dex"
2 |
3 | path1="`dirname $0`/$file_name"
4 | path2="/storage/emulated/0/Android/data/com.omarea.gesture/cache/$file_name"
5 | path3="/sdcard/Android/data/com.omarea.gesture/cache/$file_name"
6 | path4="/data/media/0/Android/data/com.omarea.gesture/cache/$file_name"
7 |
8 | origin_path=""
9 | if [[ -e "$path1" ]];then
10 | origin_path="$path2"
11 | elif [[ -e "$path2" ]]; then
12 | origin_path="$path2"
13 | elif [[ -e "$path3" ]]; then
14 | origin_path="$path3"
15 | elif [[ -e "$path4" ]]; then
16 | origin_path="$path4"
17 | else
18 | echo 'Unknown sdcard !'
19 | exit 1
20 | fi
21 |
22 | cache_dir="/data/local/tmp"
23 | target_path="$cache_dir/gesture_process.dex"
24 |
25 | current_process=`pgrep -f gesture_process.dex`
26 | if [[ ! "$current_process" == "" ]]
27 | then
28 | echo 'Kill Current GestureProcess >>'
29 | kill -9 $current_process
30 | fi
31 |
32 | echo "Origin File: " $origin_path
33 | echo "Target File: " $target_path
34 | echo ''
35 |
36 | cmd package compile -m speed com.omarea.gesture 1 > /dev/null
37 |
38 | if [[ -e $origin_path ]]; then
39 | cp $origin_path $target_path
40 | nohup dalvikvm -cp $target_path Main >/dev/null 2>&1 &
41 | sleep 2
42 | nohup app_process -Djava.class.path=$target_path $cache_dir Main >/dev/null 2>&1 &
43 | sleep 5
44 | am broadcast -a com.omarea.gesture.ConfigChanged 1>/dev/null
45 | am broadcast -a com.omarea.gesture.AdbProcess
46 | else
47 | echo "Gesture's adb_process.dex not found !"
48 | fi
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/ActionModel.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.content.SharedPreferences;
4 |
5 | import java.io.Serializable;
6 |
7 | public class ActionModel implements Serializable {
8 | public int actionCode;
9 | public String title;
10 | public String exKey;
11 | public String st;
12 | public String shellCommand;
13 |
14 | private ActionModel(int code) {
15 | this.actionCode = code;
16 | }
17 |
18 | public ActionModel(int code, String title) {
19 | this.actionCode = code;
20 | this.title = title;
21 | }
22 |
23 | public static ActionModel getConfig(SharedPreferences config, String configKey, int defaultAction) {
24 | ActionModel actionModel = new ActionModel(config.getInt(configKey, defaultAction));
25 | actionModel.exKey = configKey;
26 |
27 | return actionModel;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/AdbProcessExtractor.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.content.Context;
4 |
5 | import com.omarea.gesture.remote.RemoteAPI;
6 | import com.omarea.gesture.shell.KeepShellPublic;
7 | import com.omarea.gesture.util.GlobalState;
8 |
9 | import java.io.BufferedReader;
10 | import java.io.File;
11 | import java.io.FileOutputStream;
12 | import java.io.InputStream;
13 | import java.io.InputStreamReader;
14 |
15 | public class AdbProcessExtractor {
16 | private boolean extractFile(Context context, String file) {
17 | try {
18 | File cacheDir = context.getExternalCacheDir();
19 | cacheDir.mkdirs();
20 |
21 | cacheDir.setExecutable(true);
22 | cacheDir.setWritable(true);
23 |
24 | InputStream inputStream = context.getAssets().open(file);
25 | File outFile = new File((cacheDir.getAbsolutePath() + "/" + file));
26 | FileOutputStream fileOutputStream = new FileOutputStream(outFile);
27 | byte[] datas = new byte[10240];
28 | while (true) {
29 | int len = inputStream.read(datas);
30 | if (len > 0) {
31 | fileOutputStream.write(datas, 0, len);
32 | } else {
33 | break;
34 | }
35 | }
36 |
37 | fileOutputStream.flush();
38 | fileOutputStream.close();
39 | inputStream.close();
40 |
41 | outFile.setExecutable(true, false);
42 | outFile.setReadable(true, false);
43 | outFile.setWritable(true, false);
44 |
45 | return true;
46 | } catch (Exception ex) {
47 | return false;
48 | }
49 | }
50 |
51 | private boolean extractShellScript(Context context, String file) {
52 | try {
53 | File cacheDir = context.getExternalCacheDir();
54 | cacheDir.mkdirs();
55 | cacheDir.setExecutable(true);
56 | cacheDir.setWritable(true);
57 |
58 | InputStream inputStream = context.getAssets().open(file);
59 | File outFile = new File((cacheDir.getAbsolutePath() + "/" + file));
60 | FileOutputStream fileOutputStream = new FileOutputStream(outFile);
61 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
62 | StringBuilder stringBuffer = new StringBuilder();
63 | String line;
64 | do {
65 | line = bufferedReader.readLine();
66 | if (line == null) {
67 | break;
68 | } else {
69 | stringBuffer.append(line);
70 | stringBuffer.append("\n");
71 | }
72 | } while (true);
73 | fileOutputStream.write(stringBuffer.toString().replaceAll("\r\n", "\n").replaceAll("\r", "\n").getBytes());
74 |
75 | fileOutputStream.flush();
76 | fileOutputStream.close();
77 | inputStream.close();
78 |
79 | outFile.setExecutable(true, false);
80 | outFile.setReadable(true, false);
81 | outFile.setWritable(true, false);
82 |
83 | return true;
84 | } catch (Exception ex) {
85 | return false;
86 | }
87 | }
88 |
89 | public String extract(Context context) {
90 | if (extractFile(context, "adb_process.dex") && extractShellScript(context, "up.sh")) {
91 | File cacheDir = context.getExternalCacheDir();
92 | return cacheDir.getAbsolutePath() + "/up.sh";
93 | }
94 | return null;
95 | }
96 |
97 | // 尝试连接AdbProcess,或使用root权限激活AdbProcess并连接
98 | public boolean updateAdbProcessState(Context context, boolean useRootStartService) {
99 | // 检测外部程序运行状态或使用root权限主动激活外部进程
100 | boolean rootMode = Gesture.config.getBoolean(SpfConfig.ROOT, SpfConfig.ROOT_DEFAULT);
101 | GlobalState.enhancedMode = RemoteAPI.isOnline();
102 | if (useRootStartService && rootMode && !GlobalState.enhancedMode) {
103 | String file = extract(context);
104 | if (file != null) {
105 | String shell = "sh " + file + " >/dev/null 2>&1 &";
106 | KeepShellPublic.doCmdSync(shell);
107 | Gesture.handler.postDelayed(new Runnable() {
108 | @Override
109 | public void run() {
110 | GlobalState.enhancedMode = RemoteAPI.isOnline();
111 | }
112 | }, 5000);
113 | }
114 | }
115 | return GlobalState.enhancedMode;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/BatteryReceiver.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.BatteryManager;
7 |
8 | import com.omarea.gesture.util.GlobalState;
9 |
10 | public class BatteryReceiver extends BroadcastReceiver {
11 | private boolean powerConnected = false;
12 | public BatteryReceiver(){}
13 |
14 | public BatteryReceiver(Context context) {
15 | try {
16 | BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
17 | GlobalState.batteryCapacity = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
18 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
19 | powerConnected = notCharging(batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS));
20 | }
21 | } catch (Exception ignored) {
22 | }
23 | }
24 |
25 | private boolean notCharging(int state) {
26 | return state != BatteryManager.BATTERY_STATUS_NOT_CHARGING && state != BatteryManager.BATTERY_STATUS_DISCHARGING;
27 | }
28 |
29 | @Override
30 | public void onReceive(Context context, Intent intent) {
31 | if (intent == null) {
32 | return;
33 | }
34 | String action = intent.getAction();
35 | if (action == null) {
36 | return;
37 | }
38 |
39 | int capacity = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
40 | switch (action) {
41 | case Intent.ACTION_BATTERY_CHANGED: {
42 | powerConnected = notCharging(intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1));
43 | break;
44 | }
45 | case Intent.ACTION_POWER_DISCONNECTED: {
46 | powerConnected = false;
47 | break;
48 | }
49 | case Intent.ACTION_POWER_CONNECTED: {
50 | powerConnected = true;
51 | break;
52 | }
53 | }
54 | if (capacity != GlobalState.batteryCapacity) {
55 | GlobalState.batteryCapacity = capacity;
56 | if (GlobalState.updateBar != null) {
57 | GlobalState.updateBar.run();
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/DialogAppSwitchExclusive.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.content.SharedPreferences;
8 |
9 | import com.omarea.gesture.util.AppInfo;
10 | import com.omarea.gesture.util.AppListHelper;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Set;
14 |
15 | public class DialogAppSwitchExclusive {
16 | public void openDialog(final Context context) {
17 | AlertDialog.Builder alertDialog = new AlertDialog.Builder(context).setCancelable(false);
18 |
19 | final SharedPreferences configFile = context.getSharedPreferences(SpfConfig.AppSwitchBlackList, Context.MODE_PRIVATE);
20 | final Set inListApps = configFile.getAll().keySet();
21 |
22 | final ArrayList appInfos = new AppListHelper().loadAppList(context);
23 | final String[] appNames = new String[appInfos.size()];
24 | final boolean[] status = new boolean[appInfos.size()];
25 | for (int i = 0; i < appInfos.size(); i++) {
26 | status[i] = inListApps.contains(appInfos.get(i).packageName);
27 | appNames[i] = appInfos.get(i).appName;
28 | }
29 |
30 | alertDialog
31 | .setTitle(context.getString(R.string.exclude_app))
32 | .setMultiChoiceItems(appNames,
33 | status, new DialogInterface.OnMultiChoiceClickListener() {
34 | @Override
35 | public void onClick(DialogInterface dialog, int which, boolean isChecked) {
36 | status[which] = isChecked;
37 | }
38 | })
39 | .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
40 | @Override
41 | public void onClick(DialogInterface dialog, int which) {
42 | final SharedPreferences.Editor config = configFile.edit();
43 | config.clear();
44 | for (int i = 0; i < status.length; i++) {
45 | if (status[i]) {
46 | config.putBoolean(appInfos.get(i).packageName, true);
47 | }
48 | }
49 | config.apply();
50 | try {
51 | Intent intent = new Intent(context.getString(R.string.app_switch_changed));
52 | context.sendBroadcast(intent);
53 | } catch (Exception ignored) {
54 | }
55 | }
56 | })
57 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
58 | @Override
59 | public void onClick(DialogInterface dialog, int which) {
60 | }
61 | })
62 | .show();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/DialogHandlerEX.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.SharedPreferences;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.BaseAdapter;
11 | import android.widget.EditText;
12 | import android.widget.TextView;
13 |
14 | import com.omarea.gesture.util.AppInfo;
15 | import com.omarea.gesture.util.AppListHelper;
16 | import com.omarea.gesture.util.Handlers;
17 |
18 | import java.util.ArrayList;
19 |
20 | public class DialogHandlerEX {
21 | public void openDialog(Context context, final String key, int customActionCode) {
22 | AlertDialog.Builder alertDialog = new AlertDialog.Builder(context).setCancelable(false);
23 |
24 | final SharedPreferences configFile = context.getSharedPreferences(SpfConfigEx.configFile, Context.MODE_PRIVATE);
25 | final SharedPreferences.Editor config = configFile.edit();
26 | config.remove(SpfConfigEx.prefix_app + key);
27 | config.remove(SpfConfigEx.prefix_app_window + key);
28 | config.remove(SpfConfigEx.prefix_shell + key);
29 |
30 | switch (customActionCode) {
31 | case Handlers.CUSTOM_ACTION_APP:
32 | case Handlers.CUSTOM_ACTION_APP_WINDOW: {
33 | final String fullKey = (customActionCode == Handlers.CUSTOM_ACTION_APP ? SpfConfigEx.prefix_app : SpfConfigEx.prefix_app_window) + key;
34 |
35 | final ArrayList appInfos = new AppListHelper().loadAppList(context);
36 | final String currentApp = configFile.getString(fullKey, "");
37 | alertDialog.setTitle(context.getString(R.string.custom_app));
38 | int currentIndex = -1;
39 | if (currentApp != null && !currentApp.isEmpty()) {
40 | for (int i = 0; i < appInfos.size(); i++) {
41 | if (appInfos.get(i).packageName.equals(currentApp)) {
42 | currentIndex = i;
43 | break;
44 | }
45 | }
46 | }
47 |
48 | final int finalCurrentIndex = currentIndex;
49 | alertDialog.setSingleChoiceItems(
50 | new BaseAdapter() {
51 | @Override
52 | public int getCount() {
53 | return appInfos.size();
54 | }
55 |
56 | @Override
57 | public Object getItem(int position) {
58 | return appInfos.get(position);
59 | }
60 |
61 | @Override
62 | public long getItemId(int position) {
63 | return position;
64 | }
65 |
66 | @Override
67 | public View getView(int position, View convertView, ViewGroup parent) {
68 | LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
69 | View view = layoutInflater.inflate(R.layout.gesture_layout_app_option, null);
70 | TextView title = view.findViewById(R.id.item_title);
71 | TextView desc = view.findViewById(R.id.item_desc);
72 | AppInfo appInfo = (AppInfo) getItem(position);
73 | title.setText(appInfo.appName);
74 | desc.setText(appInfo.packageName);
75 | if (position == finalCurrentIndex) {
76 | title.setTextColor(title.getHighlightColor());
77 | }
78 |
79 | return view;
80 | }
81 | },
82 | currentIndex, new DialogInterface.OnClickListener() {
83 | @Override
84 | public void onClick(DialogInterface dialog, int which) {
85 | config.putString(fullKey, appInfos.get(which).packageName).apply();
86 |
87 | dialog.dismiss();
88 | }
89 | });
90 |
91 | break;
92 | }
93 | case Handlers.CUSTOM_ACTION_SHELL: {
94 | final String fullKey = SpfConfigEx.prefix_shell + key;
95 |
96 | alertDialog.setTitle(context.getString(R.string.custom_shell));
97 | View view = LayoutInflater.from(context).inflate(R.layout.gesture_layout_ex_shell, null);
98 | final EditText editText = view.findViewById(R.id.ex_shell);
99 | editText.setText(configFile.getString(fullKey, ""));
100 |
101 | alertDialog.setView(view);
102 | alertDialog.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
103 | @Override
104 | public void onClick(DialogInterface dialog, int which) {
105 | config.putString(fullKey, editText.getText().toString()).apply();
106 | }
107 | });
108 |
109 | break;
110 | }
111 | default: {
112 | return;
113 | }
114 | }
115 |
116 | alertDialog.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
117 | @Override
118 | public void onClick(DialogInterface dialog, int which) {
119 | }
120 | });
121 | alertDialog.show();
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/EnhancedModeGuide.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.EditText;
9 |
10 | public class EnhancedModeGuide {
11 | public void show(Context context, String shell) {
12 | View view = LayoutInflater.from(context).inflate(R.layout.layout_enhanced_mode_guide, null);
13 | EditText editText = view.findViewById(R.id.enhanced_mode_shell);
14 | editText.setText("adb -d shell sh " + shell);
15 |
16 | new AlertDialog.Builder(context).setView(view).setPositiveButton(context.getString(R.string.btn_ok), new DialogInterface.OnClickListener() {
17 | @Override
18 | public void onClick(DialogInterface dialog, int which) {
19 |
20 | }
21 | })
22 | .setOnDismissListener(new DialogInterface.OnDismissListener() {
23 | @Override
24 | public void onDismiss(DialogInterface dialog) {
25 |
26 | }
27 | })
28 | .create().show();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/FixAppSwitchDelay.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 |
6 | public class FixAppSwitchDelay extends Activity {
7 |
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | finish();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/Gesture.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.content.SharedPreferences;
7 | import android.os.Build;
8 | import android.os.Handler;
9 | import android.os.StrictMode;
10 | import android.os.VibrationEffect;
11 | import android.os.Vibrator;
12 | import android.view.HapticFeedbackConstants;
13 | import android.view.View;
14 | import android.widget.Toast;
15 |
16 | public class Gesture extends Application {
17 | public static final Handler handler = new Handler();
18 | @SuppressLint("StaticFieldLeak")
19 | public static Context context;
20 | private static Vibrator vibrator;
21 | public static SharedPreferences config;
22 |
23 | public static void vibrate(VibrateMode mode, View view) {
24 | if (vibrator == null) {
25 | vibrator = (Vibrator) (context.getSystemService(Context.VIBRATOR_SERVICE));
26 | }
27 |
28 | if (vibrator.hasVibrator()) {
29 | if (config.getBoolean(SpfConfig.VIBRATOR_USE_SYSTEM, SpfConfig.VIBRATOR_USE_SYSTEM_DEFAULT)) {
30 | switch (mode) {
31 | case VIBRATE_CLICK: {
32 | view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
33 | return;
34 | }
35 | case VIBRATE_PRESS: {
36 | view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
37 | return;
38 | }
39 | case VIBRATE_SLIDE_HOVER: {
40 | view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
41 | return;
42 | }
43 | case VIBRATE_SLIDE: {
44 | if (config.getBoolean(SpfConfig.VIBRATOR_QUICK_SLIDE, SpfConfig.VIBRATOR_QUICK_SLIDE_DEFAULT)) {
45 | view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
46 | }
47 | return;
48 | }
49 | default: {
50 | }
51 | }
52 | } else {
53 | if (mode == VibrateMode.VIBRATE_SLIDE) {
54 | if (!config.getBoolean(SpfConfig.VIBRATOR_QUICK_SLIDE, SpfConfig.VIBRATOR_QUICK_SLIDE_DEFAULT)) {
55 | return;
56 | }
57 | }
58 |
59 | boolean longTime = mode == VibrateMode.VIBRATE_SLIDE_HOVER || mode == VibrateMode.VIBRATE_PRESS;
60 |
61 | vibrator.cancel();
62 | int time = longTime ? config.getInt(SpfConfig.VIBRATOR_TIME_LONG, SpfConfig.VIBRATOR_TIME_LONG_DEFAULT) : config.getInt(SpfConfig.VIBRATOR_TIME, SpfConfig.VIBRATOR_TIME_DEFAULT);
63 | int amplitude = longTime ? config.getInt(SpfConfig.VIBRATOR_AMPLITUDE_LONG, SpfConfig.VIBRATOR_AMPLITUDE_LONG_DEFAULT) : config.getInt(SpfConfig.VIBRATOR_AMPLITUDE, SpfConfig.VIBRATOR_AMPLITUDE_DEFAULT);
64 | if (time > 0 && amplitude > 0) {
65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
66 | vibrator.vibrate(VibrationEffect.createOneShot(time, amplitude));
67 | } else {
68 | vibrator.vibrate(new long[]{0, time, amplitude}, -1);
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
75 | public static void toast(final String text, final int time) {
76 | handler.post(new Runnable() {
77 | @Override
78 | public void run() {
79 | Toast.makeText(context, text, time).show();
80 | }
81 | });
82 | }
83 |
84 | @Override
85 | protected void attachBaseContext(Context base) {
86 | super.attachBaseContext(base);
87 |
88 | config = getSharedPreferences(SpfConfig.ConfigFile, Context.MODE_PRIVATE);
89 | StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
90 | StrictMode.setThreadPolicy(policy);
91 |
92 | context = this;
93 | }
94 |
95 | public static enum VibrateMode {
96 | VIBRATE_CLICK,
97 | VIBRATE_PRESS,
98 | VIBRATE_SLIDE_HOVER,
99 | VIBRATE_SLIDE
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import android.app.Activity;
4 | import android.app.ActivityManager;
5 | import android.app.UiModeManager;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.os.Build;
9 | import android.os.Bundle;
10 | import android.os.Handler;
11 | import android.os.Looper;
12 | import android.view.View;
13 | import android.view.WindowManager;
14 | import android.widget.TabHost;
15 |
16 | import com.omarea.gesture.fragments.Fragment3Section;
17 | import com.omarea.gesture.fragments.FragmentBasic;
18 | import com.omarea.gesture.fragments.FragmentOther;
19 | import com.omarea.gesture.fragments.FragmentSimple;
20 | import com.omarea.gesture.fragments.FragmentWhiteBar;
21 | import com.omarea.gesture.util.GlobalState;
22 | import com.omarea.gesture.util.Memory;
23 |
24 |
25 | public class SettingsActivity extends Activity {
26 | private boolean inLightMode = false;
27 |
28 | private void setTheme(boolean restart) {
29 | UiModeManager uiModeManager = (UiModeManager) getSystemService(Context.UI_MODE_SERVICE);
30 | boolean isNightMode = uiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
31 |
32 | if (!isNightMode) {
33 | setTheme(R.style.gestureAppThemeLight);
34 | // 设置白色状态栏
35 | View window = this.getWindow().getDecorView();
36 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
37 | window.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
38 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
39 | window.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
40 | }
41 | }
42 |
43 | if (inLightMode != isNightMode && restart) {
44 | recreate();
45 | }
46 | inLightMode = isNightMode;
47 | }
48 |
49 | @Override
50 | public void onCreate(Bundle savedInstanceState) {
51 | if (new Memory().getMemorySizeMB(this) > 4096) {
52 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
53 | }
54 |
55 | setTheme(false);
56 | super.onCreate(savedInstanceState);
57 | setContentView(R.layout.gesture_settings);
58 |
59 | try {
60 | final TabHost tabHost = findViewById(R.id.main_tabhost);
61 | tabHost.setup();
62 | tabHost.addTab(tabHost.newTabSpec("Basic")
63 | .setContent(R.id.main_tab_0).setIndicator("", getDrawable(R.drawable.gesture_tab_switch)));
64 | tabHost.addTab(tabHost.newTabSpec("WhiteBar")
65 | .setContent(R.id.main_tab_1).setIndicator("", getDrawable(R.drawable.gesture_tab_apple)));
66 | tabHost.addTab(tabHost.newTabSpec("Edge")
67 | .setContent(R.id.main_tab_2).setIndicator("", getDrawable(R.drawable.gesture_tab_lab)));
68 | tabHost.addTab(tabHost.newTabSpec("ThreeSection")
69 | .setContent(R.id.main_tab_3).setIndicator("", getDrawable(R.drawable.gesture_tab_edge)));
70 | tabHost.addTab(tabHost.newTabSpec("Other")
71 | .setContent(R.id.main_tab_4).setIndicator("", getDrawable(R.drawable.gesture_tab_settings)));
72 |
73 | getFragmentManager().beginTransaction()
74 | .replace(R.id.main_tab_0, new FragmentBasic()).commit();
75 | getFragmentManager().beginTransaction()
76 | .replace(R.id.main_tab_1, new FragmentWhiteBar()).commit();
77 | getFragmentManager().beginTransaction()
78 | .replace(R.id.main_tab_2, new FragmentSimple()).commit();
79 | getFragmentManager().beginTransaction()
80 | .replace(R.id.main_tab_3, new Fragment3Section()).commit();
81 | getFragmentManager().beginTransaction()
82 | .replace(R.id.main_tab_4, new FragmentOther()).commit();
83 | } catch (Exception ex) {
84 | }
85 | }
86 |
87 | private void updateView() {
88 | try {
89 | Intent intent = new Intent(getString(R.string.action_config_changed));
90 | sendBroadcast(intent);
91 | } catch (Exception ignored) {
92 | }
93 | }
94 |
95 | @Override
96 | protected void onResume() {
97 | super.onResume();
98 |
99 | GlobalState.testMode = true;
100 | new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
101 | @Override
102 | public void run() {
103 | updateView();
104 | }
105 | }, 500);
106 |
107 | setTheme(true);
108 | }
109 |
110 | @Override
111 | protected void onPause() {
112 | super.onPause();
113 | GlobalState.testMode = false;
114 | new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
115 | @Override
116 | public void run() {
117 | updateView();
118 | }
119 | }, 500);
120 | }
121 |
122 |
123 | private void setExcludeFromRecents(boolean excludeFromRecents) {
124 | try {
125 | ActivityManager service = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
126 | int taskId = this.getTaskId();
127 | for (ActivityManager.AppTask task : service.getAppTasks()) {
128 | if (task.getTaskInfo().id == taskId) {
129 | task.setExcludeFromRecents(excludeFromRecents);
130 | }
131 | }
132 | } catch (Exception ex) {
133 | }
134 | }
135 |
136 | @Override
137 | public void onBackPressed() {
138 | setExcludeFromRecents(true);
139 | super.onBackPressed();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/SpfConfigEx.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | public class SpfConfigEx {
4 | public static final String configFile = "handler_ex";
5 | public static final String prefix_app = "app_";
6 | public static final String prefix_app_window = "app_form_";
7 | public static final String prefix_shell = "shell_";
8 | public static final String frequently_apps = "frequently_apps3";
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/StartActivity.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | public class StartActivity extends SettingsActivity {
4 | }
5 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/WhiteBarColor.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import com.omarea.gesture.remote.RemoteAPI;
4 | import com.omarea.gesture.util.GlobalState;
5 |
6 | public class WhiteBarColor {
7 | private static final Object threadRun = "";
8 | private static ScreenCapThread thread;
9 | private static int nextTimes = 0;
10 | private static boolean notifyed = false; // 是否已经notify过,并且还未进入wait清除notifyed状态,避免多次notify进入队列
11 |
12 | public static void updateBarColorSingle() {
13 | updateBarColor();
14 | }
15 |
16 | static void updateBarColorMultiple() {
17 | nextTimes = 2;
18 | updateBarColor();
19 | }
20 |
21 | private static void updateBarColor() {
22 | if (thread != null && thread.isAlive() && !thread.isInterrupted()) {
23 | synchronized (threadRun) {
24 | if (!notifyed && (thread.getState() == Thread.State.WAITING || thread.getState() == Thread.State.TIMED_WAITING)) {
25 | threadRun.notify();
26 | notifyed = true;
27 | }
28 | }
29 | } else {
30 | thread = new ScreenCapThread();
31 | thread.start();
32 | }
33 | }
34 |
35 | public static void updateDisplaySize() {
36 |
37 | }
38 |
39 | static class ScreenCapThread extends Thread {
40 | @Override
41 | public void run() {
42 | do {
43 | int color = RemoteAPI.getBarAutoColor(nextTimes > 0);
44 | if (color != Integer.MIN_VALUE) {
45 | GlobalState.iosBarColor = color;
46 |
47 | if (GlobalState.updateBar != null) {
48 | GlobalState.updateBar.run();
49 | }
50 | }
51 | notifyed = false;
52 | try {
53 | synchronized (threadRun) {
54 | if (nextTimes > 0) {
55 | threadRun.wait(600);
56 | nextTimes -= 1;
57 | } else {
58 | threadRun.wait();
59 | }
60 | }
61 | } catch (Exception ex) {
62 | break;
63 | }
64 | }
65 | while (true);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/fragments/Fragment3Section.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.omarea.gesture.R;
9 | import com.omarea.gesture.SpfConfig;
10 |
11 | public class Fragment3Section extends FragmentSettingsBase {
12 |
13 | @Override
14 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
15 |
16 | return inflater.inflate(R.layout.gesture_settings_3section, container, false);
17 | }
18 |
19 | @Override
20 | public void onResume() {
21 | super.onResume();
22 |
23 | bindCheckable(R.id.allow_three_section_landscape, SpfConfig.THREE_SECTION_LANDSCAPE, SpfConfig.THREE_SECTION_LANDSCAPE_DEFAULT);
24 | bindCheckable(R.id.allow_three_section_portrait, SpfConfig.THREE_SECTION_PORTRAIT, SpfConfig.THREE_SECTION_PORTRAIT_DEFAULT);
25 | bindSeekBar(R.id.bar_width_three_section, SpfConfig.THREE_SECTION_WIDTH, SpfConfig.THREE_SECTION_WIDTH_DEFAULT, true);
26 | bindSeekBar(R.id.three_section_height, SpfConfig.THREE_SECTION_HEIGHT, SpfConfig.THREE_SECTION_HEIGHT_DEFAULT, true);
27 |
28 | bindHandlerPicker(R.id.three_section_left_slide, SpfConfig.THREE_SECTION_LEFT_SLIDE, SpfConfig.THREE_SECTION_LEFT_SLIDE_DEFAULT);
29 | bindHandlerPicker(R.id.three_section_center_slide, SpfConfig.THREE_SECTION_CENTER_SLIDE, SpfConfig.THREE_SECTION_CENTER_SLIDE_DEFAULT);
30 | bindHandlerPicker(R.id.three_section_right_slide, SpfConfig.THREE_SECTION_RIGHT_SLIDE, SpfConfig.THREE_SECTION_RIGHT_SLIDE_DEFAULT);
31 | bindHandlerPicker(R.id.three_section_left_hover, SpfConfig.THREE_SECTION_LEFT_HOVER, SpfConfig.THREE_SECTION_LEFT_HOVER_DEFAULT);
32 | bindHandlerPicker(R.id.three_section_center_hover, SpfConfig.THREE_SECTION_CENTER_HOVER, SpfConfig.THREE_SECTION_CENTER_HOVER_DEFAULT);
33 | bindHandlerPicker(R.id.three_section_right_hover, SpfConfig.THREE_SECTION_RIGHT_HOVER, SpfConfig.THREE_SECTION_RIGHT_HOVER_DEFAULT);
34 |
35 | bindColorPicker(R.id.bar_color_three_section, SpfConfig.THREE_SECTION_COLOR, SpfConfig.THREE_SECTION_COLOR_DEFAULT, getString(R.string.feedback_color));
36 |
37 | updateView();
38 | }
39 |
40 | private void updateView() {
41 | setViewBackground(getActivity().findViewById(R.id.bar_color_three_section), config.getInt(SpfConfig.THREE_SECTION_COLOR, SpfConfig.THREE_SECTION_COLOR_DEFAULT));
42 |
43 | updateActionText(R.id.three_section_left_slide, SpfConfig.THREE_SECTION_LEFT_SLIDE, SpfConfig.THREE_SECTION_LEFT_SLIDE_DEFAULT);
44 | updateActionText(R.id.three_section_center_slide, SpfConfig.THREE_SECTION_CENTER_SLIDE, SpfConfig.THREE_SECTION_CENTER_SLIDE_DEFAULT);
45 | updateActionText(R.id.three_section_right_slide, SpfConfig.THREE_SECTION_RIGHT_SLIDE, SpfConfig.THREE_SECTION_RIGHT_SLIDE_DEFAULT);
46 | updateActionText(R.id.three_section_left_hover, SpfConfig.THREE_SECTION_LEFT_HOVER, SpfConfig.THREE_SECTION_LEFT_HOVER_DEFAULT);
47 | updateActionText(R.id.three_section_center_hover, SpfConfig.THREE_SECTION_CENTER_HOVER, SpfConfig.THREE_SECTION_CENTER_HOVER_DEFAULT);
48 | updateActionText(R.id.three_section_right_hover, SpfConfig.THREE_SECTION_RIGHT_HOVER, SpfConfig.THREE_SECTION_RIGHT_HOVER_DEFAULT);
49 | }
50 |
51 | @Override
52 | protected void restartService() {
53 | updateView();
54 |
55 | super.restartService();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/fragments/FragmentSimple.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.fragments;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.omarea.gesture.R;
10 | import com.omarea.gesture.SpfConfig;
11 |
12 | public class FragmentSimple extends FragmentSettingsBase {
13 | @Override
14 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
15 | return inflater.inflate(R.layout.gesture_settings_simple, container, false);
16 | }
17 |
18 | @Override
19 | public void onResume() {
20 | super.onResume();
21 |
22 | bindColorPicker(R.id.bar_edge_color, SpfConfig.CONFIG_EDGE_COLOR, SpfConfig.CONFIG_EDGE_COLOR_DEFAULT, getString(R.string.feedback_color));
23 |
24 | bindCheckable(R.id.allow_bottom_landscape, SpfConfig.CONFIG_BOTTOM_ALLOW_LANDSCAPE, SpfConfig.CONFIG_BOTTOM_ALLOW_LANDSCAPE_DEFAULT);
25 | bindCheckable(R.id.allow_bottom_portrait, SpfConfig.CONFIG_BOTTOM_ALLOW_PORTRAIT, SpfConfig.CONFIG_BOTTOM_ALLOW_PORTRAIT_DEFAULT);
26 | bindSeekBar(R.id.bar_width_bottom, SpfConfig.CONFIG_BOTTOM_WIDTH, SpfConfig.CONFIG_BOTTOM_WIDTH_DEFAULT, true);
27 | bindHandlerPicker(R.id.tap_bottom, SpfConfig.CONFIG_BOTTOM_EVENT, SpfConfig.CONFIG_BOTTOM_EVENT_DEFAULT);
28 | bindHandlerPicker(R.id.hover_bottom, SpfConfig.CONFIG_BOTTOM_EVENT_HOVER, SpfConfig.CONFIG_BOTTOM_EVENT_HOVER_DEFAULT);
29 |
30 | bindCheckable(R.id.allow_right_landscape, SpfConfig.CONFIG_RIGHT_ALLOW_LANDSCAPE, SpfConfig.CONFIG_RIGHT_ALLOW_LANDSCAPE_DEFAULT);
31 | bindCheckable(R.id.allow_right_portrait, SpfConfig.CONFIG_RIGHT_ALLOW_PORTRAIT, SpfConfig.CONFIG_RIGHT_ALLOW_PORTRAIT_DEFAULT);
32 | bindSeekBar(R.id.bar_height_right, SpfConfig.CONFIG_RIGHT_HEIGHT, SpfConfig.CONFIG_RIGHT_HEIGHT_DEFAULT, true);
33 | bindHandlerPicker(R.id.tap_right, SpfConfig.CONFIG_RIGHT_EVENT, SpfConfig.CONFIG_RIGHT_EVENT_DEFAULT);
34 | bindHandlerPicker(R.id.hover_right, SpfConfig.CONFIG_RIGHT_EVENT_HOVER, SpfConfig.CONFIG_RIGHT_EVENT_HOVER_DEFAULT);
35 |
36 | bindCheckable(R.id.allow_left_landscape, SpfConfig.CONFIG_LEFT_ALLOW_LANDSCAPE, SpfConfig.CONFIG_LEFT_ALLOW_LANDSCAPE_DEFAULT);
37 | bindCheckable(R.id.allow_left_portrait, SpfConfig.CONFIG_LEFT_ALLOW_PORTRAIT, SpfConfig.CONFIG_LEFT_ALLOW_PORTRAIT_DEFAULT);
38 | bindSeekBar(R.id.bar_height_left, SpfConfig.CONFIG_LEFT_HEIGHT, SpfConfig.CONFIG_LEFT_HEIGHT_DEFAULT, true);
39 | bindHandlerPicker(R.id.tap_left, SpfConfig.CONFIG_LEFT_EVENT, SpfConfig.CONFIG_LEFT_EVENT_DEFAULT);
40 | bindHandlerPicker(R.id.hover_left, SpfConfig.CONFIG_LEFT_EVENT_HOVER, SpfConfig.CONFIG_LEFT_EVENT_HOVER_DEFAULT);
41 |
42 | bindSeekBar(R.id.edge_side_width, SpfConfig.CONFIG_HOT_SIDE_WIDTH, SpfConfig.CONFIG_HOT_SIDE_WIDTH_DEFAULT, true);
43 | bindSeekBar(R.id.edge_bottom_height, SpfConfig.CONFIG_HOT_BOTTOM_HEIGHT, SpfConfig.CONFIG_HOT_BOTTOM_HEIGHT_DEFAULT, true);
44 |
45 | updateView();
46 | }
47 |
48 |
49 | private void updateView() {
50 | Activity activity = getActivity();
51 | setViewBackground(activity.findViewById(R.id.bar_edge_color), config.getInt(SpfConfig.CONFIG_EDGE_COLOR, SpfConfig.CONFIG_EDGE_COLOR_DEFAULT));
52 |
53 | updateActionText(R.id.tap_bottom, SpfConfig.CONFIG_BOTTOM_EVENT, SpfConfig.CONFIG_BOTTOM_EVENT_DEFAULT);
54 | updateActionText(R.id.hover_bottom, SpfConfig.CONFIG_BOTTOM_EVENT_HOVER, SpfConfig.CONFIG_BOTTOM_EVENT_HOVER_DEFAULT);
55 | updateActionText(R.id.tap_left, SpfConfig.CONFIG_LEFT_EVENT, SpfConfig.CONFIG_LEFT_EVENT_DEFAULT);
56 | updateActionText(R.id.hover_left, SpfConfig.CONFIG_LEFT_EVENT_HOVER, SpfConfig.CONFIG_LEFT_EVENT_HOVER_DEFAULT);
57 | updateActionText(R.id.tap_right, SpfConfig.CONFIG_RIGHT_EVENT, SpfConfig.CONFIG_RIGHT_EVENT_DEFAULT);
58 | updateActionText(R.id.hover_right, SpfConfig.CONFIG_RIGHT_EVENT_HOVER, SpfConfig.CONFIG_RIGHT_EVENT_HOVER_DEFAULT);
59 | }
60 |
61 | @Override
62 | protected void restartService() {
63 | updateView();
64 |
65 | super.restartService();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/remote/RemoteAPI.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.remote;
2 |
3 | import android.os.Build;
4 |
5 | import com.omarea.gesture.util.GlobalState;
6 |
7 | import java.io.BufferedReader;
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.net.URL;
11 | import java.net.URLConnection;
12 | import java.net.URLEncoder;
13 |
14 | public class RemoteAPI {
15 | private final static Object networkWaitLock = new Object();
16 | private static String host = "http://localhost:8906/";
17 |
18 | public static boolean isOnline() {
19 | String result = loadContent("version");
20 | return result != null && !result.isEmpty();
21 | }
22 |
23 | public static String[] getRecents() {
24 | return loadContent((Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) ? "recent-9" : "recent-10").split("\n");
25 | }
26 |
27 | public static int getBarAutoColor(boolean delayScreenCap) {
28 | // TODO:改为可配置而非自动
29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
30 | String isLightColor = loadContent("nav-light-color");
31 | if (isLightColor != null && isLightColor.equals("true")) {
32 | return 0xFF000000;
33 | }
34 | }
35 | if (delayScreenCap) {
36 | // 延缓截图,以免在动画播放期间过早的截图导致颜色取到的还是黑色背景
37 | try {
38 | Thread.sleep(300);
39 | } catch (Exception ignored) {
40 | }
41 | }
42 |
43 | String colorStr = loadContent("bar-color?" + GlobalState.displayWidth + "x" + GlobalState.displayHeight);
44 |
45 | if (!(colorStr == null || colorStr.isEmpty())) {
46 | try {
47 | return Integer.parseInt(colorStr);
48 | } catch (Exception ignored) {
49 | }
50 | }
51 | return Integer.MIN_VALUE;
52 | }
53 |
54 | private static String loadContent(final String api) {
55 | final String[] result = {""};
56 | new Thread(new Runnable() {
57 | @Override
58 | public void run() {
59 | synchronized (networkWaitLock) {
60 | try {
61 | URL url = new URL(host + api);
62 | result[0] = readResponse(url.openConnection());
63 | } catch (Exception ignored) {
64 | } finally {
65 | networkWaitLock.notify();
66 | }
67 | }
68 | }
69 | }).start();
70 | try {
71 | synchronized (networkWaitLock) {
72 | networkWaitLock.wait(5000);
73 | }
74 | } catch (Exception ignored) {
75 | }
76 | return result[0];
77 | }
78 |
79 | public static String getColorPollingApps() {
80 | final String[] results = {""};
81 | new Thread(new Runnable() {
82 | @Override
83 | public void run() {
84 | synchronized (networkWaitLock) {
85 | try {
86 | URL url = new URL("https://vtools.oss-cn-beijing.aliyuncs.com/EdgeGesture/color-polling-apps.txt");
87 | results[0] = readResponse(url.openConnection());
88 | } catch (Exception ignored) {
89 | } finally {
90 | networkWaitLock.notify();
91 | }
92 | }
93 | }
94 | }).start();
95 | try {
96 | synchronized (networkWaitLock) {
97 | networkWaitLock.wait(5000);
98 | }
99 | } catch (Exception ignored) {
100 | }
101 |
102 | return results[0];
103 | }
104 |
105 | private static String readResponse(URLConnection connection) {
106 | try {
107 | connection.setConnectTimeout(500);
108 | connection.setReadTimeout(3000);
109 |
110 | StringBuilder stringBuffer = new StringBuilder();
111 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
112 | String line = null;
113 | while (true) {
114 | line = bufferedReader.readLine();
115 | if (line == null) {
116 | break;
117 | } else {
118 | stringBuffer.append(line);
119 | stringBuffer.append("\n");
120 | }
121 | }
122 | return stringBuffer.toString().trim();
123 | } catch (IOException ignored) {
124 | }
125 | return null;
126 | }
127 |
128 | public static void fixDelay() {
129 | new Thread(new Runnable() {
130 | @Override
131 | public void run() {
132 | loadContent("fix-delay");
133 | }
134 | }).start();
135 | }
136 |
137 | public static void xiaomiHandymode(final int mode) {
138 | new Thread(new Runnable() {
139 | @Override
140 | public void run() {
141 | loadContent("xiaomi-handymode?" + mode);
142 | }
143 | }).start();
144 | }
145 |
146 | public static void startActivity(final String params) {
147 | new Thread(new Runnable() {
148 | @Override
149 | public void run() {
150 | try {
151 | StringBuilder paramsBuilder = new StringBuilder("am start -n com.omarea.gesture/.AppSwitchActivity");
152 | if (params != null) {
153 | paramsBuilder.append(" ");
154 | paramsBuilder.append(params);
155 | }
156 | paramsBuilder.append(" --activity-no-animation --activity-no-history --activity-exclude-from-recents --activity-clear-top --activity-clear-task");
157 | loadContent("shell?" + URLEncoder.encode(paramsBuilder.toString(), "UTF-8"));
158 | } catch (Exception ignored) {
159 | }
160 | }
161 | }).start();
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/shell/KeepShellPublic.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.shell;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by Hello on 2018/01/23.
7 | */
8 | public class KeepShellPublic {
9 | private static KeepShell keepShell = null;
10 |
11 | public static Boolean doCmdSync(List commands) {
12 | StringBuilder stringBuilder = new StringBuilder();
13 |
14 | for (String cmd : commands) {
15 | stringBuilder.append(cmd);
16 | stringBuilder.append("\n\n");
17 | }
18 |
19 | return doCmdSync(stringBuilder.toString()) != "error";
20 | }
21 |
22 | //执行脚本
23 | public static String doCmdSync(String cmd) {
24 | if (keepShell == null) {
25 | keepShell = new KeepShell();
26 | }
27 | return keepShell.doCmdSync(cmd);
28 | }
29 |
30 | //执行脚本
31 | public static Boolean checkRoot() {
32 | if (keepShell == null) {
33 | keepShell = new KeepShell();
34 | }
35 | return keepShell.checkRoot();
36 | }
37 |
38 | public static void tryExit() {
39 | if (keepShell != null) {
40 | keepShell.tryExit();
41 | keepShell = null;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/shell/ShellExecutor.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.shell;
2 |
3 | import java.io.IOException;
4 |
5 | public class ShellExecutor {
6 | private static Process getProcess(String run) throws IOException {
7 | return Runtime.getRuntime().exec(run);
8 | }
9 |
10 | public static Process getSuperUserRuntime() throws IOException {
11 | return getProcess("su");
12 | }
13 |
14 | public static Process getRuntime() throws IOException {
15 | return getProcess("sh");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/ui/ReTouchHelper.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.ui;
2 |
3 | import android.accessibilityservice.AccessibilityService;
4 | import android.accessibilityservice.GestureDescription;
5 | import android.graphics.Path;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.view.WindowManager;
9 |
10 | public class ReTouchHelper {
11 | private AccessibilityService mAccessibilityService;
12 | private WindowManager mWindowManager;
13 | private View mView;
14 | private int mFlags;
15 | private boolean running;
16 | final WindowManager.LayoutParams mParams;
17 | public ReTouchHelper(AccessibilityService accessibilityService, WindowManager windowManager, View view) {
18 | mAccessibilityService = accessibilityService;
19 | mWindowManager = windowManager;
20 | mView = view;
21 | mParams = (WindowManager.LayoutParams) view.getLayoutParams();
22 | mFlags = mParams.flags;
23 | }
24 |
25 | public void dispatchGesture(final Path touchPath) {
26 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
27 | synchronized (this) {
28 | if (running) {
29 | return;
30 | }
31 | Log.e("@Gesture", "dispatchGesture >>");
32 | pause();
33 | mView.postDelayed(new Runnable() {
34 | @Override
35 | public void run() {
36 | try {
37 | final GestureDescription.Builder builder = new GestureDescription.Builder();
38 | builder.addStroke(new GestureDescription.StrokeDescription(touchPath, 1, 1));
39 | mAccessibilityService.dispatchGesture(builder.build(), new AccessibilityService.GestureResultCallback() {
40 | @Override
41 | public void onCompleted(GestureDescription gestureDescription) {
42 | resume();
43 | super.onCompleted(gestureDescription);
44 | }
45 |
46 | public void onCancelled(GestureDescription gestureDescription) {
47 | resume();
48 | super.onCancelled(gestureDescription);
49 | }
50 | }, null);
51 | } catch (Exception ignored) {
52 | resume();
53 | }
54 | }
55 | }, 60);
56 | }
57 | }
58 | }
59 |
60 | private void pause() {
61 | running = true;
62 | mParams.flags = mFlags | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
63 | mWindowManager.updateViewLayout(mView, mParams);
64 | }
65 |
66 | private void resume() {
67 | mParams.flags = mFlags ;
68 | mWindowManager.updateViewLayout(mView, mParams);
69 | Log.e("@Gesture", "dispatchGesture √");
70 | mView.postDelayed(new Runnable() {
71 | @Override
72 | public void run() {
73 | running = false;
74 | }
75 | }, 60);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/ui/iOSTouchBarView.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.omarea.gesture.util.GlobalState;
13 |
14 | public class iOSTouchBarView extends View {
15 | private Context context = getContext();
16 |
17 | private Paint p = new Paint();
18 | private float shadowSize = 16f;
19 | private float lineWeight = 16f;
20 | private float strokeWidth = 0f;
21 | private float strokeR = 0f;
22 | private int lineColor = 0;
23 | private int strokeColor = 0;
24 | private float margin = 24f;
25 |
26 | public iOSTouchBarView(Context context) {
27 | super(context);
28 | init();
29 | }
30 |
31 | public iOSTouchBarView(Context context, AttributeSet attributeSet) {
32 | super(context, attributeSet);
33 | init();
34 | }
35 |
36 | public iOSTouchBarView(Context context, AttributeSet attributeSet, int defStyleAttr) {
37 | super(context, attributeSet, defStyleAttr);
38 | init();
39 | }
40 |
41 | private void init() {
42 | p.setAntiAlias(true);
43 | p.setStyle(Paint.Style.FILL);
44 | p.setColor(0xf0f0f0f0);
45 | p.setStrokeWidth(dp2px(context, 8));
46 | p.setStrokeCap(Paint.Cap.ROUND);
47 | // p.setShadowLayer(dp2px(context, 4), 0, 0, 0x88000000);
48 |
49 | // setLayerType(LAYER_TYPE_SOFTWARE, null);
50 | }
51 |
52 | void setStyle(int widthPx, int heightPx, int color, int shadowColor, int shadowSizeDp, int lineWeightDp, int strokeWidth, int strokeColor) {
53 | this.shadowSize = dp2px(context, shadowSizeDp);
54 | this.lineWeight = dp2px(context, lineWeightDp);
55 | this.strokeWidth = dp2px(context, strokeWidth);
56 | this.strokeR = this.strokeWidth / 2;
57 | this.margin = this.shadowSize + (this.lineWeight / 2f) + this.strokeWidth;
58 | this.lineColor = color;
59 | this.strokeColor = strokeColor;
60 |
61 | if (this.shadowSize > 0) {
62 | p.setShadowLayer(this.shadowSize, 0, 0, shadowColor);
63 | }
64 |
65 | if (this.strokeWidth > 0) {
66 | p.setStrokeWidth(this.strokeWidth);
67 | } else {
68 | p.setStrokeWidth(0);
69 | }
70 |
71 | ViewGroup.LayoutParams lp = this.getLayoutParams();
72 | int h = heightPx;
73 | int w = widthPx;
74 | if (h < 1) {
75 | h = 1;
76 | }
77 | if (w < 1) {
78 | w = 1;
79 | }
80 | lp.width = w;
81 | lp.height = h;
82 | this.setLayoutParams(lp);
83 | }
84 |
85 | /**
86 | * dp转换成px
87 | */
88 | private int dp2px(Context context, float dpValue) {
89 | float scale = context.getResources().getDisplayMetrics().density;
90 | return (int) (dpValue * scale + 0.5f);
91 | }
92 |
93 | @Override
94 | @SuppressLint("DrawAllocation")
95 | public void onDraw(Canvas canvas) {
96 | super.onDraw(canvas);
97 | p.setAlpha(255);
98 | if (GlobalState.useBatteryCapacity) {
99 | int capacity = GlobalState.batteryCapacity;
100 | p.setColor(lineColor);
101 | drawLine(canvas, p);
102 | if (capacity > 0) {
103 | if (capacity > 85) {
104 | p.setColor(Color.argb(255, 19, 142, 214));
105 | } else if (capacity > 75) {
106 | p.setColor(Color.argb(255, 0, 185, 194));
107 | } else if (capacity > 60) {
108 | p.setColor(Color.argb(255, 0, 213, 217));
109 | } else if (capacity > 45) {
110 | p.setColor(Color.argb(255, 2, 217, 141));
111 | } else if (capacity > 35) {
112 | p.setColor(Color.argb(255, 135, 203, 0));
113 | } else if (capacity > 20) {
114 | p.setColor(Color.argb(255, 252, 138, 27));
115 | } else {
116 | p.setColor(Color.argb(255, 249, 89, 47));
117 | }
118 | float totalWidth = getWidth() - (margin * 2);
119 | float outMargin = 0;
120 | canvas.drawRoundRect(margin + outMargin, margin + outMargin, margin + (totalWidth * capacity / 100f) - outMargin, margin + lineWeight - outMargin, 20, 20, p);
121 |
122 | p.setStyle(Paint.Style.FILL);
123 | p.setAlpha(210);
124 | // p.setColor(lineColor);
125 | drawLine(canvas, p);
126 | }
127 | } else {
128 | if (GlobalState.iosBarColor != Integer.MIN_VALUE) {
129 | if (strokeWidth > 0) {
130 | p.setStyle(Paint.Style.STROKE);
131 | if (GlobalState.iosBarColor == Color.WHITE) {
132 | p.setColor(Color.BLACK);
133 | } else {
134 | p.setColor(Color.WHITE);
135 | }
136 | canvas.drawRoundRect(margin - strokeR, margin - strokeR, getWidth() - margin + strokeR, margin + lineWeight + strokeR, 20, 20, p);
137 | }
138 |
139 | p.setStyle(Paint.Style.FILL);
140 | p.setColor(GlobalState.iosBarColor);
141 | drawLine(canvas, p);
142 | } else {
143 | if (strokeWidth > 0) {
144 | p.setStyle(Paint.Style.STROKE);
145 | p.setColor(strokeColor);
146 | canvas.drawRoundRect(margin - strokeR, margin - strokeR, getWidth() - margin + strokeR, margin + lineWeight + strokeR, 20, 20, p);
147 | }
148 |
149 | p.setStyle(Paint.Style.FILL);
150 | p.setColor(lineColor);
151 | drawLine(canvas, p);
152 | }
153 | }
154 | }
155 |
156 | private void drawLine(Canvas canvas, Paint p) {
157 | canvas.drawRoundRect(margin, margin, getWidth() - margin, margin + lineWeight, 20, 20, p);
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/AppInfo.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | public class AppInfo {
4 | public String appName;
5 | public String packageName;
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/AppLauncher.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.app.ActivityOptions;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.widget.Toast;
7 |
8 | import com.omarea.gesture.Gesture;
9 |
10 | public class AppLauncher {
11 | Intent getAppSwitchIntent(String appPackageName) {
12 | Intent i = Gesture.context.getPackageManager().getLaunchIntentForPackage(appPackageName);
13 | i.setFlags((i.getFlags() & ~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
14 | i.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
15 | i.setPackage(null);
16 | return i;
17 | }
18 |
19 | void startActivity(Context context, String targetApp) {
20 | try {
21 | context.startActivity(getAppSwitchIntent(targetApp));
22 | } catch (Exception ex) {
23 | Gesture.toast("" + ex.getMessage(), Toast.LENGTH_SHORT);
24 | }
25 | }
26 |
27 | public void startActivity(Context context, String targetApp, ActivityOptions activityOptions) {
28 | context.startActivity(getAppSwitchIntent(targetApp), activityOptions.toBundle());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/AppListHelper.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.pm.PackageManager;
6 | import android.content.pm.ResolveInfo;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class AppListHelper {
12 | public ArrayList loadAppList(Context context) {
13 | final PackageManager packageManager = context.getPackageManager();
14 | Intent queryActIntent = new Intent(Intent.ACTION_MAIN, null);
15 | queryActIntent.addCategory(Intent.CATEGORY_LAUNCHER);
16 | // queryActIntent.setPackage(info.packageName);
17 | List resolveInfoList = packageManager.queryIntentActivities(queryActIntent, 0);
18 |
19 | ArrayList packages = new ArrayList<>();
20 | for (final ResolveInfo resolveInfo : resolveInfoList) {
21 | String appName = (String) resolveInfo.loadLabel(packageManager);
22 | packages.add(new AppInfo() {{
23 | appName = (String) resolveInfo.loadLabel(packageManager);
24 | packageName = resolveInfo.activityInfo.packageName;
25 | }});
26 | }
27 |
28 | return packages;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/AppWindowed.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.app.ActivityOptions;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 |
8 | import java.lang.reflect.Method;
9 |
10 | public class AppWindowed {
11 | public void switchToFreeForm(Context context, String packageName) {
12 | // ActivityOptions activityOptions = ActivityOptions.makeTaskLaunchBehind();
13 | // 设置不合理的动画,可能导致切换窗口模式时奔溃,因此去掉动画
14 | ActivityOptions activityOptions = ActivityOptions.makeCustomAnimation(context.getApplicationContext(), 0, 0);
15 |
16 | Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
17 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
18 | // intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
19 | try {
20 | Method method = ActivityOptions.class.getMethod("setLaunchWindowingMode", int.class);
21 | method.invoke(activityOptions, 5);
22 | } catch (Exception e) { /* Gracefully fail */ }
23 |
24 | // int left = 50;
25 | // int top = 100;
26 | // int right = 50 + GlobalState.displayWidth / 2;
27 | // int bottom = 100 + (GlobalState.displayWidth / 2 * 16 / 9);
28 | // activityOptions.setLaunchBounds(new Rect(left, top, right, bottom));
29 |
30 | Bundle bundle = activityOptions.toBundle();
31 | context.startActivity(intent, bundle);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/BatteryUtils.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.Context;
4 | import android.os.BatteryManager;
5 |
6 | public class BatteryUtils {
7 | private BatteryManager batteryManager;
8 |
9 | public BatteryUtils(Context context) {
10 | this.batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
11 | }
12 |
13 | public int getCapacity() {
14 | return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/GlobalState.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import com.omarea.gesture.ActionModel;
6 | import com.omarea.gesture.ui.VisualFeedbackView;
7 |
8 | public class GlobalState {
9 | // 使用连续动作
10 | public static boolean consecutive = false;
11 | // 连续动作
12 | public static ActionModel consecutiveAction = null;
13 |
14 | // 电池电量
15 | public static int batteryCapacity = -1;
16 | // 小横条是否使用电量
17 | public static boolean useBatteryCapacity = false;
18 |
19 | public static long lastBackHomeTime = 0;
20 |
21 | public static boolean isLandscapf = false;
22 | public static boolean testMode = false;
23 | public static int iosBarColor = Integer.MIN_VALUE;
24 | public static Runnable updateBar;
25 | public static int displayHeight = 2340;
26 | public static int displayWidth = 1080;
27 | // 增强模式(需要Root或者ADB)
28 | public static boolean enhancedMode = false;
29 |
30 | public static VisualFeedbackView visualFeedbackView;
31 |
32 | public static void startEdgeFeedback(float startRawX, float startRawY, int sideMode) {
33 | if (visualFeedbackView != null) {
34 | visualFeedbackView.startEdgeFeedback(startRawX, startRawY, sideMode);
35 | }
36 | }
37 |
38 | public static void updateEdgeFeedback(float currentRawX, float currentRawY) {
39 | if (visualFeedbackView != null) {
40 | visualFeedbackView.updateEdgeFeedback(currentRawX, currentRawY);
41 | }
42 | }
43 |
44 | public static void updateEdgeFeedbackIcon(Bitmap bitmap, boolean oversize) {
45 | if (visualFeedbackView != null) {
46 | visualFeedbackView.updateEdgeFeedbackIcon(bitmap, oversize);
47 | }
48 | }
49 |
50 | public static void clearEdgeFeedback() {
51 | if (visualFeedbackView != null) {
52 | visualFeedbackView.clearEdgeFeedback();
53 | }
54 | }
55 |
56 | public static void startThreeSectionFeedback(float startRawX, float startRawY) {
57 | if (visualFeedbackView != null) {
58 | visualFeedbackView.startThreeSectionFeedback(startRawX, startRawY);
59 | }
60 | }
61 |
62 | public static void updateThreeSectionFeedback(float currentRawX, float currentRawY) {
63 | if (visualFeedbackView != null) {
64 | visualFeedbackView.updateThreeSectionFeedback(currentRawX, currentRawY);
65 | }
66 | }
67 |
68 | public static void updateThreeSectionFeedbackIcon(Bitmap bitmap, boolean oversize) {
69 | if (visualFeedbackView != null) {
70 | visualFeedbackView.updateThreeSectionFeedbackIcon(bitmap, oversize);
71 | }
72 | }
73 |
74 | public static void finishThreeSectionFeedbackIcon() {
75 | if (visualFeedbackView != null) {
76 | visualFeedbackView.finishThreeSectionFeedbackIcon();
77 | }
78 | }
79 |
80 | public static void clearThreeSectionFeedback() {
81 | if (visualFeedbackView != null) {
82 | visualFeedbackView.clearThreeSectionFeedback();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/Memory.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.app.ActivityManager;
4 | import android.content.Context;
5 |
6 | public class Memory {
7 | public int getMemorySizeMB(Context context) {
8 | //获得ActivityManager服务的对象
9 | ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
10 | //获得MemoryInfo对象
11 | ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
12 | //获得系统可用内存,保存在MemoryInfo对象上
13 | mActivityManager.getMemoryInfo(memoryInfo);
14 | return (int) (memoryInfo.totalMem / 1024 / 1024);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/ReceiverLock.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.IntentFilter;
7 | import android.os.Build;
8 | import android.os.Handler;
9 |
10 | /**
11 | * 监听屏幕开关事件
12 | * Created by Hello on 2018/01/23.
13 | */
14 |
15 | public class ReceiverLock extends BroadcastReceiver {
16 | public static int EVENT_SCREEN_OFF = 8;
17 | public static int EVENT_SCREEN_ON = 10;
18 | private static ReceiverLock receiver = null;
19 | private Handler callbacks;
20 |
21 | public ReceiverLock(Handler callbacks) {
22 | this.callbacks = callbacks;
23 | }
24 |
25 | public static ReceiverLock autoRegister(Context context, Handler callbacks) {
26 | if (receiver != null) {
27 | unRegister(context);
28 | }
29 |
30 | receiver = new ReceiverLock(callbacks);
31 | Context bc = context.getApplicationContext();
32 |
33 | bc.registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
35 | bc.registerReceiver(receiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
36 | }
37 | bc.registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
38 | bc.registerReceiver(receiver, new IntentFilter(Intent.ACTION_USER_PRESENT));
39 |
40 | return receiver;
41 | }
42 |
43 | public static void unRegister(Context context) {
44 | if (receiver == null) {
45 | return;
46 | }
47 | context.getApplicationContext().unregisterReceiver(receiver);
48 | receiver = null;
49 | }
50 |
51 | @Override
52 | public void onReceive(final Context p0, Intent p1) {
53 | if (p1 == null) {
54 | return;
55 | }
56 |
57 | String action = p1.getAction();
58 | if (action != null) {
59 | if (action.equals(Intent.ACTION_SCREEN_OFF)) {
60 | callbacks.sendMessage(callbacks.obtainMessage(EVENT_SCREEN_OFF));
61 | // } else if (action.equals(Intent.ACTION_USER_PRESENT) || action.equals(Intent.ACTION_USER_UNLOCKED) || action.equals(Intent.ACTION_SCREEN_ON)) {
62 | } else if (action.equals(Intent.ACTION_USER_PRESENT) || action.equals(Intent.ACTION_USER_UNLOCKED)) {
63 | try {
64 | callbacks.postDelayed(new Runnable() {
65 | @Override
66 | public void run() {
67 | if (!new ScreenState(p0).isScreenLocked()) {
68 | callbacks.sendMessage(callbacks.obtainMessage(EVENT_SCREEN_ON));
69 | }
70 | }
71 | }, 1000);
72 | } catch (Exception ignored) {
73 | }
74 | } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
75 | try {
76 | callbacks.postDelayed(new Runnable() {
77 | @Override
78 | public void run() {
79 | if (!new ScreenState(p0).isScreenLocked()) {
80 | callbacks.sendMessage(callbacks.obtainMessage(EVENT_SCREEN_ON));
81 | }
82 | }
83 | }, 6000);
84 | } catch (Exception ignored) {
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/ReceiverLockHandler.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.accessibilityservice.AccessibilityService;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.view.View;
7 |
8 | public class ReceiverLockHandler extends Handler {
9 | private View bar;
10 | private AccessibilityService accessibilityService;
11 |
12 | public ReceiverLockHandler(View bar, AccessibilityService accessibilityService) {
13 | this.bar = bar;
14 | this.accessibilityService = accessibilityService;
15 | }
16 |
17 | @Override
18 | public void handleMessage(Message msg) {
19 | super.handleMessage(msg);
20 | try {
21 | if (bar.isAttachedToWindow()) {
22 | if (msg != null) {
23 | if (msg.what == ReceiverLock.EVENT_SCREEN_ON) {
24 | bar.setVisibility(View.VISIBLE);
25 | } else if (msg.what == ReceiverLock.EVENT_SCREEN_OFF) {
26 | bar.setVisibility(View.INVISIBLE);
27 | }
28 | }
29 | } else {
30 | ReceiverLock.unRegister(accessibilityService);
31 | }
32 | } catch (Exception ignored) {
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/Recents.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.Intent;
4 |
5 | import java.util.ArrayList;
6 |
7 | public class Recents {
8 | private final ArrayList recents = new ArrayList<>();
9 | // TODO:关闭辅助服务时清理以下数据
10 | // 已经确保可以打开的应用
11 | public ArrayList whiteList = new ArrayList<>();
12 | // 已经可以肯定不是可以打开的应用
13 | public ArrayList blackList = new ArrayList() {
14 | };
15 |
16 | public ArrayList inputMethods = null;
17 | public ArrayList launcherApps = null;
18 | private int index = -1;
19 | private String currentTop = "";
20 |
21 | public void clear() {
22 | synchronized (recents) {
23 | recents.clear();
24 | currentTop = "";
25 | }
26 | }
27 |
28 | public void addRecent(String packageName) {
29 | if (currentTop.equals(packageName)) {
30 | return;
31 | }
32 |
33 | synchronized (recents) {
34 | int searchResult = recents.indexOf(packageName);
35 | if (searchResult > -1) {
36 | recents.remove(searchResult);
37 | }
38 |
39 | // Intent.CATEGORY_HOME 代步桌面应用,回到桌面时,桌面应该永远应用的后面放
40 | // 因此,在桌面上向后退永远是打开桌面前的上一个应用,而不是上上个应用
41 | if (searchResult > -1 && !Intent.CATEGORY_HOME.equals(packageName)) {
42 | recents.add(index, packageName);
43 | } else {
44 | int indexCurrent = recents.indexOf(currentTop);
45 | if (indexCurrent > -1 && indexCurrent + 1 < recents.size()) {
46 | recents.add(indexCurrent + 1, packageName);
47 | } else {
48 | recents.add(packageName);
49 | }
50 | }
51 |
52 | index = recents.indexOf(packageName);
53 | currentTop = packageName;
54 |
55 | StringBuilder packages = new StringBuilder();
56 | for (String item : recents) {
57 | packages.append(item);
58 | packages.append(", ");
59 | }
60 | }
61 | }
62 |
63 | void setRecents(ArrayList items) {
64 | synchronized (recents) {
65 | /*
66 | if (recents.size() < 4) {
67 | recents.clear();
68 | for (String packageName : items) {
69 | if (
70 | whiteList.indexOf(packageName) > -1 ||
71 | (blackList.indexOf(packageName) < 0 && ignoreApps.indexOf(packageName) < 0)
72 | ) {
73 | recents.add(packageName);
74 | }
75 | }
76 | index = recents.indexOf(currentTop);
77 | } else {
78 | ArrayList lostedItems = new ArrayList<>();
79 | for (String recent : recents) {
80 | if (items.indexOf(recent) < 0) {
81 | lostedItems.add(recent);
82 | }
83 | }
84 | recents.removeAll(lostedItems);
85 | index = recents.indexOf(currentTop);
86 | }
87 | */
88 |
89 | ArrayList lostedItems = new ArrayList<>();
90 | for (String recent : recents) {
91 | if (!recent.equals(Intent.CATEGORY_HOME) && items.indexOf(recent) < 0) {
92 | lostedItems.add(recent);
93 | }
94 | }
95 | recents.removeAll(lostedItems);
96 | index = recents.indexOf(currentTop);
97 | }
98 | }
99 |
100 | public boolean notEmpty() {
101 | return this.recents.size() > 1;
102 | }
103 |
104 | String getCurrent() {
105 | return currentTop;
106 | }
107 |
108 | String moveNext() {
109 | String packageName;
110 | synchronized (recents) {
111 | if (index < recents.size() - 1) {
112 | index += 1;
113 | packageName = recents.get(index);
114 | } else if (recents.size() > 0) {
115 | index = 0;
116 | packageName = recents.get(0);
117 | } else {
118 | packageName = null;
119 | }
120 | }
121 | if (Intent.CATEGORY_HOME.equals(packageName) && recents.size() > 1) {
122 | return moveNext();
123 | }
124 | return packageName;
125 | }
126 |
127 | String movePrevious() {
128 | String packageName;
129 | synchronized (recents) {
130 | if (index > 0) {
131 | index -= 1;
132 | packageName = recents.get(index);
133 | } else if (recents.size() > 0) {
134 | int size = recents.size();
135 | index = size - 1;
136 | packageName = recents.get(index);
137 | } else {
138 | packageName = null;
139 | }
140 | }
141 | if (Intent.CATEGORY_HOME.equals(packageName) && recents.size() > 1) {
142 | return movePrevious();
143 | }
144 |
145 | return packageName;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/ResumeNavBar.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.ContentResolver;
4 | import android.provider.Settings;
5 |
6 | public class ResumeNavBar {
7 | private ContentResolver cr = null;
8 |
9 | public ResumeNavBar(ContentResolver contentResolver) {
10 | this.cr = contentResolver;
11 | }
12 |
13 | public void run() {
14 | try {
15 | // oneui 策略取消强制禁用手势(因为锁屏唤醒后底部会触摸失灵,需要重新开关)
16 | Settings.Global.putInt(cr, "navigation_bar_gesture_disabled_by_policy", 0);
17 | } catch (Exception ignored) {
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/ScreenState.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.app.KeyguardManager;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.view.Display;
7 | import android.view.WindowManager;
8 |
9 | public class ScreenState {
10 | private Context context;
11 |
12 | public ScreenState(Context context) {
13 | this.context = context;
14 | }
15 |
16 | public boolean isScreenLocked() {
17 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
18 | Display display = windowManager.getDefaultDisplay();
19 | if (display.getState() == Display.STATE_OFF) {
20 | return true;
21 | }
22 |
23 | KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
25 | return mKeyguardManager.isDeviceLocked() || mKeyguardManager.isKeyguardLocked();
26 | } else {
27 | return mKeyguardManager.inKeyguardRestrictedInputMode() || mKeyguardManager.isDeviceLocked() || mKeyguardManager.isKeyguardLocked();
28 | }
29 | }
30 |
31 | public boolean isScreenOn() {
32 | return !isScreenLocked();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/SystemProperty.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.util.Objects;
6 |
7 | class SystemProperty {
8 | String get(String propName) {
9 | String line;
10 | BufferedReader input = null;
11 | try {
12 | Process p = Runtime.getRuntime().exec("getprop " + propName);
13 | input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
14 | line = input.readLine();
15 | input.close();
16 | p.destroy();
17 | } catch (Exception ex) {
18 | return null;
19 | } finally {
20 | if (input != null) {
21 | try {
22 | input.close();
23 | } catch (Exception ignored) {
24 | }
25 | }
26 | }
27 | return line;
28 | }
29 |
30 | boolean isMiui12() {
31 | try {
32 | // 反射调用私有接口,被Google封杀了
33 | // Object result = Class.forName("android.os.Systemproperties").getMethod("get").invoke(null, "ro.miui.ui.version.name", "");
34 | // return "V12".equals(result.toString());
35 | return Objects.equals(get("ro.miui.ui.version.name"), "V12");
36 | } catch (Exception ex) {
37 | return false;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/omarea/gesture/util/UITools.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture.util;
2 |
3 | import android.content.Context;
4 |
5 | public class UITools {
6 | /**
7 | * dp转换成px
8 | */
9 | public static int dp2px(Context context, float dpValue) {
10 | float scale = context.getResources().getDisplayMetrics().density;
11 | int value = (int) (dpValue * scale + 0.5f);
12 | if (value < 1) {
13 | return 1;
14 | }
15 | return value;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_app_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_app_exit_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_app_open_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
17 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_app_open_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_back_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
15 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_back_home_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
21 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
11 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_enter_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
11 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_enter_basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_enter_fast.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
11 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_exit_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
15 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_exit_basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_next_exit_fast.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
11 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_enter_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
14 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_enter_basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_enter_fast.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
11 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_exit_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_exit_basic.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_prev_exit_fast.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_bottom_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_bottom_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/gesture_quick_panel_right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/adb_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/adb_off.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/adb_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/adb_on.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_alpha_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_bg_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_blue_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_green_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_red_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_picker_seekbar_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/frequently_edit_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_card_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_card_view_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_card_view_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_copy.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_icon_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_icon_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_icon_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_icon_edit.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_icon_ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_icon_ok.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_logo.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_quick_question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_quick_question.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_tab_apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_tab_apple.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_tab_edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_tab_edge.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_tab_lab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_tab_lab.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_tab_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_tab_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gesture_tab_switch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/gesture_tab_switch.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/icon_question.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/landscape_bar_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/power_switch_off.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/power_switch_on.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/power_switch_style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/quick_panel_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/quick_panel_bg_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/quick_panel_bg_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/quick_panel_bg_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_progress_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
13 |
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekbar_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_track.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_track_close.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_track_open.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_app.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_app_window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_app_window.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_arrow_left.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_arrow_right.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_grid.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_home.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_info.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_jump_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_jump_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_jump_previous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_jump_previous.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_lock.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_notice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_notice.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_power.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_power.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_screenshot.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_settings.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_shell.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_split.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_split.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_switch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_switch.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_tasks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_tasks.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/touch_window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/app/src/main/res/drawable/touch_window.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/enhanced_mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
26 |
27 |
30 |
31 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
57 |
58 |
63 |
64 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_color_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
21 |
22 |
27 |
28 |
39 |
40 |
41 |
45 |
46 |
51 |
52 |
63 |
64 |
65 |
66 |
70 |
71 |
76 |
77 |
88 |
89 |
90 |
94 |
95 |
100 |
101 |
112 |
113 |
114 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_fw_ios_touch_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_fw_three_section.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_fw_vitual_touch_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_layout_action_option.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_layout_app_option.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_layout_app_option2.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
25 |
26 |
34 |
35 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_layout_ex_shell.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_layout_quick_panel_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
20 |
21 |
30 |
31 |
35 |
36 |
40 |
41 |
45 |
46 |
50 |
51 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/gesture_switch_options.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
29 |
30 |
31 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_enhanced_mode_guide.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_frequently_app_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
22 |
23 |
33 |
34 |
35 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_quick_panel.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
18 |
19 |
27 |
28 |
38 |
39 |
47 |
48 |
56 |
57 |
58 |
67 |
68 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_quick_panel_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_quick_panel_landscape.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
21 |
22 |
30 |
31 |
41 |
42 |
50 |
51 |
59 |
60 |
61 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #BC8DE4
4 | #BC8DE4
5 | #BC8DE4
6 | #ff000000
7 | #ffeeeeee
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - android
5 | - com.android.systemui
6 | - com.miui.home
7 | - com.miui.freeform
8 | - com.miui.touchassistant
9 | - com.miui.contentextension
10 | - com.miui.systemAdSolution
11 | - com.miui.securitycenter
12 | - com.omarea.filter
13 | - com.omarea.gesture
14 | - com.zbar.lib
15 | - eu.chainfire.supersu
16 | - dev.nick.app.screencast
17 | - eu.chainfire.perfmon
18 | - com.c4x.roundcorner
19 | - com.sohu.inputmethod.sogou.xiaomi
20 | - com.sohu.inputmethod.sogou
21 | - com.tencent.gamehelper.smoba
22 | - com.miui.systemadsolution
23 | - com.waterdaaan.cpufloat
24 | - com.miui.contentextension
25 | - com.miui.systemAdSolution
26 | - com.sec.app.screenrecorder
27 | - com.cyngn.screencast
28 | - com.lbe.security.miui
29 | - com.bst.airmessage
30 | - com.gamebench.metricscollector
31 | - com.samsung.android.game.gametools
32 | - com.samsung.android.app.cocktailbarservice
33 | - com.samsung.android.app.assistantmenu
34 | - com.samsung.android.app.aodservice
35 | - com.samsung.android.MtpApplication
36 | - com.android.vpndialogs
37 | - com.android.documentsui
38 | - com.android.wallpapercropper
39 | - com.mfashiongallery.emag
40 | - com.miui.aod
41 | - com.huawei.vassistant
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8dp
4 | 90dp
5 | 20dp
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Gesture
3 | Gesture(手势导航)
4 |
5 | 开启此辅助服务即可体验屏幕边缘手,如需个性化手势功能,请点击界面上的设置按钮。
6 |
7 | 启用手势导航
8 | 隐藏桌面入口
9 | 打开此开关后,本应用将从桌面隐藏,如果需要再恢复请到辅助服务界面,选中本应用进行操作
10 | 窗口(前台应用)监测
11 | 若无需使用[上个应用\下个应用]动作和小横条[自动变色]功能,可关闭此项减少性能损耗
12 | 你已关闭[窗口检测],应用切换功能无法正常工作~
13 | 关闭视觉反馈动效
14 | com.omarea.gesture.ConfigChanged
15 | com.omarea.gesture.AdbProcess
16 | com.omarea.gesture.AppSwitchChanged
17 | com.omarea.gesture.ServiceDisable
18 | 确定
19 | 取消
20 | 选择动作响应
21 | 请重复手势~
22 | 请手动去系统的“设置”-“无障碍”中激活
23 | 按“返回键”从多任务界面隐藏本应用
24 | 复制成功
25 | 复制失败
26 | 小横条手势
27 | 底边手势
28 | 右边手势
29 | 三段手势
30 | 左边手势
31 | 行为
32 | 滑动悬停
33 | 快速滑动
34 | 热区高度
35 | 热区宽度
36 | 竖屏
37 | 横屏
38 | 选择动画
39 | 返回桌面动画
40 | 应用切换动画
41 | 选择应用
42 | 默认动画
43 | 定制动画1
44 | 定制动画2
45 | 使用非[默认动画],需要授予本应用[后台运行,后台弹出界面]权限,否则可能操作无反应
46 | 横屏防误触
47 | 使用ROOT激活增强模式
48 | 未能获得ROOT权限
49 | 请先激活“增强模式”!
50 | 简易手势
51 | 小横条手势
52 | 底边三段式
53 | 其它设置
54 | 基础设置
55 | 输入自定义的脚本内容,最多可输入1024个字符。 如需执行大量脚本代码,请自行存储为文件,并通过本应用调用!
56 | 自定义脚本
57 | 自定义应用
58 | 排除应用
59 | 该功能还未完成,敬请期待!
60 | 添加
61 | 保存成功
62 | 保存失败
63 | \n单击全屏打开应用\n长按窗口化打开应用\n窗口化仅支持部分系统
64 | 跳过切换
65 | 避免通过[上个应用/下个应用]手势切换到这些应用
66 | 确定
67 | 使用遇到问题?点我
68 | 增强模式向导
69 | 增强模式
70 | 激活增强模式,可解决以下问题:\n①切换应用时会打开已清除的后台;\n②小横条不会自动反转颜色;\n③回桌面后切换应用5秒延迟;\n\n点击右侧图标查看激活代码
71 | 手势视觉反馈颜色
72 | 小横条阴影颜色
73 | 小横条描边颜色
74 | 横屏小横条颜色
75 | 竖屏小横条颜色
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/xml-v24/keyevent_accessibility.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/keyevent_accessibility.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/test/java/com/omarea/gesture/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.omarea.gesture;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.21'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:4.1.1'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | // maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
17 | maven {
18 | url 'https://jitpack.io'
19 | }
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/color-polling-apps.txt:
--------------------------------------------------------------------------------
1 | com.ss.android.ugc.aweme
--------------------------------------------------------------------------------
/docs/EnhancedMode.md:
--------------------------------------------------------------------------------
1 | ## 准备工作
2 | - 一台电脑
3 | - 一条数据线
4 | - 以下是图文教程(如果看不到图片,可以尝试科学上网,或者更换不同运营商的网络)
5 |
6 | ### 1. 激活开发者设置
7 | - 在系统设置里连续点击系统版本(软件版本,不是Android版本),直到提示开发者模式已激活
8 | - 在系统设置里找到开发者选项,并勾选【USB调试】
9 |
10 | > 下图以MIUI为例,其它UI可能有所不同,但基本类似
11 |
12 | 
13 | 
14 |
15 | ### 2. 获得电脑上的ADB工具
16 | > 此处以Windows为例,但不仅限于Windows
17 |
18 | - 首先,你得下载`platform-tools`(如果你有其他手机助手软件附带ADB工具,也可以直接使用)
19 | - 下载[platform-tools](https://omarea.lanzous.com/iDi6Teongtg),`并解压到电脑上`
20 | - 双点击解压目录下的 `打开CMD命令行.bat` 打开ADB命令窗口
21 |
22 | 
23 |
24 | ### 3. 执行命令
25 | - 点击**Gesture**增强模式右侧的机器人小图标,出现激活提示弹窗后,插上数据线连接电脑
26 | - 复制激活命令
27 | ```sh
28 | adb -d shell sh /storage/emulated/0/Android/data/com.omarea.gesture/cache/up.sh
29 | ```
30 | - 并在命令行窗口中点击鼠标右键粘贴代码,并按下回车键
31 |
32 | - 如果你的手机是首次和电脑连接,会出现授权提示,此时需要你在手机上点击确认
33 | - 确认完之后,你可能需要重复刚刚的动作
34 | - 如果你小心误操作错过了手机上弹出的授权窗口。你是新手的话,建议重启手机和电脑从头再来一次。经验丰富的老鸟随意。
35 | - 总之,如果激命令执行成功后,Gesture主页的机器人图标会变成绿色
36 |
37 |
38 | 
39 |
40 | ### 4. 疑难问题
41 | - 拔掉数据线增强模式就失效了?
42 | > 这的确是个难以解决的问题,在Oreo+系统上极容易出现。
43 | > 有网友建议,手机插上电脑后,把连接模式改成“仅充电”,再执行代码。
44 |
45 |
46 | ### 其它
47 | - 如果我说的不是很清楚,也没有关系,问问你身边有没有高手
48 | - 让他们帮帮你也是很简单的
--------------------------------------------------------------------------------
/docs/FAQ.md:
--------------------------------------------------------------------------------
1 | #### FAQ
2 |
3 | > 用Home键回到桌面后,通过手势切换应用会延迟 5 秒
4 | - 这是Google对第三方后台应用的限制无法规避,可尝试将动画模式换成“定制动画”
5 |
6 | > 应用切换手势没反应
7 | - 例如 Xiaomi's MIUI,需要授予“后台弹出界面”权限才能正常使用,其它系统类似
8 |
9 | > 通过手势切换应用会重新打开关闭的应用
10 | - 系统不让第三方程序获取应用后台状态,如果你已经ROOT,可尝试打开“ROOT增强”选项
11 |
12 | > 感觉手势响应有延迟
13 | - 因为分配给后台程序的CPU资源较少,如果你有ROOT权限,可尝试复制本程序到System目录
14 |
15 | > 手机重启后不会自动自动开启手势,或者经常自动关闭
16 | - 检查系统的 自启动管理、后台检查、内存管理、省电优化、游戏加速 等功能,将应用添加到白名单
17 |
18 | > 使用定制动画时“返回桌面”不彻底
19 | - 因为的确不是模拟Home键点击,而是直接打开了桌面,当然也是为了规避常见问题第一条
20 |
--------------------------------------------------------------------------------
/docs/adb_shell.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/docs/adb_shell.jpg
--------------------------------------------------------------------------------
/docs/dev-settings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/docs/dev-settings.jpg
--------------------------------------------------------------------------------
/docs/dev-settings2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/docs/dev-settings2.jpg
--------------------------------------------------------------------------------
/docs/shell_window.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/docs/shell_window.jpg
--------------------------------------------------------------------------------
/docs/success.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/docs/success.jpg
--------------------------------------------------------------------------------
/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 | android.enableJetifier=true
10 | android.useAndroidX=true
11 | org.gradle.jvmargs=-Xmx1536m
12 | # When configured, Gradle will run in incubating parallel mode.
13 | # This option should only be used with decoupled projects. More details, visit
14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
15 | # org.gradle.parallel=true
16 |
17 |
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helloklf/EdgeGesture/fca8d3aaa9552744161eccf582d386802d3d496d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Nov 13 15:35:04 GMT+08:00 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------