├── .gitignore ├── .idea ├── caches │ └── gradle_models.ser ├── codeStyles │ └── Project.xml ├── dictionaries │ └── zhipingne.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── XposedUtil ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── tvcfish │ │ └── xposed │ │ └── util │ │ ├── XHelper.java │ │ └── XLog.java │ └── res │ └── values │ └── strings.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── tvcfish │ │ └── xposed │ │ └── aidehelper │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── litepal.xml │ │ ├── templates │ │ │ ├── AIDEWebSamples.zip │ │ │ ├── HelloJavaScript.zip │ │ │ ├── PhoneGapAppNew.zip │ │ │ └── WebsiteBootstrap.zip │ │ └── xposed_init │ ├── java │ │ └── me │ │ │ └── tvcfish │ │ │ └── xposed │ │ │ └── aidehelper │ │ │ ├── activity │ │ │ └── MainActivity.java │ │ │ ├── hook │ │ │ ├── ActionBarIcon.java │ │ │ ├── AutoCompletion.java │ │ │ ├── AutoRotate.java │ │ │ ├── EnabledHookModel.java │ │ │ ├── GradleCompletionExpand.java │ │ │ ├── HookInit.java │ │ │ ├── SearchPage.java │ │ │ ├── SwitchVersion.java │ │ │ ├── SymbolBar.java │ │ │ └── UnlockPremium.java │ │ │ ├── model │ │ │ └── MethodCompletion.java │ │ │ ├── provider │ │ │ └── DBProvider.java │ │ │ └── util │ │ │ ├── ConversionUtil.java │ │ │ ├── FileUtil.java │ │ │ └── TranslateUtil.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── alipay.jpg │ │ ├── ic_launcher_background.xml │ │ └── wechat.jpg │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ └── update_log │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── main_preference.xml │ └── test │ └── java │ └── me │ └── tvcfish │ └── xposed │ └── aidehelper │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image-1.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | /app/release 13 | -------------------------------------------------------------------------------- /.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/dictionaries/zhipingne.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gmail 5 | zhipingne 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 40 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 zhiping 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub All Releases](https://img.shields.io/github/downloads/ikws4/AideHelper/total) 2 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/ikws4/AideHelper) 3 | ![GitHub](https://img.shields.io/github/license/ikws4/AideHelper) 4 | 5 | ## 简介 6 | 一款专门为AIDE量身打造的Xposed插件,提供个性化选择。 7 | 8 | 如果你在VirtualXposed环境下打开AIDE很慢,那么去清除VirtualXPosed的数据,在重新使用就好多了 9 | 10 | ## 关于翻译功能失效 11 | 1. 去[搜狗深智引擎](https://deepi.sogou.com/)申请api 12 | 2. 替换下方的pid和key就好了[TranslateUtil.java](https://github.com/ikws4/AideHelper/blob/master/app/src/main/java/me/tvcfish/xposed/aidehelper/util/TranslateUtil.java) 13 | 14 | 15 | ## 功能介绍 16 | 17 | - 解锁专业版 18 | 19 | - 禁用自动旋转 20 | 21 | - 符号栏调整 22 | 23 | - 搜索结果界面调整 24 | 25 | - 去除Aide的icon 26 | 27 | - 中文补全 28 | 29 | - Gradle补全拓展 30 | 31 | - 版本切换 32 | 33 | ## 下载 34 | 35 | [CoolApk](https://www.coolapk.com/apk/me.tvcfish.xposed.aidehelper) 36 | 37 | [release](https://github.com/TvcFish/AideHelper/releases) 38 | -------------------------------------------------------------------------------- /XposedUtil/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /XposedUtil/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | 6 | defaultConfig { 7 | minSdkVersion 15 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation 'androidx.annotation:annotation:1.0.1' 28 | 29 | //xposed 30 | compileOnly 'de.robv.android.xposed:api:82' 31 | } 32 | -------------------------------------------------------------------------------- /XposedUtil/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 | -------------------------------------------------------------------------------- /XposedUtil/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /XposedUtil/src/main/java/me/tvcfish/xposed/util/XHelper.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.util; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findClassIfExists; 4 | 5 | import android.annotation.SuppressLint; 6 | import android.app.Activity; 7 | import androidx.annotation.NonNull; 8 | import de.robv.android.xposed.XSharedPreferences; 9 | import de.robv.android.xposed.XposedHelpers; 10 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; 11 | import java.io.File; 12 | import java.lang.ref.WeakReference; 13 | import java.lang.reflect.Field; 14 | 15 | /** 16 | * Xposed辅助类 17 | * 18 | * @date: 2019/2/23 19 | * @author: TvcFish 20 | * @email: zhipingne@gmail.com 21 | */ 22 | public class XHelper { 23 | 24 | private static LoadPackageParam sLoadPackageParam; 25 | //配置参数 26 | private static WeakReference xSharedPreferences = new WeakReference<>(null); 27 | //包名 28 | private static String sAppPackageName; 29 | 30 | /** 31 | * 初始化操作 32 | * 33 | * @param loadPackageParam 用来加载类 34 | */ 35 | public static void init(@NonNull LoadPackageParam loadPackageParam,String appPackageName) { 36 | sLoadPackageParam = loadPackageParam; 37 | sAppPackageName = appPackageName; 38 | } 39 | 40 | /** 41 | * 获取ClassLoader 42 | * 43 | * @return ClassLoader 44 | * @throws NullPointerException 如果sLoadPackageParam为空,那么抛出一个异常,提示调用init方法后在调用此方法 45 | */ 46 | private static ClassLoader getClassLoader() throws NullPointerException { 47 | if (sLoadPackageParam == null) { 48 | throw new NullPointerException( 49 | "loadPackageParam is null, please invoked init method, then use the method."); 50 | } else { 51 | return sLoadPackageParam.classLoader; 52 | } 53 | } 54 | 55 | /** 56 | * 获取Class 57 | * 58 | * @param name 类的路径 59 | * @return Class 60 | */ 61 | public static Class findClass(String name) { 62 | return XposedHelpers.findClassIfExists(name, getClassLoader()); 63 | } 64 | 65 | /** 66 | * 创建一个实例 67 | * 68 | * @param className 类名 69 | * @param args 类参数 70 | * @return Object 71 | */ 72 | public static Object newInstance(String className, Object... args) { 73 | return XposedHelpers.newInstance(findClass(className), args); 74 | } 75 | 76 | /** 77 | * 调用静态方法 78 | * 79 | * @param className 类名 80 | * @param methodName 方法名 81 | * @param args 参数 82 | * @return Object 83 | */ 84 | public static Object callStaticMethod(String className, String methodName, Object... args) { 85 | return XposedHelpers.callStaticMethod(findClass(className), methodName, args); 86 | } 87 | 88 | /** 89 | * 获取Filed 90 | * 91 | * @param className 类名 92 | * @param name filed的名字 93 | * @return Filed 94 | */ 95 | public static Field getField(String className, String name) throws NoSuchFieldException { 96 | Class clazz = findClassIfExists(className, getClassLoader()); 97 | Field field = clazz.getField(name); 98 | field.setAccessible(true); 99 | return field; 100 | } 101 | 102 | /** 103 | * 获取Filed 104 | * 105 | * @param clazz Filed所在的类 106 | * @param name filed的名字 107 | * @return Filed 108 | */ 109 | public static Field getField(Class clazz, String name) throws NoSuchFieldException { 110 | Field field = clazz.getField(name); 111 | field.setAccessible(true); 112 | return field; 113 | } 114 | 115 | /** 116 | * 获取SharedPreferences 117 | * 118 | * @return preferences 119 | */ 120 | public static XSharedPreferences getSharedPreferences() { 121 | XSharedPreferences preferences = xSharedPreferences.get(); 122 | if (preferences == null) { 123 | preferences = new XSharedPreferences(sAppPackageName); 124 | preferences.makeWorldReadable(); 125 | preferences.reload(); 126 | xSharedPreferences = new WeakReference<>(preferences); 127 | } else { 128 | preferences.reload(); 129 | } 130 | return preferences; 131 | } 132 | 133 | /** 134 | * 使shared_prefs文件夹下所以preferences文件可读 135 | * 136 | * @param activity 用来获取App内置存储路径 137 | */ 138 | @SuppressLint("SetWorldReadable") 139 | public static void setPreferencesReadable(Activity activity) { 140 | File dataDir = new File(activity.getApplicationInfo().dataDir); 141 | File prefsDir = new File(dataDir, "shared_prefs"); 142 | File[] arrayOfFiles = prefsDir.listFiles(); 143 | for (File prefsFile : arrayOfFiles) { 144 | if (prefsFile.exists()) { 145 | for (File file : new File[]{dataDir, prefsDir, prefsFile}) { 146 | file.setReadable(true, false); 147 | file.setExecutable(true, false); 148 | } 149 | } 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /XposedUtil/src/main/java/me/tvcfish/xposed/util/XLog.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.util; 2 | 3 | import de.robv.android.xposed.XposedBridge; 4 | 5 | /** 6 | * 对XposedBridge.log的封住 7 | * 8 | * @date: 2019/2/23 9 | * @author: TvcFish 10 | * @email: zhipingne@gmail.com 11 | */ 12 | public class XLog { 13 | 14 | /** 15 | * 打印日志 16 | * 17 | * @param tag TAG 18 | * @param message 打印信息 19 | */ 20 | public static void show(String tag, String message) { 21 | //如果是release,则不打印 22 | if (!BuildConfig.DEBUG) { 23 | XposedBridge.log(tag + "->" + message); 24 | } 25 | } 26 | 27 | /** 28 | * 打印日志 29 | * 30 | * @param tag TAG 31 | * @param message 打印异常信息 32 | */ 33 | public static void show(String tag, Throwable message) { 34 | //如果是release,则不打印 35 | if (!BuildConfig.DEBUG) { 36 | XposedBridge.log(tag + "->" + message); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /XposedUtil/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | XposedUtil 3 | 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | signingConfigs { 5 | } 6 | compileSdkVersion 28 7 | defaultConfig { 8 | applicationId "me.tvcfish.xposed.aidehelper" 9 | minSdkVersion 15 10 | targetSdkVersion 28 11 | versionCode 11002 12 | versionName "1.2" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(include: ['*.jar'], dir: 'libs') 25 | implementation 'androidx.annotation:annotation:1.0.1' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'androidx.test:runner:1.1.1' 28 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 29 | //捐赠 30 | implementation 'com.canking.minipay:minipay:1.0.5' 31 | //网络 32 | implementation 'com.squareup.okhttp3:okhttp:3.12.1' 33 | //数据库 34 | implementation 'org.litepal.android:java:3.0.0' 35 | //xposed 36 | compileOnly 'de.robv.android.xposed:api:82' 37 | 38 | implementation project(':XposedUtil') 39 | } 40 | 41 | afterEvaluate { 42 | installDebug.doLast { 43 | updateVirtualXposedAPP.execute() 44 | rebootVirtualXposedAPP.execute() 45 | launchVirtualXposedAPP.execute() 46 | } 47 | } 48 | // 更新 VXP 中的 app 49 | task updateVirtualXposedAPP(type: Exec) { 50 | def pkg = android.defaultConfig.applicationId 51 | commandLine android.adbExecutable, 'shell', 'am', 'broadcast', '-a', 'io.va.exposed.CMD', '-e', 'cmd', 'update', '-e', 'pkg', pkg 52 | } 53 | // 重启 VXP 54 | task rebootVirtualXposedAPP(type: Exec) { 55 | commandLine android.adbExecutable, 'shell', 'am', 'broadcast', '-a', 'io.va.exposed.CMD', '-e', 'cmd', 'reboot' 56 | } 57 | // 重启 VXP 需要 hook 的 APP,需要知道它的包名 58 | task launchVirtualXposedAPP(type: Exec) { 59 | def pkg = 'com.aide.ui'// 需要 hook 的 app 60 | commandLine android.adbExecutable, 'shell', 'am', 'broadcast', '-a', 'io.va.exposed.CMD', '-e', 'cmd', 'launch', '-e', 'pkg', pkg 61 | } -------------------------------------------------------------------------------- /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/me/tvcfish/xposed/aidehelper/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("me.tvcfish.xposed.aidepro", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 15 | 18 | 21 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/assets/litepal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/assets/templates/AIDEWebSamples.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/assets/templates/AIDEWebSamples.zip -------------------------------------------------------------------------------- /app/src/main/assets/templates/HelloJavaScript.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/assets/templates/HelloJavaScript.zip -------------------------------------------------------------------------------- /app/src/main/assets/templates/PhoneGapAppNew.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/assets/templates/PhoneGapAppNew.zip -------------------------------------------------------------------------------- /app/src/main/assets/templates/WebsiteBootstrap.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/assets/templates/WebsiteBootstrap.zip -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | me.tvcfish.xposed.aidehelper.hook.HookInit -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.AlertDialog; 5 | import android.content.ActivityNotFoundException; 6 | import android.content.ContentResolver; 7 | import android.content.Context; 8 | import android.content.DialogInterface; 9 | import android.content.DialogInterface.OnClickListener; 10 | import android.content.Intent; 11 | import android.content.SharedPreferences; 12 | import android.content.SharedPreferences.Editor; 13 | import android.net.Uri; 14 | import android.os.Bundle; 15 | import android.preference.Preference; 16 | import android.preference.PreferenceActivity; 17 | import android.preference.PreferenceScreen; 18 | import android.widget.Toast; 19 | import com.canking.minipay.Config; 20 | import com.canking.minipay.MiniPayUtils; 21 | import java.io.File; 22 | import me.tvcfish.xposed.aidehelper.BuildConfig; 23 | import me.tvcfish.xposed.aidehelper.R; 24 | import me.tvcfish.xposed.aidehelper.util.FileUtil; 25 | 26 | @SuppressLint("ExportedPreferenceActivity") 27 | public class MainActivity extends PreferenceActivity { 28 | 29 | private boolean isEnable; 30 | private Context mContext; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | init(); 36 | addPreferencesFromResource(R.xml.main_preference); 37 | setWorldReadable(); 38 | updateLogDialog(false); 39 | FileUtil.copyAssetsFileToSdcard(this, "templates"); 40 | } 41 | 42 | /** 43 | * 初始化操作 44 | */ 45 | private void init() { 46 | mContext = this; 47 | isEnable = isExpModuleActive(this); 48 | // assets/templates文件夹创建 49 | FileUtil.mkdirs(FileUtil.getExternalFilesDirPath(this) + "/assets/templates"); 50 | } 51 | 52 | 53 | @Override 54 | public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 55 | switch (preference.getKey()) { 56 | case "donation": 57 | Config config = new Config.Builder("FKX03835LYVF3XNJFBLVB0", R.drawable.alipay, 58 | R.drawable.wechat) 59 | .build(); 60 | MiniPayUtils.setupPay(this, config); 61 | break; 62 | case "update_log": 63 | updateLogDialog(true); 64 | break; 65 | } 66 | return super.onPreferenceTreeClick(preferenceScreen, preference); 67 | } 68 | 69 | /** 70 | * 更新日志对话框 71 | * 72 | * @param isShow 是否 直接显示(false就按versionCode进行判断) 73 | */ 74 | private void updateLogDialog(boolean isShow) { 75 | 76 | final SharedPreferences sharedPreferences = getSharedPreferences("app_version", 77 | Context.MODE_PRIVATE); 78 | int versionCode = sharedPreferences.getInt("versionCode", 10000); 79 | 80 | if (BuildConfig.VERSION_CODE > versionCode || isShow) { 81 | //读取raw下的update_log文件 82 | String updateLog = FileUtil.readTextFromRaw(this, R.raw.update_log); 83 | 84 | //对话框 85 | new AlertDialog.Builder(this) 86 | .setTitle(R.string.pref_update_log) 87 | .setMessage(updateLog) 88 | .setCancelable(false) 89 | .setNegativeButton(R.string.app_ok, new OnClickListener() { 90 | @Override 91 | public void onClick(DialogInterface dialog, int which) { 92 | Editor editor = sharedPreferences.edit(); 93 | editor.putInt("versionCode", BuildConfig.VERSION_CODE); 94 | editor.apply(); 95 | //判断是否开启模块,使用Hook改变方法内容 96 | showNoEnableDialog(isEnable); 97 | } 98 | }) 99 | .show(); 100 | } else { 101 | //判断是否开启模块,使用Hook改变方法内容 102 | showNoEnableDialog(isEnable); 103 | } 104 | 105 | } 106 | 107 | /** 108 | * 判断模块是否开启 109 | */ 110 | private boolean isExpModuleActive(Context context) { 111 | 112 | boolean isExp = false; 113 | if (context == null) { 114 | throw new IllegalArgumentException("context must not be null!!"); 115 | } 116 | 117 | try { 118 | ContentResolver contentResolver = context.getContentResolver(); 119 | Uri uri = Uri.parse("content://me.weishu.exposed.CP/"); 120 | Bundle result = null; 121 | try { 122 | result = contentResolver.call(uri, "active", null, null); 123 | } catch (RuntimeException e) { 124 | // TaiChi is killed, try invoke 125 | try { 126 | Intent intent = new Intent("me.weishu.exp.ACTION_ACTIVE"); 127 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 128 | context.startActivity(intent); 129 | } catch (Throwable e1) { 130 | return false; 131 | } 132 | } 133 | if (result == null) { 134 | result = contentResolver.call(uri, "active", null, null); 135 | } 136 | 137 | if (result == null) { 138 | return false; 139 | } 140 | isExp = result.getBoolean("active", false); 141 | } catch (Throwable ignored) { 142 | } 143 | return isExp; 144 | } 145 | 146 | /** 147 | * 判断是否开启模块,使用Hook改变方法内容 EnabledHookModel.java 148 | */ 149 | private void showNoEnableDialog(boolean isEnable) { 150 | if (isEnable) { 151 | return; 152 | } 153 | new AlertDialog.Builder(this) 154 | .setTitle(R.string.main_activity_hook_dialog_title) 155 | .setMessage(R.string.main_activity_hook_dialog_message) 156 | .setCancelable(false) 157 | .setPositiveButton(R.string.app_get_vxp, new OnClickListener() { 158 | @Override 159 | public void onClick(DialogInterface dialog, int which) { 160 | try { 161 | Intent intent = getPackageManager().getLaunchIntentForPackage("io.va.exposed"); 162 | startActivity(intent); 163 | } catch (ActivityNotFoundException e) { 164 | Toast.makeText(mContext, "VXP未安装", Toast.LENGTH_SHORT).show(); 165 | Uri uri = Uri.parse("https://github.com/android-hacker/VirtualXposed/releases"); 166 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 167 | startActivity(intent); 168 | } 169 | finish(); 170 | } 171 | }) 172 | .setNegativeButton(R.string.app_get_taici, new OnClickListener() { 173 | @Override 174 | public void onClick(DialogInterface dialog, int which) { 175 | Intent t = new Intent("me.weishu.exp.ACTION_MODULE_MANAGE"); 176 | t.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID)); 177 | t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 178 | try { 179 | startActivity(t); 180 | } catch (ActivityNotFoundException e) { 181 | // TaiChi not installed. 182 | Toast.makeText(mContext, "太极未安装", Toast.LENGTH_SHORT).show(); 183 | Uri uri = Uri.parse("https://github.com/taichi-framework/TaiChi/releases"); 184 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 185 | startActivity(intent); 186 | } 187 | finish(); 188 | } 189 | }).show(); 190 | } 191 | 192 | /** 193 | * 把SharedPreferences数据设置为公开 194 | */ 195 | @SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) 196 | @SuppressLint({"SetWorldReadable", "WorldReadableFiles"}) 197 | private void setWorldReadable() { 198 | File dataDir = new File(getApplicationInfo().dataDir); 199 | File prefsDir = new File(dataDir, "shared_prefs"); 200 | File prefsFile = new File(prefsDir, BuildConfig.APPLICATION_ID + "_preferences.xml"); 201 | if (prefsFile.exists()) { 202 | for (File file : new File[]{dataDir, prefsDir, prefsFile}) { 203 | file.setReadable(true, false); 204 | file.setExecutable(true, false); 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/ActionBarIcon.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | import de.robv.android.xposed.XC_MethodHook; 8 | import me.tvcfish.xposed.util.XHelper; 9 | 10 | enum ActionBarIcon { 11 | 12 | INSTANCE; 13 | 14 | /** 15 | * 开始Hook 16 | */ 17 | public void startHook() { 18 | if (!isOpen()) { 19 | return; 20 | } 21 | hookTarget(); 22 | } 23 | 24 | /** 25 | * 是否开启此功能 26 | * 27 | * @return boolean 28 | */ 29 | private boolean isOpen() { 30 | return XHelper.getSharedPreferences().getBoolean("action_bar_icon", false); 31 | } 32 | 33 | /** 34 | * Hook代码实现 35 | */ 36 | private void hookTarget() { 37 | Class clazz = XHelper.findClass("com.aide.ui.MainActivity"); 38 | findAndHookMethod(clazz, "onCreate", Bundle.class, new XC_MethodHook() { 39 | 40 | @Override 41 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 42 | super.afterHookedMethod(param); 43 | Activity activity = (Activity) param.thisObject; 44 | activity.getActionBar().setDisplayShowHomeEnabled(false); 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/AutoCompletion.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.callMethod; 4 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 5 | import static de.robv.android.xposed.XposedHelpers.getStaticObjectField; 6 | 7 | import android.annotation.SuppressLint; 8 | import android.app.Activity; 9 | import android.app.AlertDialog; 10 | import android.content.DialogInterface; 11 | import android.content.DialogInterface.OnClickListener; 12 | import android.graphics.Color; 13 | import android.net.Uri; 14 | import android.os.Build.VERSION_CODES; 15 | import android.os.Bundle; 16 | import android.view.Gravity; 17 | import android.view.LayoutInflater; 18 | import android.view.Menu; 19 | import android.view.MenuItem; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.AdapterView; 23 | import android.widget.ArrayAdapter; 24 | import android.widget.EditText; 25 | import android.widget.ImageView; 26 | import android.widget.LinearLayout; 27 | import android.widget.LinearLayout.LayoutParams; 28 | import android.widget.ListView; 29 | import android.widget.PopupMenu; 30 | import android.widget.PopupMenu.OnMenuItemClickListener; 31 | import android.widget.TextView; 32 | import android.widget.TextView.BufferType; 33 | import androidx.annotation.RequiresApi; 34 | import de.robv.android.xposed.XC_MethodHook; 35 | import de.robv.android.xposed.XC_MethodReplacement; 36 | import de.robv.android.xposed.XposedHelpers; 37 | import me.tvcfish.xposed.aidehelper.model.MethodCompletion; 38 | import me.tvcfish.xposed.aidehelper.provider.DBProvider; 39 | import me.tvcfish.xposed.aidehelper.util.ConversionUtil; 40 | import me.tvcfish.xposed.aidehelper.util.TranslateUtil; 41 | import me.tvcfish.xposed.util.XHelper; 42 | import me.tvcfish.xposed.util.XLog; 43 | 44 | enum AutoCompletion { 45 | 46 | @SuppressLint("StaticFieldLeak") 47 | INSTANCE; 48 | 49 | //MainActivity 50 | private Activity mContext; 51 | //TAG 52 | private static final String TAG = "AutoCompletion"; 53 | 54 | /** 55 | * 开始Hook 56 | */ 57 | public void startHook() { 58 | if (!isOpen()) { 59 | return; 60 | } 61 | //获取上下文 62 | getContext(); 63 | 64 | hookArrayAdapter(); 65 | 66 | hookItemLongClick(); 67 | } 68 | 69 | /** 70 | * 获取上下文 71 | */ 72 | private void getContext() { 73 | Class clazz = XHelper.findClass("com.aide.ui.MainActivity"); 74 | findAndHookMethod(clazz, "onCreate", Bundle.class, new XC_MethodHook() { 75 | @Override 76 | protected void beforeHookedMethod(MethodHookParam param) { 77 | mContext = (Activity) param.thisObject; 78 | } 79 | }); 80 | } 81 | 82 | /** 83 | * 判断是否开启中文补全功能 84 | * 85 | * @return boolean 86 | */ 87 | private boolean isOpen() { 88 | return XHelper.getSharedPreferences().getBoolean("chinese_completion", true); 89 | } 90 | 91 | /** 92 | * 注入翻译代码 93 | */ 94 | private void hookArrayAdapter() { 95 | //主要目标Class 96 | Class clazz = XHelper.findClass("com.aide.ui.a$a"); 97 | 98 | //重写整个getView方法 99 | findAndHookMethod(clazz, "getView", int.class, View.class, ViewGroup.class, 100 | new XC_MethodReplacement() { 101 | @SuppressLint({"ResourceType", "SetTextI18n"}) 102 | @Override 103 | protected Object replaceHookedMethod(MethodHookParam param) { 104 | ArrayAdapter arrayAdapter = (ArrayAdapter) param.thisObject; 105 | int position = (int) param.args[0]; 106 | 107 | View view = (View) param.args[1]; 108 | ViewGroup viewGroup = (ViewGroup) param.args[2]; 109 | 110 | if (view == null) { 111 | view = LayoutInflater.from(arrayAdapter.getContext()) 112 | .inflate(0x7f0a0008, viewGroup, false); 113 | } 114 | //转换成SourceEntity 115 | Object sourceEntity = arrayAdapter.getItem(position); 116 | //是否可见 117 | int visibility = View.GONE; 118 | 119 | if (sourceEntity == null) { 120 | TextView textView = view.findViewById(0x7f080025); 121 | ImageView imageView = view.findViewById(0x7f080024); 122 | view.findViewById(0x7f080026).setVisibility(visibility); 123 | textView.setText("No matches"); 124 | imageView.setImageResource(0x7f070011); 125 | } else { 126 | TextView textView = view.findViewById(0x7f080025); 127 | String J8 = (String) callMethod(sourceEntity, "J8"); 128 | String XL = (String) callMethod(sourceEntity, "XL"); 129 | String we = (String) callMethod(sourceEntity, "we"); 130 | 131 | //5.j6[sourceEntity.DW().ordinal()] 132 | int[] j6 = (int[]) getStaticObjectField( 133 | XHelper.findClass("com.aide.ui.a$5"), "j6"); 134 | Object sourceEntity$a = callMethod(sourceEntity, "DW"); 135 | int ordinal = (int) callMethod(sourceEntity$a, "ordinal"); 136 | int i2 = j6[ordinal]; 137 | 138 | switch (i2) { 139 | case 1: 140 | case 2: 141 | case 3: 142 | if (XL == null) { 143 | textView.setText(J8); 144 | break; 145 | } 146 | String stringBuilder = J8 + XL; 147 | textView.setText(stringBuilder, BufferType.SPANNABLE); 148 | break; 149 | case 4: 150 | if (we == null) { 151 | textView.setText(J8); 152 | break; 153 | } 154 | String stringBuilder1 = J8 + " - " + we; 155 | textView.setText(stringBuilder1, BufferType.SPANNABLE); 156 | break; 157 | case 5: 158 | textView.setText(J8, BufferType.SPANNABLE); 159 | break; 160 | default: 161 | textView.setText(J8); 162 | break; 163 | } 164 | //翻译 165 | try { 166 | MethodCompletion method = TranslateUtil 167 | .getTranslation(mContext, textView.getText().toString()); 168 | textView.append("\n->" + method.getChinese()); 169 | textView.setTag(method); 170 | callMethod(arrayAdapter, "j6", textView, J8.length(), textView.getText().length(), 171 | Color.parseColor("#FFAAAAAA")); 172 | } catch (Exception e) { 173 | XLog.show(TAG, e); 174 | } 175 | 176 | ImageView imageView = view.findViewById(0x7f080024); 177 | boolean Zo = (boolean) callMethod(sourceEntity, "Zo"); 178 | if (i2 != 6) { 179 | switch (i2) { 180 | case 1: 181 | if (!Zo) { 182 | imageView.setImageResource(0x7f070010); 183 | break; 184 | } 185 | imageView.setImageResource(0x7f07000e); 186 | break; 187 | case 2: 188 | if (!Zo) { 189 | imageView.setImageResource(0x7f07000b); 190 | break; 191 | } 192 | imageView.setImageResource(0x7f07000c); 193 | break; 194 | case 3: 195 | imageView.setImageResource(0x7f07000b); 196 | break; 197 | case 4: 198 | if (!Zo) { 199 | imageView.setImageResource(0x7f0700ee); 200 | break; 201 | } 202 | imageView.setImageResource(0x7f0700ef); 203 | break; 204 | default: 205 | imageView.setImageResource(0x7f070011); 206 | break; 207 | } 208 | } else { 209 | imageView.setImageResource(0x7f0700f0); 210 | } 211 | ImageView helpButton = view.findViewById(0x7f080026); 212 | helpButton.setVisibility(visibility); 213 | } 214 | return view; 215 | } 216 | }); 217 | } 218 | 219 | /** 220 | * 注入item长按代码 221 | */ 222 | private void hookItemLongClick() { 223 | //AdapterView长按 224 | Class clazz = XHelper.findClass("com.aide.ui.a$4"); 225 | 226 | findAndHookMethod(clazz, "onItemLongClick", AdapterView.class, View.class, 227 | int.class, 228 | long.class, new XC_MethodReplacement() { 229 | @Override 230 | protected Object replaceHookedMethod(final MethodHookParam param) { 231 | 232 | //adapterView 233 | final Object thisObject = param.thisObject; 234 | //item索引 235 | final int index = (int) param.args[2]; 236 | //item中的TextView 237 | final LinearLayout linearLayout = (LinearLayout) param.args[1]; 238 | final TextView textView = (TextView) linearLayout.getChildAt(1); 239 | 240 | //长按弹出popupMenu 241 | PopupMenu popupMenu = new PopupMenu(mContext, (View) param.args[1]); 242 | final Menu menu = popupMenu.getMenu(); 243 | menu.add(0, 2, 0, "修正翻译"); 244 | menu.add(0, 3, 0, "代码笔记"); 245 | menu.add(0, 4, 0, "查看文档"); 246 | 247 | //设置popupMenu的点击事件 248 | popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() { 249 | @RequiresApi(api = VERSION_CODES.JELLY_BEAN) 250 | @Override 251 | public boolean onMenuItemClick(MenuItem item) { 252 | switch (item.getItemId()) { 253 | case 2: 254 | //dialog中的EditView 255 | final EditText editText = new EditText(mContext); 256 | //获取上面传输来的Tag 257 | final MethodCompletion method = (MethodCompletion) textView 258 | .getTag(); 259 | editText.setText(method.getChinese()); 260 | //new一个对话框 261 | new AlertDialog.Builder(mContext).setTitle("修正翻译").setView(editText) 262 | .setCancelable(false) 263 | .setNegativeButton("取消", null) 264 | .setPositiveButton("确定", new OnClickListener() { 265 | @Override 266 | public void onClick(DialogInterface dialog, int which) { 267 | //更新数据库,通过english判断 268 | Uri uri = Uri 269 | .parse(DBProvider.TRANSLATION_CONTENT_URL); 270 | 271 | //更新 272 | Bundle bundle = new Bundle(); 273 | bundle.putString("english", method.getEnglish()); 274 | bundle.putString("chinese", editText.getText().toString()); 275 | bundle.putInt("state", DBProvider.TRANSLATE_STATE_OK); 276 | mContext.getContentResolver() 277 | .call(uri, "update", DBProvider.TRANSLATE, bundle); 278 | } 279 | }).show(); 280 | break; 281 | case 3: 282 | //代码笔记 283 | //获取上面传输来的Tag 284 | final MethodCompletion method1 = (MethodCompletion) textView 285 | .getTag(); 286 | //编辑框 287 | LinearLayout layout = new LinearLayout(mContext); 288 | LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 289 | LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 290 | 291 | final EditText et = new EditText(mContext); 292 | et.setText(method1.getNotes()); 293 | et.setTextSize(ConversionUtil.px2sp(mContext, 28)); 294 | et.setTextColor(Color.parseColor("#FFAAAAAA")); 295 | et.setHint("你可以在这里添加你的笔记"); 296 | et.setBackground(null); 297 | et.setGravity(Gravity.TOP); 298 | int padding = ConversionUtil.dip2px(mContext, 24); 299 | layout.setPadding(padding, 0, padding, 0); 300 | layout.addView(et, layoutParams); 301 | 302 | new AlertDialog.Builder(mContext) 303 | .setTitle("代码笔记") 304 | .setView(layout) 305 | .setCancelable(false) 306 | .setNegativeButton("取消", null) 307 | .setPositiveButton("保存", new OnClickListener() { 308 | @Override 309 | public void onClick(DialogInterface dialog, int which) { 310 | //更新代码笔记 311 | Uri uri = Uri 312 | .parse(DBProvider.TRANSLATION_CONTENT_URL); 313 | 314 | //更新 315 | Bundle bundle = new Bundle(); 316 | bundle.putString("english", method1.getEnglish()); 317 | bundle.putString("notes", et.getText().toString()); 318 | mContext.getContentResolver() 319 | .call(uri, "update", DBProvider.CODE_NOTES, bundle); 320 | } 321 | }) 322 | .show(); 323 | 324 | break; 325 | case 4: 326 | //查看文档,勿动 327 | try { 328 | @SuppressLint("ResourceType") 329 | ViewGroup AIDEEditorPager = mContext.findViewById(0x7f0800f1); 330 | XposedHelpers.callMethod(AIDEEditorPager, "Ws"); 331 | Activity activity = (Activity) XHelper 332 | .callStaticMethod("com.aide.ui.f", "u7"); 333 | ListView completionListView = (ListView) XposedHelpers 334 | .getObjectField(thisObject, "j6"); 335 | Object sourceEntity = completionListView.getItemAtPosition(index); 336 | String QX = XposedHelpers.callMethod(sourceEntity, "QX").toString(); 337 | String EQ = XHelper.callStaticMethod("com.aide.ui.activities.a", "EQ") 338 | .toString(); 339 | XHelper.callStaticMethod("com.aide.common.b", "j6", activity, 340 | QX, EQ); 341 | } catch (Exception e) { 342 | XLog.show(TAG, e); 343 | } 344 | break; 345 | } 346 | return true; 347 | } 348 | }); 349 | popupMenu.show(); 350 | return true; 351 | } 352 | }); 353 | } 354 | 355 | } 356 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/AutoRotate.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.app.Activity; 6 | import android.content.pm.ActivityInfo; 7 | import android.os.Bundle; 8 | import de.robv.android.xposed.XC_MethodHook; 9 | import me.tvcfish.xposed.util.XHelper; 10 | 11 | enum AutoRotate { 12 | 13 | INSTANCE; 14 | 15 | /** 16 | * 开始Hook 17 | */ 18 | public void startHook() { 19 | if (!isOpen()) { 20 | return; 21 | } 22 | hookMethod(); 23 | } 24 | 25 | /** 26 | * 是否开启此功能 27 | * 28 | * @return boolean 29 | */ 30 | private boolean isOpen() { 31 | return XHelper.getSharedPreferences().getBoolean("auto_rotate", true); 32 | } 33 | 34 | /** 35 | * Hook代码实现 36 | */ 37 | private void hookMethod(){ 38 | findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() { 39 | @Override 40 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 41 | super.afterHookedMethod(param); 42 | Activity activity = (Activity) param.thisObject; 43 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 44 | } 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/EnabledHookModel.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.content.Context; 6 | import de.robv.android.xposed.XC_MethodReplacement; 7 | import me.tvcfish.xposed.aidehelper.BuildConfig; 8 | import me.tvcfish.xposed.util.XHelper; 9 | 10 | enum EnabledHookModel { 11 | 12 | INSTANCE; 13 | 14 | /** 15 | * 开始Hook 16 | */ 17 | public void startHook() { 18 | hookTarget(); 19 | } 20 | 21 | /** 22 | * Hook代码实现 23 | */ 24 | private void hookTarget() { 25 | Class clazz = XHelper.findClass(BuildConfig.APPLICATION_ID + ".activity.MainActivity"); 26 | findAndHookMethod(clazz, "isExpModuleActive", Context.class, new XC_MethodReplacement() { 27 | @Override 28 | protected Object replaceHookedMethod(MethodHookParam param) { 29 | return true; 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/GradleCompletionExpand.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.callMethod; 4 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 5 | import static de.robv.android.xposed.XposedHelpers.newInstance; 6 | 7 | import de.robv.android.xposed.XC_MethodHook; 8 | import me.tvcfish.xposed.util.XHelper; 9 | 10 | enum GradleCompletionExpand { 11 | 12 | INSTANCE; 13 | 14 | /** 15 | * 开始Hook 16 | */ 17 | public void startHook() { 18 | if (!isOpen()) { 19 | return; 20 | } 21 | hookTarget(); 22 | } 23 | 24 | /** 25 | * 是否开启此功能 26 | * 27 | * @return boolean 28 | */ 29 | private boolean isOpen() { 30 | return XHelper.getSharedPreferences().getBoolean("gradle_completion_expand", false); 31 | } 32 | 33 | /** 34 | * Hook代码实现 35 | */ 36 | private void hookTarget() { 37 | Class clazz = XHelper.findClass("com.aide.engine.b$b$b"); 38 | findAndHookMethod(clazz, "FH", String.class, new XC_MethodHook() { 39 | @Override 40 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 41 | super.afterHookedMethod(param); 42 | if (param.args[0].equals("compile 'com.google.android.gms:play-services:+'")) { 43 | Object thisObject = param.thisObject; 44 | Class SourceEntity = XHelper.findClass("com.aide.engine.SourceEntity"); 45 | //api和implementation 46 | String[] strings = new String[]{"api", "implementation"}; 47 | customGradleCompletion(thisObject, SourceEntity, strings); 48 | 49 | //自定义 50 | String customs = XHelper.getSharedPreferences().getString("gradle_completion_custom", ""); 51 | String[] split = customs.split("\n"); 52 | customGradleCompletion(thisObject, SourceEntity, split); 53 | } 54 | } 55 | }); 56 | } 57 | 58 | /** 59 | * 自定义补全 60 | */ 61 | private void customGradleCompletion(Object thisObject, Class SourceEntityClass, 62 | String[] strings) { 63 | for (String value : strings) { 64 | Object SourceEntity = newInstance(SourceEntityClass, value); 65 | callMethod(thisObject, "j6", SourceEntity); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/HookInit.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.app.Application; 6 | import android.content.Context; 7 | import android.util.Log; 8 | import de.robv.android.xposed.IXposedHookLoadPackage; 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 11 | import me.tvcfish.xposed.aidehelper.BuildConfig; 12 | import me.tvcfish.xposed.util.XHelper; 13 | import me.tvcfish.xposed.util.XLog; 14 | 15 | public class HookInit implements IXposedHookLoadPackage { 16 | 17 | @Override 18 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) { 19 | final String packageName = lpparam.packageName; 20 | //初始化 21 | XHelper.init(lpparam,BuildConfig.APPLICATION_ID); 22 | 23 | //判断是否启用模块 24 | if (packageName.equals(BuildConfig.APPLICATION_ID)) { 25 | EnabledHookModel.INSTANCE.startHook(); 26 | return; 27 | } 28 | 29 | if (!packageName.equals("com.aide.ui")) { 30 | return; 31 | } 32 | 33 | findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() { 34 | @Override 35 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 36 | super.afterHookedMethod(param); 37 | //解锁高级版 38 | UnlockPremium.INSTANCE.startHook(); 39 | //禁用自动旋转 40 | AutoRotate.INSTANCE.startHook(); 41 | //符号栏 42 | SymbolBar.INSTANCE.startHook(); 43 | //搜索界面 44 | SearchPage.INSTANCE.startHook(); 45 | //Action 46 | ActionBarIcon.INSTANCE.startHook(); 47 | //中文补全 48 | AutoCompletion.INSTANCE.startHook(); 49 | //Gradle补全拓展 50 | GradleCompletionExpand.INSTANCE.startHook(); 51 | //版本切换 52 | SwitchVersion.INSTANCE.startHook(); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/SearchPage.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.widget.TextView; 6 | import de.robv.android.xposed.XC_MethodHook; 7 | import me.tvcfish.xposed.util.XHelper; 8 | 9 | enum SearchPage { 10 | 11 | INSTANCE; 12 | 13 | /** 14 | * 开始Hook 15 | */ 16 | public void startHook() { 17 | if (!isOpen()) { 18 | return; 19 | } 20 | hookMethod(); 21 | } 22 | 23 | /** 24 | * 是否开启此功能 25 | * 26 | * @return boolean 27 | */ 28 | private boolean isOpen() { 29 | return XHelper.getSharedPreferences().getBoolean("search_page_adjustment", false); 30 | } 31 | 32 | /** 33 | * Hook代码实现 34 | */ 35 | private void hookMethod() { 36 | Class clazz = XHelper.findClass("com.aide.ui.browsers.FindResultTextView"); 37 | Class findResult = XHelper.findClass("com.aide.engine.FindResult"); 38 | findAndHookMethod(clazz, "setContent", findResult, new XC_MethodHook() { 39 | @Override 40 | protected void afterHookedMethod(MethodHookParam param) { 41 | TextView textView = (TextView) param.thisObject; 42 | textView.setSingleLine(false); 43 | } 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/SwitchVersion.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import android.content.res.AssetManager; 6 | import android.os.Environment; 7 | import de.robv.android.xposed.XC_MethodHook; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import me.tvcfish.xposed.util.BuildConfig; 11 | import me.tvcfish.xposed.util.XHelper; 12 | 13 | enum SwitchVersion { 14 | INSTANCE; 15 | 16 | /** 17 | * 开始Hook 18 | */ 19 | public void startHook() { 20 | if (isOpen().equals("com.aide.ui")) { 21 | return; 22 | } 23 | hookMethod(); 24 | } 25 | 26 | /** 27 | * 是否开启此功能 28 | * 29 | * @return boolean 30 | */ 31 | private String isOpen() { 32 | return XHelper.getSharedPreferences().getString("switch_version", "com.aide.ui"); 33 | } 34 | 35 | /** 36 | * Hook代码实现 37 | */ 38 | private void hookMethod() { 39 | Class clazz = XHelper.findClass("com.aide.ui.f"); 40 | findAndHookMethod(clazz, "j6", String.class, new XC_MethodHook() { 41 | @Override 42 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 43 | super.beforeHookedMethod(param); 44 | param.args[0] = isOpen(); 45 | } 46 | }); 47 | 48 | //模版添加 49 | if (!isOpen().equals("com.aide.ui")) { 50 | findAndHookMethod(AssetManager.class, "open", String.class, new XC_MethodHook() { 51 | @Override 52 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 53 | super.beforeHookedMethod(param); 54 | String fileName = param.args[0].toString(); 55 | String aideHelper = Environment.getExternalStorageDirectory() + "/Android/data/" 56 | + BuildConfig.APPLICATION_ID + "/files/assets/templates/"; 57 | switch (fileName) { 58 | case "templates/WebsiteBootstrap.zip": 59 | File websiteBootstrap = new File(aideHelper + "WebsiteBootstrap.zip"); 60 | param.setResult(new FileInputStream(websiteBootstrap)); 61 | break; 62 | case "templates/HelloJavaScript.zip": 63 | File helloJavaScript = new File(aideHelper + "HelloJavaScript.zip"); 64 | param.setResult(new FileInputStream(helloJavaScript)); 65 | break; 66 | case "templates/PhoneGapAppNew.zip": 67 | File phoneGapAppNew = new File(aideHelper + "PhoneGapAppNew.zip"); 68 | param.setResult(new FileInputStream(phoneGapAppNew)); 69 | break; 70 | case "AIDEWebSamples.zip": 71 | File aideWebSamples = new File(aideHelper + "AIDEWebSamples.zip"); 72 | param.setResult(new FileInputStream(aideWebSamples)); 73 | break; 74 | } 75 | } 76 | }); 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/SymbolBar.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | import static de.robv.android.xposed.XposedHelpers.setObjectField; 5 | 6 | import android.annotation.SuppressLint; 7 | import android.app.Activity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.View.OnClickListener; 11 | import android.view.ViewGroup.LayoutParams; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | import de.robv.android.xposed.XC_MethodReplacement; 15 | import java.lang.reflect.Field; 16 | import me.tvcfish.xposed.aidehelper.util.ConversionUtil; 17 | import me.tvcfish.xposed.util.XHelper; 18 | 19 | enum SymbolBar { 20 | INSTANCE; 21 | 22 | /** 23 | * 开始Hook 24 | */ 25 | public void startHook() { 26 | if (!isOpen()) { 27 | return; 28 | } 29 | hookMethod(); 30 | } 31 | 32 | 33 | /** 34 | * 是否开启此功能 35 | * 36 | * @return boolean 37 | */ 38 | private boolean isOpen() { 39 | return XHelper.getSharedPreferences().getBoolean("symbol_bar_adjustment", false); 40 | } 41 | 42 | /** 43 | * 符号栏拓展 44 | */ 45 | private void hookMethod() { 46 | 47 | final Class clazz = XHelper.findClass("com.aide.ui.o"); 48 | 49 | //重写整个j6方法 50 | findAndHookMethod(clazz, "j6", String.class, new XC_MethodReplacement() { 51 | @SuppressLint({"ResourceType", "ClickableViewAccessibility", "SetTextI18n"}) 52 | @Override 53 | protected Object replaceHookedMethod(MethodHookParam param) 54 | throws NoSuchFieldException, IllegalAccessException { 55 | final Object thisObject = param.thisObject; 56 | Field field = XHelper.getField(clazz, "DW"); 57 | Field field1 = XHelper.getField(clazz, "FH"); 58 | Field field2 = XHelper.getField(clazz, "j6"); 59 | 60 | String str = (String) param.args[0]; 61 | View DW = (View) field.get(thisObject); 62 | String FH = (String) field1.get(thisObject); 63 | final Activity j6 = (Activity) field2.get(thisObject); 64 | 65 | if (DW != null && str != null && !FH.equals(str)) { 66 | //this.FH = str; 67 | setObjectField(thisObject, "FH", str); 68 | LayoutInflater layoutInflater = LayoutInflater.from(j6); 69 | 70 | int i = (int) (40.0f * j6.getResources().getDisplayMetrics().density); 71 | int i2 = (int) (40.0f * j6.getResources().getDisplayMetrics().density); 72 | LinearLayout viewGroup = DW.findViewById(0x7f080143); 73 | viewGroup.removeAllViews(); 74 | for (String replace : str.split(" ")) { 75 | final String replace2 = replace.replace("s", " "); 76 | final TextView textView = (TextView) layoutInflater.inflate(0x7f0a003c, null); 77 | textView.setTextSize(ConversionUtil.sp2px(j6, 5)); 78 | if (replace2.trim().length() == 0) { 79 | textView.setText("TAB"); 80 | } else { 81 | textView.setText(replace2); 82 | } 83 | viewGroup.addView(textView, new LayoutParams(i, i2)); 84 | //new 3(this,replace2) 85 | OnClickListener clickListener = (OnClickListener) XHelper 86 | .newInstance("com.aide.ui.o$3", thisObject, replace2); 87 | textView.setOnClickListener(clickListener); 88 | } 89 | } 90 | return null; 91 | } 92 | }); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/hook/UnlockPremium.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.hook; 2 | 3 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; 4 | 5 | import de.robv.android.xposed.XC_MethodReplacement; 6 | import me.tvcfish.xposed.util.XHelper; 7 | 8 | enum UnlockPremium { 9 | 10 | INSTANCE; 11 | 12 | /** 13 | * 开始Hook 14 | */ 15 | public void startHook() { 16 | if (!isOpen()) { 17 | return; 18 | } 19 | hookTarget(); 20 | } 21 | 22 | /** 23 | * 是否开启此功能 24 | * 25 | * @return boolean 26 | */ 27 | private boolean isOpen() { 28 | return XHelper.getSharedPreferences().getBoolean("unlock_premium", false); 29 | } 30 | 31 | /** 32 | * Hook代码实现 33 | */ 34 | private void hookTarget() { 35 | Class clazz = XHelper.findClass("pc"); 36 | String[] strings = new String[]{"a8", "FH", "VH", "tp", "EQ", "QX", "XL", "j3"}; 37 | for (String value : strings) { 38 | findAndHookMethod(clazz, value, new XC_MethodReplacement() { 39 | @Override 40 | protected Object replaceHookedMethod(MethodHookParam param) { 41 | return true; 42 | } 43 | }); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/model/MethodCompletion.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.model; 2 | 3 | import org.litepal.crud.LitePalSupport; 4 | 5 | public class MethodCompletion extends LitePalSupport { 6 | 7 | private int id; 8 | private String english; 9 | private String chinese; 10 | private String notes; 11 | private int state; 12 | 13 | public int getId() { 14 | return id; 15 | } 16 | 17 | public void setId(int id) { 18 | this.id = id; 19 | } 20 | 21 | public String getEnglish() { 22 | return english; 23 | } 24 | 25 | public void setEnglish(String english) { 26 | this.english = english; 27 | } 28 | 29 | public String getChinese() { 30 | return chinese; 31 | } 32 | 33 | public void setChinese(String chinese) { 34 | this.chinese = chinese; 35 | } 36 | 37 | public String getNotes() { 38 | return notes; 39 | } 40 | 41 | public void setNotes(String notes) { 42 | this.notes = notes; 43 | } 44 | 45 | public int getState() { 46 | return state; 47 | } 48 | 49 | public void setState(int state) { 50 | this.state = state; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/provider/DBProvider.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.provider; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.content.UriMatcher; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.os.Bundle; 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | import me.tvcfish.xposed.aidehelper.model.MethodCompletion; 12 | import org.litepal.LitePal; 13 | 14 | public class DBProvider extends ContentProvider { 15 | 16 | public static final String CODE_NOTES = "1"; 17 | public static final String TRANSLATE = "2"; 18 | 19 | public static final int TRANSLATE_STATE_FAIL = -2; 20 | public static final int TRANSLATE_STATE_INIT = -1; 21 | public static final int TRANSLATE_STATE_OK = 1; 22 | 23 | private static final String AUTHORITY = "me.tvcfish.xposed.aidehelper.provider.DBProvider"; 24 | public static final String TRANSLATION_CONTENT_URL = 25 | "content://" + AUTHORITY + "/MethodCompletion"; 26 | private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); 27 | 28 | static { 29 | URI_MATCHER.addURI(AUTHORITY, "MethodCompletion", 0); 30 | } 31 | 32 | 33 | @Override 34 | public boolean onCreate() { 35 | return false; 36 | } 37 | 38 | @Nullable 39 | @Override 40 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, 41 | @Nullable String[] selectionArgs, @Nullable String sortOrder) { 42 | return null; 43 | } 44 | 45 | @Nullable 46 | @Override 47 | public String getType(@NonNull Uri uri) { 48 | return null; 49 | } 50 | 51 | @Nullable 52 | @Override 53 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 54 | return null; 55 | } 56 | 57 | @Override 58 | public int delete(@NonNull Uri uri, @Nullable String selection, 59 | @Nullable String[] selectionArgs) { 60 | return 0; 61 | } 62 | 63 | @Override 64 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, 65 | @Nullable String[] selectionArgs) { 66 | return 0; 67 | } 68 | 69 | @Nullable 70 | @Override 71 | public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) { 72 | switch (method) { 73 | case "save": 74 | assert extras != null; 75 | save(extras); 76 | break; 77 | case "query": 78 | assert extras != null; 79 | return query(extras); 80 | case "update": 81 | assert extras != null; 82 | assert arg != null; 83 | update(extras, arg); 84 | break; 85 | } 86 | return super.call(method, arg, extras); 87 | } 88 | 89 | /** 90 | * 保存到数据库 91 | */ 92 | private void save(Bundle bundle) { 93 | MethodCompletion method = new MethodCompletion(); 94 | method.setEnglish(bundle.getString("english")); 95 | method.setChinese(bundle.getString("chinese")); 96 | method.setNotes(bundle.getString("notes")); 97 | method.setState(bundle.getInt("state")); 98 | method.save(); 99 | } 100 | 101 | /** 102 | * 查询 103 | */ 104 | private Bundle query(Bundle bundle) { 105 | //获取值用来做查询条件 106 | String english = bundle.getString("english"); 107 | //查询数据库 108 | MethodCompletion method = LitePal.where("english=?", english).find(MethodCompletion.class) 109 | .get(0); 110 | 111 | //把获取的数据填充到Bundle 112 | bundle.putString("english", method.getEnglish()); 113 | bundle.putString("chinese", method.getChinese()); 114 | bundle.putString("notes", method.getNotes()); 115 | bundle.putInt("state", method.getState()); 116 | return bundle; 117 | } 118 | 119 | /** 120 | * 更新 121 | */ 122 | private void update(Bundle bundle, String arg) { 123 | //条件 124 | String english = bundle.getString("english"); 125 | 126 | //参数 127 | ContentValues values = new ContentValues(); 128 | switch (arg) { 129 | case CODE_NOTES: 130 | String notes = bundle.getString("notes"); 131 | values.put("notes", notes); 132 | break; 133 | case TRANSLATE: 134 | if (bundle.getInt("state") == TRANSLATE_STATE_OK) { 135 | //翻译,添加中文翻译 136 | String chinese = bundle.getString("chinese"); 137 | int state = bundle.getInt("state"); 138 | values.put("chinese", chinese); 139 | values.put("state", state); 140 | } 141 | int state = bundle.getInt("state"); 142 | values.put("state", state); 143 | 144 | break; 145 | } 146 | //更新 147 | LitePal.updateAll(MethodCompletion.class, values, "english=?", english); 148 | } 149 | 150 | 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/util/ConversionUtil.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.util; 2 | 3 | import android.content.Context; 4 | 5 | public class ConversionUtil { 6 | 7 | /** 8 | * dp转px 9 | */ 10 | 11 | public static int dip2px(Context context, int dp) { 12 | float density = context.getResources().getDisplayMetrics().density; 13 | return (int) (dp * density + 0.5); 14 | } 15 | 16 | /** 17 | * px转换dip 18 | */ 19 | public static int px2dip(Context context,int px) { 20 | final float scale = context.getResources().getDisplayMetrics().density; 21 | return (int) (px / scale + 0.5f); 22 | } 23 | 24 | /** 25 | * px转换sp 26 | */ 27 | public static int px2sp(Context context,int pxValue) { 28 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 29 | return (int) (pxValue / fontScale + 0.5f); 30 | } 31 | 32 | /** 33 | * sp转换px 34 | */ 35 | public static int sp2px(Context context,int spValue) { 36 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 37 | return (int) (spValue * fontScale + 0.5f); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.util; 2 | 3 | import android.app.Activity; 4 | import android.os.Environment; 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | public class FileUtil { 11 | 12 | /** 13 | * 从Raw读取文本文件 14 | * @param activity 用来获取Resources 15 | * @param rawId raw文件Id 16 | * @return text content 17 | */ 18 | public static String readTextFromRaw(Activity activity, int rawId) { 19 | try { 20 | InputStream inputStream = activity.getResources().openRawResource(rawId); 21 | int size = inputStream.available(); 22 | byte[] buffer = new byte[size]; 23 | inputStream.read(buffer); 24 | inputStream.close(); 25 | return new String(buffer); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | return "操作异常:" + e.getMessage(); 29 | } 30 | } 31 | 32 | /** 33 | * 创建文件夹 34 | */ 35 | public static void mkdirs(String filePath) { 36 | File file = new File(filePath); 37 | if (!file.exists()) { 38 | file.mkdirs(); 39 | } 40 | } 41 | 42 | /** 43 | * 获取应用外置储存路径 44 | */ 45 | public static String getExternalFilesDirPath(Activity activity) { 46 | File file = activity.getExternalFilesDir(""); 47 | if (file != null) { 48 | return file.getPath(); 49 | } else { 50 | String path = Environment.getExternalStorageDirectory().getAbsolutePath(); 51 | File appPath = new File(path + "Android/data/me.tvcfish.xposed.aidehelper/files"); 52 | if (!appPath.exists()) { 53 | appPath.mkdirs(); 54 | } 55 | return appPath.getPath(); 56 | } 57 | } 58 | 59 | /** 60 | * 把assets文件复制到SD卡 61 | * 62 | * @param activity 用来获取assets资源 63 | * @param filePath assets文件路径 64 | */ 65 | public static void copyAssetsFileToSdcard(Activity activity, String filePath) { 66 | try { 67 | String[] strings = activity.getResources().getAssets().list(filePath); 68 | 69 | if (strings != null) { 70 | for (String value : strings) { 71 | InputStream is = activity.getResources().getAssets().open(filePath + "/" + value); 72 | 73 | File file = new File( 74 | getExternalFilesDirPath(activity) + "/assets/" + filePath + "/" + value); 75 | 76 | //如果文件存在,退出该次操作 77 | if (file.exists()) { 78 | continue; 79 | } 80 | 81 | FileOutputStream fos = new FileOutputStream(file); 82 | byte[] buffer = new byte[1024]; 83 | int byteCount; 84 | while ((byteCount = is.read(buffer)) != -1) {//循环从输入流读取 buffer字节 85 | fos.write(buffer, 0, byteCount);//将读取的输入流写入到输出流 86 | } 87 | fos.flush();//刷新缓冲区 88 | is.close(); 89 | fos.close(); 90 | } 91 | } 92 | } catch (IOException e) { 93 | e.printStackTrace(); 94 | } 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/me/tvcfish/xposed/aidehelper/util/TranslateUtil.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper.util; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import androidx.annotation.NonNull; 7 | import java.io.IOException; 8 | import java.security.NoSuchAlgorithmException; 9 | import me.tvcfish.xposed.aidehelper.model.MethodCompletion; 10 | import me.tvcfish.xposed.aidehelper.provider.DBProvider; 11 | import me.tvcfish.xposed.util.XHelper; 12 | import me.tvcfish.xposed.util.XLog; 13 | import okhttp3.Call; 14 | import okhttp3.Callback; 15 | import okhttp3.FormBody; 16 | import okhttp3.OkHttpClient; 17 | import okhttp3.Request; 18 | import okhttp3.Response; 19 | import org.json.JSONException; 20 | import org.json.JSONObject; 21 | import org.json.JSONTokener; 22 | 23 | public class TranslateUtil { 24 | 25 | private static final String from = "en"; 26 | private static final String to = "zh-CHS"; 27 | /*******************************************/ 28 | private static final String pid = "your pid"; 29 | private static final String key = "your key"; 30 | /*******************************************/ 31 | private static final String salt = "1434918491"; 32 | 33 | //TAG 34 | private static final String TAG = "TranslateUtil"; 35 | 36 | 37 | private static void saveRequest(final Context context, final String q) { 38 | String en = wordSegmentation(q.toCharArray(), 0, 39 | q.length(), false, ""); 40 | OkHttpClient client = new OkHttpClient(); 41 | final FormBody.Builder builder = new FormBody.Builder(); 42 | builder.add("from", from) 43 | .add("to", to) 44 | .add("pid", pid) 45 | .add("q", en) 46 | .add("salt", salt) 47 | .add("sign", getMD5(pid + en + salt + key)); 48 | final Request request = new Request.Builder() 49 | .url("http://fanyi.sogou.com/reventondc/api/sogouTranslate") 50 | .addHeader("content-type", "application/x-www-form-urlencoded") 51 | .addHeader("accept", "application/json") 52 | .post(builder.build()) 53 | .build(); 54 | client.newCall(request).enqueue(new Callback() { 55 | @Override 56 | public void onFailure(@NonNull Call call, @NonNull IOException e) { 57 | //数据库操作,翻译失败.添加标记 58 | Uri uri = Uri 59 | .parse(DBProvider.TRANSLATION_CONTENT_URL); 60 | Bundle bundle = new Bundle(); 61 | bundle.putString("english", q); 62 | bundle.putInt("state", DBProvider.TRANSLATE_STATE_FAIL); 63 | context.getContentResolver().call(uri, "update", DBProvider.TRANSLATE, bundle); 64 | } 65 | 66 | @Override 67 | public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { 68 | assert response.body() != null; 69 | JSONTokener jsonToken = new JSONTokener(response.body().string()); 70 | try { 71 | JSONObject translation = new JSONObject(jsonToken); 72 | String chinese = translation.getString("translation"); 73 | //数据库操作,更新数据 74 | Uri uri = Uri 75 | .parse(DBProvider.TRANSLATION_CONTENT_URL); 76 | Bundle bundle = new Bundle(); 77 | bundle.putString("english", q); 78 | bundle.putString("chinese", chinese); 79 | bundle.putInt("state", DBProvider.TRANSLATE_STATE_OK); 80 | context.getContentResolver().call(uri, "update", DBProvider.TRANSLATE, bundle); 81 | } catch (JSONException e) { 82 | XLog.show(TAG,e); 83 | } 84 | } 85 | }); 86 | } 87 | 88 | public static MethodCompletion getTranslation(Context context, String text) { 89 | //Provider Uri 90 | Uri uri = Uri.parse(DBProvider.TRANSLATION_CONTENT_URL); 91 | 92 | //读取数据库 93 | Bundle read = new Bundle(); 94 | read.putString("english", text); 95 | read = context.getContentResolver().call(uri, "query", null, read); 96 | 97 | assert read != null; 98 | int state = read.getInt("state"); 99 | MethodCompletion method = new MethodCompletion(); 100 | if (state == 0) { 101 | //写入默认数据 102 | try { 103 | Bundle write = new Bundle(); 104 | write.putString("english", text); 105 | write.putInt("state", DBProvider.TRANSLATE_STATE_INIT); 106 | context.getContentResolver().call(uri, "save", null, write); 107 | method.setChinese("成功写入初始数据,请再次滑动列表进行翻译"); 108 | return method; 109 | } catch (Exception e) { 110 | XLog.show(TAG,e); 111 | method.setChinese("无法写入初始数据,请赋予AideHelper读写权限"); 112 | return method; 113 | } 114 | } else if (state == DBProvider.TRANSLATE_STATE_INIT) { 115 | //翻译 116 | TranslateUtil.saveRequest(context, text); 117 | method.setChinese("翻译中..."); 118 | return method; 119 | } else if (state == DBProvider.TRANSLATE_STATE_FAIL) { 120 | //翻译 121 | TranslateUtil.saveRequest(context, text); 122 | method.setChinese("翻译失败,请检查网络"); 123 | return method; 124 | } else { 125 | //返回以存在的数据 126 | MethodCompletion readMethod = new MethodCompletion(); 127 | readMethod.setEnglish(read.getString("english")); 128 | readMethod.setChinese(read.getString("chinese")); 129 | readMethod.setNotes(read.getString("notes")); 130 | return readMethod; 131 | } 132 | } 133 | 134 | /** 135 | * 分词 136 | * 137 | * @param word 原词组 138 | * @param index 索引 0 139 | * @param wordLength 词组长度 140 | * @param result 结果 141 | * @return result 142 | */ 143 | private static String wordSegmentation(char[] word, int index, int wordLength, boolean mark, 144 | String result) { 145 | if (index == wordLength) { 146 | return result.trim(); 147 | } else { 148 | char ch = word[index]; 149 | //如果是字母,继续判断大小写 150 | if (Character.isLetter(ch)) { 151 | //是大写 152 | if (Character.isUpperCase(ch)) { 153 | if (index > 0 && index < wordLength) { 154 | boolean before = Character.isLowerCase(word[index - 1]); 155 | boolean after = Character.isLowerCase(word[index + 1]); 156 | if (before && after) { 157 | result += " " + ch; 158 | } else { 159 | result += ch; 160 | } 161 | } else { 162 | result += ch; 163 | } 164 | } else { 165 | result += ch; 166 | } 167 | } else { 168 | //后面是类包名,不分词,直接退出 169 | if (ch == '-') { 170 | if (word[index - 1] == ' ' && word[index + 1] == ' ') { 171 | return result.trim(); 172 | } else { 173 | result += '-'; 174 | } 175 | } else if (ch == '(') { //是否为方法 176 | mark = true; 177 | result += "("; 178 | } else if (ch == '.') { 179 | result += '-'; 180 | } else if (mark && ch == ' ') { 181 | if (word[index - 1] == ',') { 182 | result += ch; 183 | } else { 184 | result += ":"; 185 | } 186 | } 187 | //不是字母,前后加一个空格 188 | else { 189 | result += " " + ch + " "; 190 | } 191 | } 192 | return wordSegmentation(word, index + 1, wordLength, mark, result); 193 | } 194 | } 195 | 196 | private static String getMD5(String text) { 197 | String s = null; 198 | char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 199 | 'a', 'b', 'c', 'd', 'e', 'f'};// 用来将字节转换成16进制表示的字符 200 | try { 201 | java.security.MessageDigest md = java.security.MessageDigest 202 | .getInstance("MD5"); 203 | md.update(text.getBytes()); 204 | byte tmp[] = md.digest();// MD5 的计算结果是一个 128 位的长整数, 205 | // 用字节表示就是 16 个字节 206 | char str[] = new char[16 * 2];// 每个字节用 16 进制表示的话,使用两个字符, 所以表示成 16 207 | // 进制需要 32 个字符 208 | int k = 0;// 表示转换结果中对应的字符位置 209 | for (int i = 0; i < 16; i++) {// 从第一个字节开始,对 MD5 的每一个字节// 转换成 16 210 | // 进制字符的转换 211 | byte byte0 = tmp[i];// 取第 i 个字节 212 | str[k++] = hexDigits[byte0 >>> 4 & 0xf];// 取字节中高 4 位的数字转换,// >>> 213 | // 为逻辑右移,将符号位一起右移 214 | str[k++] = hexDigits[byte0 & 0xf];// 取字节中低 4 位的数字转换 215 | 216 | } 217 | s = new String(str);// 换后的结果转换为字符串 218 | 219 | } catch (NoSuchAlgorithmException e) { 220 | // TODO Auto-generated catch block 221 | e.printStackTrace(); 222 | } 223 | return s; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/drawable/alipay.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/drawable/wechat.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/raw/update_log: -------------------------------------------------------------------------------- 1 | Version: 1.2 2 | 1.适配太极 3 | 2.代码优化 4 | tip:已完成太极的适配工作,但由于太极只开放了1.0版本的使用,所以后续版本就等太极慢慢开放。 5 | 6 | Version: 1.1 7 | 1.解决Web中缺少Samples模版的问题@FlenkeAustin 8 | 9 | Version: 1.0 10 | 1.已开源至GitHub(欢迎Start) 11 | 2.开源库引用说明更新 12 | 3.进入慢更时代(如果不是必要情况应该不会更新了) 13 | 14 | Version: 0.07-beta 15 | 1.修复WebsiteBootstrap JavaScript PhoneGap项目创建后为空的问题 @FlenKeAustin 16 | 2.添加更新日志的Dialog 17 | 3.厚颜无耻的添加了捐赠,嘿嘿嘿 18 | tip:安装该版本后请执行一次打开AideHelper的操作(解压模版文件) 19 | 20 | Version: 0.06-beta 21 | 1.解锁专业版-是指AIDE的专业版内容(终于搞好了) 22 | 23 | Version: 0.05-beta 24 | 1.界面微调 2.gradle补全拓展 25 | 26 | Version: 0.04-beta 27 | 1.添加模块启用检查 28 | 2.添加PhoneGap支持(酷友要求@FlenKeAustin,只适用于破解版) -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AideHelper 3 | VXP 4 | 太极 5 | 好的 6 | 7 | 微信 8 | 支付宝 9 | 10 | 11 | 模块未启用 12 | 请前往Xposed激活该模块(支持太极、VirtualXposed) 13 | 14 | 15 | 16 | 基本功能 17 | 18 | 解锁专业版 19 | AIDE的专业版内容 20 | 21 | 禁用自动旋转 22 | 屏幕随手机旋转,建议开启此选项 23 | 24 | 25 | UI调整 26 | 提供一些适当的布局调整选项 27 | 28 | 符号栏调整 29 | 字体大小以及一些间距调整 30 | 搜索结果界面调整 31 | 取消单行显示 32 | 去除AIDE的icon 33 | ActionBar中的AIDE图标 34 | 35 | 36 | 37 | 拓展选项 38 | 39 | 中文补全 40 | 补全翻译,添加中文注释(sdcard/Android/data/me.tvcfish.xposed.aidehelper/files/databases) 41 | 42 | 版本切换 43 | 提供默认(Android C/C++ Java)和Web(Website JavaScript)以及PhoneGap(如果闪退,请开启【解锁专业版选项】)之间的版本切换 44 | 45 | 默认 46 | Web 47 | PhoneGap 48 | 49 | 50 | com.aide.ui 51 | com.aide.web 52 | com.aide.phonegap 53 | 54 | 55 | Gradle补全拓展 56 | 添加api和implementation,支持自定义 57 | 58 | 开启 59 | 自定义 60 | 自定义补全内容,使用换行隔开 61 | 62 | 63 | 64 | 关于 65 | 66 | 作者 67 | TvcFish@CoolApk 68 | 69 | 捐赠 70 | 请作者吃一包辣条 71 | 72 | 开源相关 73 | 感谢各大开源项目,世界因你们而更加精彩 74 | okhttp 75 | An HTTP+HTTP/2 client for Android and Java applications. 76 | LitePal 77 | An Android library that makes developers use SQLite database extremely easy. 78 | MiniPay 79 | A nice tool for mobile pay without Wechat or Ali sdk 80 | 81 | 更新日志 82 | 看看都更新了什么内容 83 | 84 | GitHub 85 | 欢迎Start该项目 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/xml/main_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 17 | 18 | 22 | 23 | 28 | 29 | 34 | 35 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 51 | 52 | 56 | 57 | 61 | 62 | 67 | 68 | 69 | 70 | 77 | 78 | 79 | 80 | 81 | 82 | 86 | 90 | 91 | 92 | 96 | 99 | 100 | 101 | 105 | 106 | 110 | 111 | 115 | 116 | 120 | 123 | 124 | 125 | 126 | 130 | 133 | 134 | 135 | 139 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /app/src/test/java/me/tvcfish/xposed/aidehelper/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package me.tvcfish.xposed.aidehelper; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 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 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.3.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /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/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 17 23:07:45 CST 2019 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-4.10.1-all.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 | -------------------------------------------------------------------------------- /image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikws4/AideHelper/3ccbd15315d706d7318d5a770cba9a2d14d1b9ea/image-1.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':XposedUtil' 2 | --------------------------------------------------------------------------------