├── LICENSE ├── README.md └── app ├── .gitignore ├── .idea └── vcs.xml ├── app.iml ├── build.gradle ├── drop ├── .gitignore ├── build.gradle ├── drop.iml ├── gradle.properties ├── gradlew ├── gradlew.bat ├── local.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── yalantis │ │ └── phoenix │ │ ├── PullToRefreshView.java │ │ ├── refresh_view │ │ ├── BaseRefreshView.java │ │ └── SunRefreshView.java │ │ └── util │ │ ├── Logger.java │ │ └── Utils.java │ └── res │ ├── drawable-hdpi │ ├── buildings.png │ ├── sky.png │ └── sun.png │ ├── drawable-mdpi │ ├── buildings.png │ ├── sky.png │ └── sun.png │ ├── drawable-xhdpi │ ├── buildings.png │ ├── sky.png │ └── sun.png │ ├── drawable-xxhdpi │ ├── buildings.png │ ├── sky.png │ └── sun.png │ ├── drawable-xxxhdpi │ ├── buildings.png │ ├── sky.png │ └── sun.png │ └── values │ └── attrs.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── build.gradle ├── build │ └── generated │ │ └── source │ │ ├── buildConfig │ │ └── release │ │ │ └── me │ │ │ └── imid │ │ │ └── swipebacklayout │ │ │ └── lib │ │ │ └── BuildConfig.java │ │ └── r │ │ └── release │ │ ├── android │ │ └── support │ │ │ └── v7 │ │ │ └── appcompat │ │ │ └── R.java │ │ └── me │ │ └── imid │ │ └── swipebacklayout │ │ └── lib │ │ └── R.java ├── library.iml └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── imid │ │ └── swipebacklayout │ │ └── lib │ │ ├── SwipeBackLayout.java │ │ ├── Utils.java │ │ ├── ViewDragHelper.java │ │ └── app │ │ ├── SwipeBackActivity.java │ │ ├── SwipeBackActivityBase.java │ │ ├── SwipeBackActivityHelper.java │ │ └── SwipeBackPreferenceActivity.java │ └── res │ ├── drawable-xhdpi │ ├── shadow_bottom.png │ ├── shadow_left.png │ └── shadow_right.png │ ├── layout │ └── swipeback_layout.xml │ └── values │ ├── attrs.xml │ └── styles.xml ├── libs ├── api-82-sources.jar ├── api-82.jar ├── umeng-analytics-v6.0.1.jar └── utdid4all-1.0.4.jar ├── local.properties ├── proguard-rules.pro ├── settings.gradle └── src ├── androidTest └── java │ └── com │ └── coderstory │ └── miui_toolkit │ └── ApplicationTest.java ├── main ├── AndroidManifest.xml ├── assets │ ├── google │ ├── hosts │ ├── hosts_noad │ ├── hosts_nostore │ ├── hosts_noup │ ├── none │ └── xposed_init ├── java │ └── com │ │ └── coderstory │ │ └── miui_toolkit │ │ ├── Activity │ │ ├── AboutActivity.java │ │ ├── DisableAppActivity.java │ │ ├── HelperActivity.java │ │ ├── MainActivity.java │ │ └── SplashActivity.java │ │ ├── Adapter │ │ ├── AppInfo.java │ │ └── AppInfoAdapter.java │ │ ├── XposedModule │ │ ├── CorePatch.java │ │ ├── MiuiRoot.java │ │ ├── RemoveAds.java │ │ ├── RemoveSearchBar.java │ │ ├── ThemePather.java │ │ ├── ThemePather2.java │ │ ├── ThemePather3.java │ │ └── isEnable.java │ │ ├── service │ │ └── UpdateService.java │ │ └── tools │ │ ├── CrashHelper │ │ ├── CrashApplication.java │ │ └── CrashHandler.java │ │ ├── Hosts │ │ ├── FileHelper.java │ │ └── HostsHelper.java │ │ ├── RequestPermissions.java │ │ ├── Root │ │ ├── ShellUtils.java │ │ └── SuHelper.java │ │ └── Update │ │ ├── CheckUpdate.java │ │ ├── HttpHelper.java │ │ └── UpdateConfig.java └── res │ ├── drawable │ ├── launcher_background.png │ ├── qr_alipay.png │ └── shooter.png │ ├── layout │ ├── activity_about.xml │ ├── activity_disable_app.xml │ ├── activity_helper.xml │ ├── activity_main.xml │ ├── activity_splash.xml │ └── app_info_item.xml │ ├── menu │ └── menu.xml │ ├── mipmap-xxhdpi │ └── launcher.png │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── test └── java └── com └── coderstory └── miui_toolkit └── ExampleUnitTest.java /README.md: -------------------------------------------------------------------------------- 1 | Mi Kit是个用于修改MIUI系统的Xposed模块 2 | 3 | 包含主题破解,下拉菜单搜索框隐藏,去广告,屏蔽系统更新, android核心校验破解等功能 4 | 5 | 项目采用GPL v2协议 6 | 7 | 已停止开发 8 | 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | def releaseTime() { 4 | return new Date().format("HH-mm-ss") 5 | } 6 | 7 | android { 8 | compileSdkVersion 24 9 | buildToolsVersion '24.0.1' 10 | 11 | // allprojects { 12 | // repositories { 13 | // mavenCentral() 14 | // } 15 | // } 16 | 17 | allprojects { 18 | repositories { 19 | jcenter() 20 | } 21 | } 22 | defaultConfig { 23 | applicationId "com.coderstory.miui_toolkit" 24 | minSdkVersion 19 25 | targetSdkVersion 24 26 | versionCode 78 27 | versionName '1.7.7' 28 | // jackOptions { 29 | // enabled true 30 | // } 31 | } 32 | buildTypes { 33 | release { 34 | shrinkResources true 35 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 36 | debuggable false 37 | jniDebuggable false 38 | renderscriptDebuggable false 39 | minifyEnabled true 40 | zipAlignEnabled true 41 | } 42 | debug { 43 | // minifyEnabled true 44 | } 45 | } 46 | // android.applicationVariants.all { variant -> 47 | // variant.outputs.each { output -> 48 | // def outputFile = output.outputFile 49 | // if (outputFile != null && outputFile.name.endsWith('.apk')) { 50 | // def fileName = "Mi Kit-${defaultConfig.versionCode}-${defaultConfig.versionName}-${releaseTime()}.apk" 51 | // output.outputFile = new File(outputFile.parent, fileName) 52 | // } 53 | // } 54 | // } 55 | productFlavors { 56 | } 57 | // dexOptions { 58 | // incremental true 59 | // } 60 | // compileOptions { 61 | // sourceCompatibility JavaVersion.VERSION_1_8 62 | // targetCompatibility JavaVersion.VERSION_1_8 63 | // } 64 | compileOptions { 65 | sourceCompatibility JavaVersion.VERSION_1_7 66 | targetCompatibility JavaVersion.VERSION_1_7 67 | } 68 | } 69 | 70 | dependencies { 71 | provided fileTree(include: ['*.jar'], dir: 'libs') 72 | // compile project(path: ':library') 73 | compile project(path: ':library') 74 | compile 'com.android.support:appcompat-v7:24.1.1' 75 | //51compile 'com.android.support:design:24.1.1' 76 | // provided 'com.android.support.constraint:constraint-layout:1.0.0-alpha4' 77 | compile 'com.umeng.analytics:analytics:latest.integration' 78 | provided 'junit:junit:4.12' 79 | provided 'de.robv.android.xposed:api:82' 80 | compile project(':drop') 81 | } 82 | 83 | buildscript { 84 | dependencies { 85 | classpath 'com.android.tools.build:gradle:2.2.0-beta1' 86 | } 87 | repositories { 88 | jcenter() 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/drop/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/drop/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion '24.0.1' 6 | 7 | defaultConfig { 8 | minSdkVersion 19 9 | targetSdkVersion 24 10 | } 11 | compileOptions { 12 | sourceCompatibility JavaVersion.VERSION_1_7 13 | targetCompatibility JavaVersion.VERSION_1_7 14 | } 15 | } 16 | 17 | dependencies { 18 | compile 'com.android.support:appcompat-v7:24.1.1' 19 | } 20 | 21 | -------------------------------------------------------------------------------- /app/drop/drop.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /app/drop/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_NAME=Phoenix 2 | POM_ARTIFACT_ID=phoenix 3 | POM_PACKAGING=aar -------------------------------------------------------------------------------- /app/drop/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /app/drop/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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/drop/local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | #Thu Apr 21 10:10:00 CST 2016 11 | sdk.dir=D\:\\JAVA_Project\\sdk 12 | -------------------------------------------------------------------------------- /app/drop/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/drop/src/main/java/com/yalantis/phoenix/refresh_view/BaseRefreshView.java: -------------------------------------------------------------------------------- 1 | package com.yalantis.phoenix.refresh_view; 2 | 3 | import android.content.Context; 4 | import android.graphics.ColorFilter; 5 | import android.graphics.PixelFormat; 6 | import android.graphics.drawable.Animatable; 7 | import android.graphics.drawable.Drawable; 8 | import android.support.annotation.NonNull; 9 | 10 | import com.yalantis.phoenix.PullToRefreshView; 11 | 12 | public abstract class BaseRefreshView extends Drawable implements Drawable.Callback, Animatable { 13 | 14 | private PullToRefreshView mRefreshLayout; 15 | private boolean mEndOfRefreshing; 16 | 17 | public BaseRefreshView(Context context, PullToRefreshView layout) { 18 | mRefreshLayout = layout; 19 | } 20 | 21 | public Context getContext() { 22 | return mRefreshLayout != null ? mRefreshLayout.getContext() : null; 23 | } 24 | 25 | public PullToRefreshView getRefreshLayout() { 26 | return mRefreshLayout; 27 | } 28 | 29 | public abstract void setPercent(float percent, boolean invalidate); 30 | 31 | public abstract void offsetTopAndBottom(int offset); 32 | 33 | @Override 34 | public void invalidateDrawable(@NonNull Drawable who) { 35 | final Callback callback = getCallback(); 36 | if (callback != null) { 37 | callback.invalidateDrawable(this); 38 | } 39 | } 40 | 41 | @Override 42 | public void scheduleDrawable(Drawable who, Runnable what, long when) { 43 | final Callback callback = getCallback(); 44 | if (callback != null) { 45 | callback.scheduleDrawable(this, what, when); 46 | } 47 | } 48 | 49 | @Override 50 | public void unscheduleDrawable(Drawable who, Runnable what) { 51 | final Callback callback = getCallback(); 52 | if (callback != null) { 53 | callback.unscheduleDrawable(this, what); 54 | } 55 | } 56 | 57 | @Override 58 | public int getOpacity() { 59 | return PixelFormat.TRANSLUCENT; 60 | } 61 | 62 | @Override 63 | public void setAlpha(int alpha) { 64 | 65 | } 66 | 67 | @Override 68 | public void setColorFilter(ColorFilter cf) { 69 | 70 | } 71 | 72 | /** 73 | * Our animation depend on type of current work of refreshing. 74 | * We should to do different things when it's end of refreshing 75 | * 76 | * @param endOfRefreshing - we will check current state of refresh with this 77 | */ 78 | public void setEndOfRefreshing(boolean endOfRefreshing) { 79 | mEndOfRefreshing = endOfRefreshing; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/drop/src/main/java/com/yalantis/phoenix/refresh_view/SunRefreshView.java: -------------------------------------------------------------------------------- 1 | package com.yalantis.phoenix.refresh_view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Rect; 9 | import android.graphics.drawable.Animatable; 10 | import android.view.animation.Animation; 11 | import android.view.animation.Interpolator; 12 | import android.view.animation.LinearInterpolator; 13 | import android.view.animation.Transformation; 14 | 15 | import com.yalantis.phoenix.PullToRefreshView; 16 | import com.yalantis.phoenix.R; 17 | import com.yalantis.phoenix.util.Utils; 18 | 19 | /** 20 | * Created by Oleksii Shliama on 22/12/2014. 21 | * https://dribbble.com/shots/1650317-Pull-to-Refresh-Rentals 22 | */ 23 | public class SunRefreshView extends BaseRefreshView implements Animatable { 24 | 25 | private static final float SCALE_START_PERCENT = 0.5f; 26 | private static final int ANIMATION_DURATION = 1000; 27 | 28 | private final static float SKY_RATIO = 0.65f; 29 | private static final float SKY_INITIAL_SCALE = 1.05f; 30 | 31 | private final static float TOWN_RATIO = 0.22f; 32 | private static final float TOWN_INITIAL_SCALE = 1.20f; 33 | private static final float TOWN_FINAL_SCALE = 1.30f; 34 | 35 | private static final float SUN_FINAL_SCALE = 0.75f; 36 | private static final float SUN_INITIAL_ROTATE_GROWTH = 1.2f; 37 | private static final float SUN_FINAL_ROTATE_GROWTH = 1.5f; 38 | 39 | private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); 40 | 41 | private PullToRefreshView mParent; 42 | private Matrix mMatrix; 43 | private Animation mAnimation; 44 | 45 | private int mTop; 46 | private int mScreenWidth; 47 | 48 | private int mSkyHeight; 49 | private float mSkyTopOffset; 50 | private float mSkyMoveOffset; 51 | 52 | private int mTownHeight; 53 | private float mTownInitialTopOffset; 54 | private float mTownFinalTopOffset; 55 | private float mTownMoveOffset; 56 | 57 | private int mSunSize = 100; 58 | private float mSunLeftOffset; 59 | private float mSunTopOffset; 60 | 61 | private float mPercent = 0.0f; 62 | private float mRotate = 0.0f; 63 | 64 | private Bitmap mSky; 65 | private Bitmap mSun; 66 | private Bitmap mTown; 67 | 68 | private boolean isRefreshing = false; 69 | 70 | public SunRefreshView(Context context, final PullToRefreshView parent) { 71 | super(context, parent); 72 | mParent = parent; 73 | mMatrix = new Matrix(); 74 | 75 | setupAnimations(); 76 | parent.post(new Runnable() { 77 | @Override 78 | public void run() { 79 | initiateDimens(parent.getWidth()); 80 | } 81 | }); 82 | } 83 | 84 | public void initiateDimens(int viewWidth) { 85 | if (viewWidth <= 0 || viewWidth == mScreenWidth) return; 86 | 87 | mScreenWidth = viewWidth; 88 | mSkyHeight = (int) (SKY_RATIO * mScreenWidth); 89 | mSkyTopOffset = (mSkyHeight * 0.38f); 90 | mSkyMoveOffset = Utils.convertDpToPixel(getContext(), 15); 91 | 92 | mTownHeight = (int) (TOWN_RATIO * mScreenWidth); 93 | mTownInitialTopOffset = (mParent.getTotalDragDistance() - mTownHeight * TOWN_INITIAL_SCALE); 94 | mTownFinalTopOffset = (mParent.getTotalDragDistance() - mTownHeight * TOWN_FINAL_SCALE); 95 | mTownMoveOffset = Utils.convertDpToPixel(getContext(), 10); 96 | 97 | mSunLeftOffset = 0.3f * (float) mScreenWidth; 98 | mSunTopOffset = (mParent.getTotalDragDistance() * 0.1f); 99 | 100 | mTop = -mParent.getTotalDragDistance(); 101 | 102 | createBitmaps(); 103 | } 104 | 105 | private void createBitmaps() { 106 | final BitmapFactory.Options options = new BitmapFactory.Options(); 107 | options.inPreferredConfig = Bitmap.Config.RGB_565; 108 | 109 | mSky = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sky, options); 110 | mSky = Bitmap.createScaledBitmap(mSky, mScreenWidth, mSkyHeight, true); 111 | mTown = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.buildings, options); 112 | mTown = Bitmap.createScaledBitmap(mTown, mScreenWidth, (int) (mScreenWidth * TOWN_RATIO), true); 113 | mSun = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sun, options); 114 | mSun = Bitmap.createScaledBitmap(mSun, mSunSize, mSunSize, true); 115 | } 116 | 117 | @Override 118 | public void setPercent(float percent, boolean invalidate) { 119 | setPercent(percent); 120 | if (invalidate) setRotate(percent); 121 | } 122 | 123 | @Override 124 | public void offsetTopAndBottom(int offset) { 125 | mTop += offset; 126 | invalidateSelf(); 127 | } 128 | 129 | @Override 130 | public void draw(Canvas canvas) { 131 | if (mScreenWidth <= 0) return; 132 | 133 | final int saveCount = canvas.save(); 134 | 135 | canvas.translate(0, mTop); 136 | canvas.clipRect(0, -mTop, mScreenWidth, mParent.getTotalDragDistance()); 137 | 138 | drawSky(canvas); 139 | drawSun(canvas); 140 | drawTown(canvas); 141 | 142 | canvas.restoreToCount(saveCount); 143 | } 144 | 145 | private void drawSky(Canvas canvas) { 146 | Matrix matrix = mMatrix; 147 | matrix.reset(); 148 | 149 | float dragPercent = Math.min(1f, Math.abs(mPercent)); 150 | 151 | float skyScale; 152 | float scalePercentDelta = dragPercent - SCALE_START_PERCENT; 153 | if (scalePercentDelta > 0) { 154 | /** Change skyScale between {@link #SKY_INITIAL_SCALE} and 1.0f depending on {@link #mPercent} */ 155 | float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT); 156 | skyScale = SKY_INITIAL_SCALE - (SKY_INITIAL_SCALE - 1.0f) * scalePercent; 157 | } else { 158 | skyScale = SKY_INITIAL_SCALE; 159 | } 160 | 161 | float offsetX = -(mScreenWidth * skyScale - mScreenWidth) / 2.0f; 162 | float offsetY = (1.0f - dragPercent) * mParent.getTotalDragDistance() - mSkyTopOffset // Offset canvas moving 163 | - mSkyHeight * (skyScale - 1.0f) / 2 // Offset sky scaling 164 | + mSkyMoveOffset * dragPercent; // Give it a little move top -> bottom 165 | 166 | matrix.postScale(skyScale, skyScale); 167 | matrix.postTranslate(offsetX, offsetY); 168 | canvas.drawBitmap(mSky, matrix, null); 169 | } 170 | 171 | private void drawTown(Canvas canvas) { 172 | Matrix matrix = mMatrix; 173 | matrix.reset(); 174 | 175 | float dragPercent = Math.min(1f, Math.abs(mPercent)); 176 | 177 | float townScale; 178 | float townTopOffset; 179 | float townMoveOffset; 180 | float scalePercentDelta = dragPercent - SCALE_START_PERCENT; 181 | if (scalePercentDelta > 0) { 182 | /** 183 | * Change townScale between {@link #TOWN_INITIAL_SCALE} and {@link #TOWN_FINAL_SCALE} depending on {@link #mPercent} 184 | * Change townTopOffset between {@link #mTownInitialTopOffset} and {@link #mTownFinalTopOffset} depending on {@link #mPercent} 185 | */ 186 | float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT); 187 | townScale = TOWN_INITIAL_SCALE + (TOWN_FINAL_SCALE - TOWN_INITIAL_SCALE) * scalePercent; 188 | townTopOffset = mTownInitialTopOffset - (mTownFinalTopOffset - mTownInitialTopOffset) * scalePercent; 189 | townMoveOffset = mTownMoveOffset * (1.0f - scalePercent); 190 | } else { 191 | float scalePercent = dragPercent / SCALE_START_PERCENT; 192 | townScale = TOWN_INITIAL_SCALE; 193 | townTopOffset = mTownInitialTopOffset; 194 | townMoveOffset = mTownMoveOffset * scalePercent; 195 | } 196 | 197 | float offsetX = -(mScreenWidth * townScale - mScreenWidth) / 2.0f; 198 | float offsetY = (1.0f - dragPercent) * mParent.getTotalDragDistance() // Offset canvas moving 199 | + townTopOffset 200 | - mTownHeight * (townScale - 1.0f) / 2 // Offset town scaling 201 | + townMoveOffset; // Give it a little move 202 | 203 | matrix.postScale(townScale, townScale); 204 | matrix.postTranslate(offsetX, offsetY); 205 | 206 | canvas.drawBitmap(mTown, matrix, null); 207 | } 208 | 209 | private void drawSun(Canvas canvas) { 210 | Matrix matrix = mMatrix; 211 | matrix.reset(); 212 | 213 | float dragPercent = mPercent; 214 | if (dragPercent > 1.0f) { // Slow down if pulling over set height 215 | dragPercent = (dragPercent + 9.0f) / 10; 216 | } 217 | 218 | float sunRadius = (float) mSunSize / 2.0f; 219 | float sunRotateGrowth = SUN_INITIAL_ROTATE_GROWTH; 220 | 221 | float offsetX = mSunLeftOffset; 222 | float offsetY = mSunTopOffset 223 | + (mParent.getTotalDragDistance() / 2) * (1.0f - dragPercent) // Move the sun up 224 | - mTop; // Depending on Canvas position 225 | 226 | float scalePercentDelta = dragPercent - SCALE_START_PERCENT; 227 | if (scalePercentDelta > 0) { 228 | float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT); 229 | float sunScale = 1.0f - (1.0f - SUN_FINAL_SCALE) * scalePercent; 230 | sunRotateGrowth += (SUN_FINAL_ROTATE_GROWTH - SUN_INITIAL_ROTATE_GROWTH) * scalePercent; 231 | 232 | matrix.preTranslate(offsetX + (sunRadius - sunRadius * sunScale), offsetY * (2.0f - sunScale)); 233 | matrix.preScale(sunScale, sunScale); 234 | 235 | offsetX += sunRadius; 236 | offsetY = offsetY * (2.0f - sunScale) + sunRadius * sunScale; 237 | } else { 238 | matrix.postTranslate(offsetX, offsetY); 239 | 240 | offsetX += sunRadius; 241 | offsetY += sunRadius; 242 | } 243 | 244 | matrix.postRotate( 245 | (isRefreshing ? -360 : 360) * mRotate * (isRefreshing ? 1 : sunRotateGrowth), 246 | offsetX, 247 | offsetY); 248 | 249 | canvas.drawBitmap(mSun, matrix, null); 250 | } 251 | 252 | public void setPercent(float percent) { 253 | mPercent = percent; 254 | } 255 | 256 | public void setRotate(float rotate) { 257 | mRotate = rotate; 258 | invalidateSelf(); 259 | } 260 | 261 | public void resetOriginals() { 262 | setPercent(0); 263 | setRotate(0); 264 | } 265 | 266 | @Override 267 | protected void onBoundsChange(Rect bounds) { 268 | super.onBoundsChange(bounds); 269 | } 270 | 271 | @Override 272 | public void setBounds(int left, int top, int right, int bottom) { 273 | super.setBounds(left, top, right, mSkyHeight + top); 274 | } 275 | 276 | @Override 277 | public boolean isRunning() { 278 | return false; 279 | } 280 | 281 | @Override 282 | public void start() { 283 | mAnimation.reset(); 284 | isRefreshing = true; 285 | mParent.startAnimation(mAnimation); 286 | } 287 | 288 | @Override 289 | public void stop() { 290 | mParent.clearAnimation(); 291 | isRefreshing = false; 292 | resetOriginals(); 293 | } 294 | 295 | private void setupAnimations() { 296 | mAnimation = new Animation() { 297 | @Override 298 | public void applyTransformation(float interpolatedTime, Transformation t) { 299 | setRotate(interpolatedTime); 300 | } 301 | }; 302 | mAnimation.setRepeatCount(Animation.INFINITE); 303 | mAnimation.setRepeatMode(Animation.RESTART); 304 | mAnimation.setInterpolator(LINEAR_INTERPOLATOR); 305 | mAnimation.setDuration(ANIMATION_DURATION); 306 | } 307 | 308 | } 309 | -------------------------------------------------------------------------------- /app/drop/src/main/java/com/yalantis/phoenix/util/Logger.java: -------------------------------------------------------------------------------- 1 | package com.yalantis.phoenix.util; 2 | 3 | import android.text.TextUtils; 4 | 5 | public final class Logger { 6 | 7 | private static final String TAG = "Phoenix"; 8 | 9 | /** 10 | * Set true or false if you want read logs or not 11 | */ 12 | private static boolean logEnabled_d = false; 13 | private static boolean logEnabled_i = false; 14 | private static boolean logEnabled_e = false; 15 | 16 | public static void d() { 17 | if (logEnabled_d) { 18 | android.util.Log.v(TAG, getLocation()); 19 | } 20 | } 21 | 22 | public static void d(String msg) { 23 | if (logEnabled_d) { 24 | android.util.Log.v(TAG, getLocation() + msg); 25 | } 26 | } 27 | 28 | public static void i(String msg) { 29 | if (logEnabled_i) { 30 | android.util.Log.i(TAG, getLocation() + msg); 31 | } 32 | } 33 | 34 | public static void i() { 35 | if (logEnabled_i) { 36 | android.util.Log.i(TAG, getLocation()); 37 | } 38 | } 39 | 40 | public static void e(String msg) { 41 | if (logEnabled_e) { 42 | android.util.Log.e(TAG, getLocation() + msg); 43 | } 44 | } 45 | 46 | public static void e(String msg, Throwable e) { 47 | if (logEnabled_e) { 48 | android.util.Log.e(TAG, getLocation() + msg, e); 49 | } 50 | } 51 | 52 | public static void e(Throwable e) { 53 | if (logEnabled_e) { 54 | android.util.Log.e(TAG, getLocation(), e); 55 | } 56 | } 57 | 58 | public static void e() { 59 | if (logEnabled_e) { 60 | android.util.Log.e(TAG, getLocation()); 61 | } 62 | } 63 | 64 | private static String getLocation() { 65 | final String className = Logger.class.getName(); 66 | final StackTraceElement[] traces = Thread.currentThread() 67 | .getStackTrace(); 68 | boolean found = false; 69 | 70 | for (StackTraceElement trace : traces) { 71 | try { 72 | if (found) { 73 | if (!trace.getClassName().startsWith(className)) { 74 | Class clazz = Class.forName(trace.getClassName()); 75 | return "[" + getClassName(clazz) + ":" 76 | + trace.getMethodName() + ":" 77 | + trace.getLineNumber() + "]: "; 78 | } 79 | } else if (trace.getClassName().startsWith(className)) { 80 | found = true; 81 | } 82 | } catch (ClassNotFoundException ignored) { 83 | } 84 | } 85 | 86 | return "[]: "; 87 | } 88 | 89 | private static String getClassName(Class clazz) { 90 | if (clazz != null) { 91 | if (!TextUtils.isEmpty(clazz.getSimpleName())) { 92 | return clazz.getSimpleName(); 93 | } 94 | 95 | return getClassName(clazz.getEnclosingClass()); 96 | } 97 | 98 | return ""; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /app/drop/src/main/java/com/yalantis/phoenix/util/Utils.java: -------------------------------------------------------------------------------- 1 | package com.yalantis.phoenix.util; 2 | 3 | import android.content.Context; 4 | 5 | public class Utils { 6 | 7 | public static int convertDpToPixel(Context context, int dp) { 8 | float density = context.getResources().getDisplayMetrics().density; 9 | return Math.round((float) dp * density); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-hdpi/buildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-hdpi/buildings.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-hdpi/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-hdpi/sky.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-hdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-hdpi/sun.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-mdpi/buildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-mdpi/buildings.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-mdpi/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-mdpi/sky.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-mdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-mdpi/sun.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xhdpi/buildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xhdpi/buildings.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xhdpi/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xhdpi/sky.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xhdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xhdpi/sun.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxhdpi/buildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxhdpi/buildings.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxhdpi/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxhdpi/sky.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxhdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxhdpi/sun.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxxhdpi/buildings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxxhdpi/buildings.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxxhdpi/sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxxhdpi/sky.png -------------------------------------------------------------------------------- /app/drop/src/main/res/drawable-xxxhdpi/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/drop/src/main/res/drawable-xxxhdpi/sun.png -------------------------------------------------------------------------------- /app/drop/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Wed Aug 10 20:28:11 CST 2016 16 | systemProp.http.proxyHost=127.0.0.1 17 | systemProp.http.proxyPort=1080 18 | -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 03 00:22:05 CST 2016 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-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /app/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /app/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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | compile 'com.android.support:appcompat-v7:24.1.1' 9 | } 10 | 11 | android { 12 | compileSdkVersion 24 13 | buildToolsVersion '24.0.1' 14 | 15 | defaultConfig { 16 | minSdkVersion 7 17 | targetSdkVersion 22 18 | versionCode 1 19 | versionName "1.0.0" 20 | } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_7 24 | targetCompatibility JavaVersion.VERSION_1_7 25 | } 26 | } -------------------------------------------------------------------------------- /app/library/build/generated/source/buildConfig/release/me/imid/swipebacklayout/lib/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Automatically generated file. DO NOT MODIFY 3 | */ 4 | package me.imid.swipebacklayout.lib; 5 | 6 | public final class BuildConfig { 7 | public static final boolean DEBUG = false; 8 | public static final String APPLICATION_ID = "me.imid.swipebacklayout.lib"; 9 | public static final String BUILD_TYPE = "release"; 10 | public static final String FLAVOR = ""; 11 | public static final int VERSION_CODE = 1; 12 | public static final String VERSION_NAME = "1.0.0"; 13 | } 14 | -------------------------------------------------------------------------------- /app/library/library.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /app/library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/library/src/main/java/me/imid/swipebacklayout/lib/Utils.java: -------------------------------------------------------------------------------- 1 | 2 | package me.imid.swipebacklayout.lib; 3 | 4 | import android.app.Activity; 5 | import android.app.ActivityOptions; 6 | import android.os.Build; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | 11 | public class Utils { 12 | private Utils() { 13 | } 14 | 15 | // /** 16 | // * Convert a translucent themed Activity 17 | // * {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque 18 | // * Activity. 19 | // *

20 | // * Call this whenever the background of a translucent Activity has changed 21 | // * to become opaque. Doing so will allow the {@link android.view.Surface} of 22 | // * the Activity behind to be released. 23 | // *

24 | // * This call has no effect on non-translucent activities or on activities 25 | // * with the {@link android.R.attr#windowIsFloating} attribute. 26 | // */ 27 | // private static void convertActivityFromTranslucent(Activity activity) { 28 | // try { 29 | // Method method = Activity.class.getDeclaredMethod("convertFromTranslucent"); 30 | // method.setAccessible(true); 31 | // method.invoke(activity); 32 | // } catch (Throwable ignored) { 33 | // } 34 | // } 35 | 36 | /** 37 | * Convert a translucent themed Activity 38 | * {@link android.R.attr#windowIsTranslucent} back from opaque to 39 | * translucent following a call to 40 | * {link #convertActivityFromTranslucent(android.app.Activity)} . 41 | *

42 | * Calling this allows the Activity behind this one to be seen again. Once 43 | * all such Activities have been redrawn 44 | *

45 | * This call has no effect on non-translucent activities or on activities 46 | * with the {@link android.R.attr#windowIsFloating} attribute. 47 | */ 48 | public static void convertActivityToTranslucent(Activity activity) { 49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 50 | convertActivityToTranslucentAfterL(activity); 51 | } else { 52 | convertActivityToTranslucentBeforeL(activity); 53 | } 54 | } 55 | 56 | /** 57 | * Calling the convertToTranslucent method on platforms before Android 5.0 58 | */ 59 | private static void convertActivityToTranslucentBeforeL(Activity activity) { 60 | try { 61 | Class[] classes = Activity.class.getDeclaredClasses(); 62 | Class translucentConversionListenerClazz = null; 63 | for (Class clazz : classes) { 64 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 65 | translucentConversionListenerClazz = clazz; 66 | } 67 | } 68 | Method method = Activity.class.getDeclaredMethod("convertToTranslucent", 69 | translucentConversionListenerClazz); 70 | method.setAccessible(true); 71 | method.invoke(activity, new Object[] { 72 | null 73 | }); 74 | } catch (Throwable ignored) { 75 | } 76 | } 77 | 78 | /** 79 | * Calling the convertToTranslucent method on platforms after Android 5.0 80 | */ 81 | private static void convertActivityToTranslucentAfterL(Activity activity) { 82 | try { 83 | Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions"); 84 | getActivityOptions.setAccessible(true); 85 | Object options = getActivityOptions.invoke(activity); 86 | 87 | Class[] classes = Activity.class.getDeclaredClasses(); 88 | Class translucentConversionListenerClazz = null; 89 | for (Class clazz : classes) { 90 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 91 | translucentConversionListenerClazz = clazz; 92 | } 93 | } 94 | Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent", 95 | translucentConversionListenerClazz, ActivityOptions.class); 96 | convertToTranslucent.setAccessible(true); 97 | convertToTranslucent.invoke(activity, null, options); 98 | } catch (Throwable ignored) { 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/library/src/main/java/me/imid/swipebacklayout/lib/app/SwipeBackActivity.java: -------------------------------------------------------------------------------- 1 | 2 | package me.imid.swipebacklayout.lib.app; 3 | 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 9 | import me.imid.swipebacklayout.lib.Utils; 10 | 11 | public class SwipeBackActivity extends AppCompatActivity implements SwipeBackActivityBase { 12 | private SwipeBackActivityHelper mHelper; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | mHelper = new SwipeBackActivityHelper(this); 18 | mHelper.onActivityCreate(); 19 | } 20 | 21 | @Override 22 | protected void onPostCreate(Bundle savedInstanceState) { 23 | super.onPostCreate(savedInstanceState); 24 | mHelper.onPostCreate(); 25 | } 26 | 27 | @Override 28 | public View findViewById(int id) { 29 | View v = super.findViewById(id); 30 | if (v == null && mHelper != null) 31 | return mHelper.findViewById(id); 32 | return v; 33 | } 34 | 35 | @Override 36 | public SwipeBackLayout getSwipeBackLayout() { 37 | return mHelper.getSwipeBackLayout(); 38 | } 39 | 40 | @Override 41 | public void setSwipeBackEnable(boolean enable) { 42 | getSwipeBackLayout().setEnableGesture(enable); 43 | } 44 | 45 | @Override 46 | public void scrollToFinishActivity() { 47 | Utils.convertActivityToTranslucent(this); 48 | getSwipeBackLayout().scrollToFinishActivity(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/library/src/main/java/me/imid/swipebacklayout/lib/app/SwipeBackActivityBase.java: -------------------------------------------------------------------------------- 1 | package me.imid.swipebacklayout.lib.app; 2 | 3 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 4 | /** 5 | * @author Yrom 6 | */ 7 | public interface SwipeBackActivityBase { 8 | /** 9 | * @return the SwipeBackLayout associated with this activity. 10 | */ 11 | SwipeBackLayout getSwipeBackLayout(); 12 | 13 | void setSwipeBackEnable(boolean enable); 14 | 15 | /** 16 | * Scroll out contentView and finish the activity 17 | */ 18 | public abstract void scrollToFinishActivity(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/library/src/main/java/me/imid/swipebacklayout/lib/app/SwipeBackActivityHelper.java: -------------------------------------------------------------------------------- 1 | package me.imid.swipebacklayout.lib.app; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.ColorDrawable; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | 9 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 10 | import me.imid.swipebacklayout.lib.Utils; 11 | 12 | /** 13 | * @author Yrom 14 | */ 15 | public class SwipeBackActivityHelper { 16 | private Activity mActivity; 17 | 18 | private SwipeBackLayout mSwipeBackLayout; 19 | 20 | public SwipeBackActivityHelper(Activity activity) { 21 | mActivity = activity; 22 | } 23 | 24 | @SuppressWarnings("deprecation") 25 | public void onActivityCreate() { 26 | mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 27 | mActivity.getWindow().getDecorView().setBackgroundDrawable(null); 28 | mSwipeBackLayout = (SwipeBackLayout) LayoutInflater.from(mActivity).inflate( 29 | me.imid.swipebacklayout.lib.R.layout.swipeback_layout, null); 30 | mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { 31 | @Override 32 | public void onScrollStateChange(int state, float scrollPercent) { 33 | } 34 | 35 | @Override 36 | public void onEdgeTouch(int edgeFlag) { 37 | Utils.convertActivityToTranslucent(mActivity); 38 | } 39 | 40 | @Override 41 | public void onScrollOverThreshold() { 42 | 43 | } 44 | }); 45 | } 46 | 47 | public void onPostCreate() { 48 | mSwipeBackLayout.attachToActivity(mActivity); 49 | } 50 | 51 | public View findViewById(int id) { 52 | if (mSwipeBackLayout != null) { 53 | return mSwipeBackLayout.findViewById(id); 54 | } 55 | return null; 56 | } 57 | 58 | public SwipeBackLayout getSwipeBackLayout() { 59 | return mSwipeBackLayout; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/library/src/main/java/me/imid/swipebacklayout/lib/app/SwipeBackPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | 2 | package me.imid.swipebacklayout.lib.app; 3 | 4 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 5 | import android.os.Bundle; 6 | import android.preference.PreferenceActivity; 7 | import android.view.View; 8 | 9 | public class SwipeBackPreferenceActivity extends PreferenceActivity implements SwipeBackActivityBase { 10 | private SwipeBackActivityHelper mHelper; 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | mHelper = new SwipeBackActivityHelper(this); 16 | mHelper.onActivityCreate(); 17 | } 18 | 19 | @Override 20 | protected void onPostCreate(Bundle savedInstanceState) { 21 | super.onPostCreate(savedInstanceState); 22 | mHelper.onPostCreate(); 23 | } 24 | 25 | @Override 26 | public View findViewById(int id) { 27 | View v = super.findViewById(id); 28 | if (v == null && mHelper != null) 29 | return mHelper.findViewById(id); 30 | return v; 31 | } 32 | 33 | @Override 34 | public SwipeBackLayout getSwipeBackLayout() { 35 | return mHelper.getSwipeBackLayout(); 36 | } 37 | @Override 38 | public void setSwipeBackEnable(boolean enable) { 39 | getSwipeBackLayout().setEnableGesture(enable); 40 | } 41 | 42 | @Override 43 | public void scrollToFinishActivity() { 44 | getSwipeBackLayout().scrollToFinishActivity(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/library/src/main/res/drawable-xhdpi/shadow_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/library/src/main/res/drawable-xhdpi/shadow_bottom.png -------------------------------------------------------------------------------- /app/library/src/main/res/drawable-xhdpi/shadow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/library/src/main/res/drawable-xhdpi/shadow_left.png -------------------------------------------------------------------------------- /app/library/src/main/res/drawable-xhdpi/shadow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/library/src/main/res/drawable-xhdpi/shadow_right.png -------------------------------------------------------------------------------- /app/library/src/main/res/layout/swipeback_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/libs/api-82-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/libs/api-82-sources.jar -------------------------------------------------------------------------------- /app/libs/api-82.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/libs/api-82.jar -------------------------------------------------------------------------------- /app/libs/umeng-analytics-v6.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/libs/umeng-analytics-v6.0.1.jar -------------------------------------------------------------------------------- /app/libs/utdid4all-1.0.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/libs/utdid4all-1.0.4.jar -------------------------------------------------------------------------------- /app/local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | #Fri Aug 12 19:24:09 CST 2016 11 | sdk.dir=D\:\\Application\\sdk 12 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #指定代码的压缩级别 2 | -optimizationpasses 7 3 | #包明不混合大小写 4 | -dontusemixedcaseclassnames 5 | #不去忽略非公共的库类 6 | -dontskipnonpubliclibraryclasses 7 | #优化 不优化输入的类文件 8 | -dontoptimize 9 | #预校验 10 | -dontpreverify 11 | #混淆时是否记录日志 12 | -verbose 13 | #混淆时所采用的算法 14 | -optimizations !code/simplification/arithmetic,!field/,!class/merging/ 15 | #保护注解 16 | -keepattributes Annotation 17 | #保持哪些类不被混淆 18 | -keep public class com.coderstory.miui_toolkit.XposedModule.** 19 | -keep class com.coderstory.miui_toolkit.Activity.MainActivity { 20 | boolean isEnable(); 21 | } 22 | -keepclassmembers class * { 23 | public (org.json.JSONObject); 24 | } 25 | -keep public class com.coderstory.miui_toolkit.R$*{ 26 | public static final int *; 27 | } 28 | -keepclassmembers enum * { 29 | public static **[] values(); 30 | public static ** valueOf(java.lang.String); 31 | } 32 | -keep public class com.umeng.fb.ui.ThreadView { 33 | } 34 | #如果有引用v4包可以添加下面这行 35 | -keep public class * extends android.support.v4.app.Fragment 36 | -keep public class * extends android.support.v7.app.Fragment 37 | #忽略警告 38 | -ignorewarning 39 | #记录生成的日志数据,gradle build时在本项目根目录输出 40 | #apk 包内所有 class 的内部结构 41 | -dump class_files.txt 42 | #未混淆的类和成员 43 | -printseeds seeds.txt 44 | #列出从 apk 中删除的代码 45 | -printusage unused.txt 46 | #混淆前后的映射 47 | -printmapping mapping.txt -------------------------------------------------------------------------------- /app/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':library', ':drop' -------------------------------------------------------------------------------- /app/src/androidTest/java/com/coderstory/miui_toolkit/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 59 | 60 | 61 | 62 | 65 | 68 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/src/main/assets/hosts_nostore: -------------------------------------------------------------------------------- 1 | 2 | 127.0.0.1 live.zdworkscdn.com 3 | 127.0.0.1 music.search.xiaomi.net 4 | 127.0.0.1 img.zdworkscdn.com 5 | 127.0.0.1 video.xiaomi.com 6 | 127.0.0.1 app.market.xiaomi.com 7 | 127.0.0.1 image.cdn.mvideo.xiaomi.com 8 | 127.0.0.1 mvideo.duokanbox.com -------------------------------------------------------------------------------- /app/src/main/assets/hosts_noup: -------------------------------------------------------------------------------- 1 | 2 | 127.0.0.1 update.miui.com -------------------------------------------------------------------------------- /app/src/main/assets/none: -------------------------------------------------------------------------------- 1 | 127.0.0.1 localhost 2 | 255.255.255.255 broadcasthost 3 | ::1 localhost 4 | fe80::1%lo0 localhost -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.coderstory.miui_toolkit.XposedModule.CorePatch 2 | com.coderstory.miui_toolkit.XposedModule.RemoveAds 3 | com.coderstory.miui_toolkit.XposedModule.RemoveSearchBar 4 | com.coderstory.miui_toolkit.XposedModule.ThemePather 5 | com.coderstory.miui_toolkit.XposedModule.ThemePather2 6 | com.coderstory.miui_toolkit.XposedModule.ThemePather3 7 | com.coderstory.miui_toolkit.XposedModule.MiuiRoot 8 | com.coderstory.miui_toolkit.XposedModule.isEnable -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Activity/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Activity; 2 | 3 | 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | 9 | import com.coderstory.miui_toolkit.R; 10 | import com.umeng.analytics.MobclickAgent; 11 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 12 | import me.imid.swipebacklayout.lib.app.SwipeBackActivity; 13 | 14 | public class AboutActivity extends SwipeBackActivity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_about); 20 | getSwipeBackLayout().setSwipeMode(SwipeBackLayout.FULL_SCREEN_LEFT); 21 | getSwipeBackLayout().setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT); 22 | } 23 | 24 | //打开我的博客 25 | public void openMyBlog(View view) { 26 | Intent intent = new Intent(Intent.ACTION_VIEW); 27 | intent.setData(Uri.parse(getString(R.string.myblog_url))); 28 | startActivity(intent); 29 | 30 | } 31 | //打开支付宝 32 | public void openAlipay(View view) { 33 | // Toast.makeText(this, "",Toast.LENGTH_LONG).show(); 34 | Intent intent = new Intent(Intent.ACTION_VIEW); 35 | intent.setData(Uri.parse(getString(R.string.alipay_url))); 36 | startActivity(intent); 37 | } 38 | 39 | @Override 40 | protected void onResume() { 41 | super.onResume(); 42 | MobclickAgent.onResume(this); 43 | } 44 | @Override 45 | protected void onPause() { 46 | super.onPause(); 47 | MobclickAgent.onPause(this); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Activity/DisableAppActivity.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Activity; 2 | 3 | import android.app.AlertDialog; 4 | import android.app.Dialog; 5 | import android.app.ProgressDialog; 6 | import android.content.DialogInterface; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageInfo; 9 | import android.graphics.Color; 10 | import android.os.AsyncTask; 11 | import android.os.Bundle; 12 | import android.os.Looper; 13 | import android.support.v7.app.AppCompatActivity; 14 | import android.util.Log; 15 | import android.view.View; 16 | import android.widget.AdapterView; 17 | import android.widget.ListView; 18 | import android.widget.Toast; 19 | 20 | import com.coderstory.miui_toolkit.Adapter.AppInfo; 21 | import com.coderstory.miui_toolkit.Adapter.AppInfoAdapter; 22 | import com.coderstory.miui_toolkit.R; 23 | import com.umeng.analytics.MobclickAgent; 24 | import com.yalantis.phoenix.PullToRefreshView; 25 | 26 | import java.io.DataOutputStream; 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public class DisableAppActivity extends AppCompatActivity { 31 | 32 | 33 | private List appInfoList = new ArrayList<>(); 34 | private List appInfoList2 = new ArrayList<>(); 35 | // private Context mContext=null; 36 | List packages=new ArrayList<>(); 37 | AppInfoAdapter adapter=null; 38 | ListView listView=null; 39 | AppInfo appInfo=null ; 40 | int mposition=0; 41 | View mview=null; 42 | com.yalantis.phoenix.PullToRefreshView mPullToRefreshView; 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.activity_disable_app); 48 | // mContext = DisableAppActivity.this; 49 | Toast.makeText(this, R.string.disableapptips,Toast.LENGTH_LONG).show(); 50 | 51 | 52 | 53 | new MyTask().execute(); 54 | 55 | mPullToRefreshView = (PullToRefreshView) findViewById(R.id.pull_to_refresh); 56 | 57 | mPullToRefreshView.setOnRefreshListener(new PullToRefreshView.OnRefreshListener() { 58 | @Override 59 | public void onRefresh() { 60 | mPullToRefreshView.postDelayed(new Runnable() { 61 | @Override 62 | public void run() { 63 | initData(); 64 | showData(); 65 | adapter.notifyDataSetChanged(); 66 | mPullToRefreshView.setRefreshing(false); 67 | } 68 | }, 2000); 69 | } 70 | }); 71 | 72 | } 73 | 74 | private void initFruit() { 75 | //packageInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM)==0 表示是系统应用 76 | appInfoList.clear(); 77 | appInfoList2.clear(); 78 | for (int i = 0; i < packages.size(); i++) { 79 | PackageInfo packageInfo = packages.get(i); 80 | if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) { 81 | if (packageInfo.applicationInfo.enabled) { 82 | AppInfo appInfo = new AppInfo(packageInfo.applicationInfo.loadLabel(getPackageManager()).toString(), packageInfo.applicationInfo.loadIcon(getPackageManager()), packageInfo.packageName, false, String.valueOf(packageInfo.versionName)); 83 | appInfoList.add(appInfo); 84 | } else { 85 | AppInfo appInfo = new AppInfo(packageInfo.applicationInfo.loadLabel(getPackageManager()).toString(), packageInfo.applicationInfo.loadIcon(getPackageManager()), packageInfo.packageName, true, String.valueOf(packageInfo.versionName)); 86 | appInfoList2.add(appInfo); 87 | } 88 | } 89 | } 90 | appInfoList.addAll(appInfoList2); 91 | } 92 | 93 | private void initData() 94 | { 95 | packages = new ArrayList<>(); 96 | packages = getPackageManager().getInstalledPackages(0); 97 | initFruit(); 98 | } 99 | 100 | private void showData() 101 | { 102 | adapter = new AppInfoAdapter(this, R.layout.app_info_item,appInfoList); 103 | listView = (ListView) findViewById(R.id.listView); 104 | assert listView != null; 105 | listView.setAdapter(adapter); 106 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 107 | @Override 108 | public void onItemClick(AdapterView parent, View view, int position, long id) { 109 | mposition = position; 110 | mview=view; 111 | AlertDialog.Builder dialog = new AlertDialog.Builder(DisableAppActivity.this); 112 | dialog.setTitle(R.string.Tips_Title); 113 | String tipsText; 114 | String BtnText=getString(R.string.Btn_Sure) ; 115 | appInfo = appInfoList.get(mposition); 116 | if (appInfo.getDisable()) { 117 | tipsText = getString(R.string.sureAntiDisable)+appInfo.getName()+getString(R.string.sureAntiDisableAfter); 118 | }else { 119 | tipsText = getString(R.string.sureDisable)+appInfo.getName() +getString(R.string.sureDisableAfter); 120 | } 121 | dialog.setMessage(tipsText); 122 | dialog.setPositiveButton(BtnText, new DialogInterface.OnClickListener() { 123 | @Override 124 | public void onClick(DialogInterface dialog, int which) { 125 | String commandText = "pm disable " + appInfo.getPackageName(); 126 | Log.e("cc", commandText); 127 | Process process = null; 128 | DataOutputStream os = null; 129 | try { 130 | if (appInfo.getDisable() ) { 131 | commandText = "pm enable " + appInfo.getPackageName(); 132 | } 133 | String cmd = commandText; 134 | process = Runtime.getRuntime().exec("su"); //切换到root帐号 135 | os = new DataOutputStream(process.getOutputStream()); 136 | os.writeBytes(cmd + "\n"); 137 | os.writeBytes("exit\n"); 138 | os.flush(); 139 | process.waitFor(); 140 | // View rootView = LayoutInflater.from(mContext).inflate(R.layout.app_info_item, null); 141 | if (appInfo.getDisable()) { 142 | appInfo.setDisable(false); 143 | appInfoList.set(mposition, appInfo); 144 | mview.setBackgroundColor(Color.parseColor("#d027b6d2")); //正常的颜色 145 | } else { 146 | appInfo.setDisable(true); 147 | appInfoList.set(mposition, appInfo); 148 | mview.setBackgroundColor(Color.parseColor("#d0d7d7d7")); //冻结的颜色 149 | 150 | } 151 | } catch (Exception ignored) { 152 | 153 | } finally { 154 | try { 155 | if (os != null) { 156 | os.close(); 157 | } 158 | assert process != null; 159 | process.destroy(); 160 | } catch (Exception ignored) { 161 | } 162 | } 163 | } 164 | }); 165 | dialog.setCancelable(true); 166 | dialog.setNegativeButton(R.string.Btn_Cancel, new DialogInterface.OnClickListener() { 167 | @Override 168 | public void onClick(DialogInterface dialog, int which) { 169 | dialog.cancel(); 170 | } 171 | }); 172 | dialog.show(); 173 | } 174 | }); 175 | } 176 | 177 | 178 | class MyTask extends AsyncTask { 179 | 180 | @Override 181 | protected void onPreExecute() { 182 | // setProgressBarIndeterminateVisibility(true); 183 | showProgress(); 184 | } 185 | 186 | @Override 187 | protected void onPostExecute(String param) { 188 | showData(); 189 | //setProgressBarIndeterminateVisibility(false); 190 | adapter.notifyDataSetChanged(); 191 | closeProgress(); 192 | } 193 | 194 | 195 | 196 | @Override 197 | protected String doInBackground(String... params) { 198 | Looper.prepare(); 199 | initData(); 200 | return null; 201 | } 202 | } 203 | 204 | private Dialog dialog; 205 | protected void showProgress() { 206 | if(dialog == null) { 207 | // dialog.setContentView(R.layout.progress_dialog); 208 | // dialog.getWindow().setAttributes(params); 209 | dialog = ProgressDialog.show(this,getString( R.string.Tips_Title), getString(R.string.loadappinfo)); 210 | dialog.show(); 211 | } 212 | } 213 | // 214 | protected void closeProgress() { 215 | 216 | if(dialog != null) { 217 | dialog.cancel(); 218 | dialog = null; 219 | } 220 | } 221 | 222 | 223 | @Override 224 | protected void onResume() { 225 | super.onResume(); 226 | MobclickAgent.onResume(this); 227 | } 228 | @Override 229 | protected void onPause() { 230 | super.onPause(); 231 | MobclickAgent.onPause(this); 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Activity/HelperActivity.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Activity; 2 | 3 | import android.os.Bundle; 4 | import android.text.Html; 5 | import android.text.method.LinkMovementMethod; 6 | import android.widget.TextView; 7 | 8 | import com.coderstory.miui_toolkit.R; 9 | import com.umeng.analytics.MobclickAgent; 10 | import me.imid.swipebacklayout.lib.SwipeBackLayout; 11 | import me.imid.swipebacklayout.lib.app.SwipeBackActivity; 12 | 13 | public class HelperActivity extends SwipeBackActivity { 14 | 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_helper); 20 | getSwipeBackLayout().setSwipeMode(SwipeBackLayout.EDGE_LEFT); 21 | getSwipeBackLayout().setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT); 22 | TextView tv =(TextView)findViewById(R.id.helptext); 23 | tv.setMovementMethod(LinkMovementMethod.getInstance()); 24 | tv.setText(Html.fromHtml(getString(R.string.texts))); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | MobclickAgent.onResume(this); 31 | } 32 | @Override 33 | protected void onPause() { 34 | super.onPause(); 35 | MobclickAgent.onPause(this); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Activity/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Activity; 2 | 3 | import android.content.Intent; 4 | import android.os.AsyncTask; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import com.coderstory.miui_toolkit.R; 9 | import com.umeng.analytics.MobclickAgent; 10 | 11 | 12 | public class SplashActivity extends AppCompatActivity { 13 | private static final int SHOW_TIME_MIN = 1500; 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_splash); 18 | 19 | //倒计时返回主界面 20 | new AsyncTask() { 21 | @Override 22 | protected void onPostExecute(Integer result) { 23 | Intent intent = new Intent(SplashActivity.this,MainActivity.class); 24 | startActivity(intent); 25 | finish(); 26 | } 27 | @Override 28 | protected Integer doInBackground(Void... params) { 29 | long startTime = System.currentTimeMillis(); 30 | long loadingTime = System.currentTimeMillis() - startTime; 31 | if (loadingTime < SHOW_TIME_MIN) { 32 | try { 33 | Thread.sleep(SHOW_TIME_MIN - loadingTime); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | return 1; 39 | } 40 | }.execute(); 41 | } 42 | 43 | @Override 44 | protected void onResume() { 45 | super.onResume(); 46 | MobclickAgent.onResume(this); 47 | } 48 | @Override 49 | protected void onPause() { 50 | super.onPause(); 51 | MobclickAgent.onPause(this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Adapter/AppInfo.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Adapter; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | /** 6 | * Created by cc on 2015/12/11. 单个app info的模型 7 | */ 8 | public class AppInfo { 9 | 10 | //public AppInfo() { 11 | //} 12 | 13 | private String name; 14 | private Drawable imageId; 15 | // private String AppDir; 16 | private boolean isDisable = true; 17 | private String packageName = ""; 18 | private String Version=""; 19 | 20 | //public void setAppDir(String AppDir) {this.AppDir=AppDir;} 21 | public void setDisable(boolean disable) { 22 | this.isDisable = disable; 23 | } 24 | 25 | Drawable getImageId() { 26 | return this.imageId; 27 | } 28 | public String getVersion() { 29 | return this.Version; 30 | } 31 | public String getPackageName() { 32 | return packageName; 33 | } 34 | public String getName() { 35 | return this.name; 36 | } 37 | //public String getappdir() { 38 | // return this.AppDir; 39 | //} 40 | public boolean getDisable() { 41 | return isDisable; 42 | } 43 | 44 | public AppInfo(String name, Drawable imageId, String packageName, boolean Disable,String version) { 45 | this.name = name; 46 | this.imageId = imageId; 47 | this.packageName = packageName; 48 | this.isDisable = Disable; 49 | //this.AppDir = appdir; 50 | this.Version=version; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/Adapter/AppInfoAdapter.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.Adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ArrayAdapter; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.coderstory.miui_toolkit.R; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Created by cc on 2015/12/11. 18 | */ 19 | public class AppInfoAdapter extends ArrayAdapter { 20 | private int resourceId; 21 | 22 | public AppInfoAdapter(Context context, int textViewResourceId, List objects) 23 | { 24 | super(context,textViewResourceId,objects); 25 | resourceId=textViewResourceId; 26 | } 27 | @Override 28 | public View getView (int position ,View convertView,ViewGroup parent) 29 | { 30 | AppInfo appInfo = (AppInfo) getItem(position); 31 | View view= LayoutInflater.from(getContext()).inflate(resourceId,null); 32 | ImageView imageView= (ImageView) view.findViewById(R.id.app_image); 33 | TextView textView= (TextView) view.findViewById(R.id.app_name); 34 | 35 | textView.setTag(appInfo.getPackageName()); 36 | imageView.setImageDrawable(appInfo.getImageId()); 37 | textView.setText(" 应用名 : "+appInfo.getName()+"\r\n 版本号 : "+appInfo.getVersion()); 38 | if(appInfo.getDisable()){ 39 | view.setBackgroundColor(Color.parseColor("#d0d7d7d7")); //冻结的颜色 40 | } 41 | return view; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/CorePatch.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.util.Base64; 7 | import de.robv.android.xposed.IXposedHookLoadPackage; 8 | import de.robv.android.xposed.IXposedHookZygoteInit; 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XSharedPreferences; 11 | import de.robv.android.xposed.XposedBridge; 12 | import de.robv.android.xposed.XposedHelpers; 13 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 14 | 15 | 16 | /** 17 | * Created by CoderStory on 2016/6/4. 18 | */ 19 | public class CorePatch implements IXposedHookZygoteInit, IXposedHookLoadPackage { 20 | private Context PMcontext = null; 21 | // private Context ctx = null; 22 | 23 | public void initZygote(IXposedHookZygoteInit.StartupParam paramStartupParam) 24 | throws Throwable { 25 | final XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 26 | prefs.makeWorldReadable(); 27 | 28 | //XposedHelpers.findClass("android.content.pm.PackageParser", null); 29 | // XposedHelpers.findClass("java.util.jar.JarVerifier$VerifierEntry", null); 30 | 31 | XposedBridge.hookAllMethods(XposedHelpers.findClass("com.android.org.conscrypt.OpenSSLSignature", null), "engineVerify", new XC_MethodHook() { 32 | protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 33 | throws Throwable { 34 | prefs.reload(); 35 | if (prefs.getBoolean("CorePatcher", false)) { 36 | paramAnonymousMethodHookParam.setResult(true); 37 | } 38 | 39 | } 40 | }); 41 | 42 | XposedHelpers.findAndHookMethod("java.security.MessageDigest", null, "isEqual", byte[].class, byte[].class, new XC_MethodHook() { 43 | protected void beforeHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 44 | throws Throwable { 45 | prefs.reload(); 46 | if (prefs.getBoolean("CorePatcher", false)) { 47 | paramAnonymousMethodHookParam.setResult(true); 48 | } 49 | 50 | } 51 | }); 52 | 53 | XposedHelpers.findAndHookMethod("java.security.Signature", null, "verify", byte[].class, new XC_MethodHook() { 54 | protected void beforeHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 55 | throws Throwable { 56 | prefs.reload(); 57 | if (prefs.getBoolean("CorePatcher", false)) { 58 | if (((((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("sha1withrsa")) || (((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("rsa-sha1")) || (((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("1.3.14.3.2.26with1.2.840.113549.1.1.1"))) &&( XposedHelpers.getIntField(paramAnonymousMethodHookParam.thisObject, "state") == 3)) { 59 | paramAnonymousMethodHookParam.setResult(true); 60 | } 61 | } 62 | 63 | } 64 | }); 65 | 66 | XposedHelpers.findAndHookMethod("java.security.Signature", null, "verify", byte[].class, Integer.TYPE, Integer.TYPE, new XC_MethodHook() { 67 | protected void beforeHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 68 | throws Throwable { 69 | prefs.reload(); 70 | if (prefs.getBoolean("CorePatcher", false)) { 71 | if (((((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("sha1withrsa")) || (((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("rsa-sha1")) || (((java.security.Signature) paramAnonymousMethodHookParam.thisObject).getAlgorithm().toLowerCase().equals("1.3.14.3.2.26with1.2.840.113549.1.1.1"))) && (XposedHelpers.getIntField(paramAnonymousMethodHookParam.thisObject, "state") == 3)) { 72 | paramAnonymousMethodHookParam.setResult(true); 73 | } 74 | } 75 | 76 | } 77 | }); 78 | } 79 | 80 | @Override 81 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) 82 | throws Throwable { 83 | final XSharedPreferences prefs = new XSharedPreferences("com.coderstory.toolkit", "UserSettings"); 84 | prefs.makeWorldReadable(); 85 | if (("android".equals(paramLoadPackageParam.packageName)) && (paramLoadPackageParam.processName.equals("android"))) { 86 | 87 | Class localClass = XposedHelpers.findClass("com.android.server.pm.PackageManagerService", paramLoadPackageParam.classLoader); 88 | 89 | XposedBridge.hookAllConstructors(XposedHelpers.findClass("com.android.server.pm.PackageManagerService", paramLoadPackageParam.classLoader), new XC_MethodHook() { 90 | protected void afterHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 91 | throws Throwable { 92 | prefs.reload(); 93 | if (!prefs.getBoolean("CorePatcher", false)) { 94 | return; 95 | } 96 | PMcontext = ((Context) paramAnonymousMethodHookParam.args[0]); 97 | } 98 | }); 99 | XposedBridge.hookAllMethods(localClass, "compareSignatures", new XC_MethodHook() { 100 | protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 101 | throws Throwable { 102 | 103 | prefs.reload(); 104 | if (!prefs.getBoolean("CorePatcher", false)) { 105 | return; 106 | } 107 | 108 | PackageInfo localObject; 109 | int k; 110 | int j; 111 | android.content.pm.Signature[] arrayOfSignature2; 112 | int i; 113 | int m; 114 | String tmpStr; 115 | try { 116 | localObject = PMcontext.getPackageManager().getPackageInfo("android", PackageManager.GET_SIGNATURES); 117 | if (localObject.signatures[0] == null) { 118 | return; 119 | } 120 | tmpStr = Base64.encodeToString(localObject.signatures[0].toByteArray(), 0).replaceAll("\n", ""); 121 | k = 0; 122 | j = 0; 123 | android.content.pm.Signature[] arrayOfSignature1 = (android.content.pm.Signature[]) paramAnonymousMethodHookParam.args[0]; 124 | arrayOfSignature2 = (android.content.pm.Signature[]) paramAnonymousMethodHookParam.args[1]; 125 | i = k; 126 | if (arrayOfSignature1 != null) { 127 | i = k; 128 | if (arrayOfSignature1.length > 0) { 129 | m = arrayOfSignature1.length; 130 | k = 0; 131 | for (; ; ) { 132 | i = j; 133 | if (k >= m) { 134 | break; 135 | } 136 | if (Base64.encodeToString(arrayOfSignature1[k].toByteArray(), 0).replaceAll("\n", "").equals(tmpStr)) { 137 | j = 1; 138 | } 139 | k += 1; 140 | } 141 | } 142 | } 143 | k = i; 144 | } catch (Exception p2) { 145 | p2.printStackTrace(); 146 | return; 147 | } 148 | if (arrayOfSignature2 != null) { 149 | k = i; 150 | if (arrayOfSignature2.length > 0) { 151 | m = arrayOfSignature2.length; 152 | j = 0; 153 | for (; ; ) { 154 | k = i; 155 | if (j >= m) { 156 | break; 157 | } 158 | if (Base64.encodeToString(arrayOfSignature2[j].toByteArray(), 0).replaceAll("\n", "").equals(tmpStr)) { 159 | i = 1; 160 | } 161 | j += 1; 162 | } 163 | } 164 | } 165 | if (k == 0) { 166 | paramAnonymousMethodHookParam.setResult(0); 167 | } 168 | } 169 | }); 170 | 171 | // XposedBridge.hookAllMethods(localClass, "installPackageAsUser", new XC_MethodHook() { 172 | // protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 173 | // throws Throwable { 174 | // prefs.reload(); 175 | // if (!prefs.getBoolean("CorePatcher", false)) { 176 | // return; 177 | // } 178 | // int i = 2; 179 | // int j = (Integer) paramAnonymousMethodHookParam.args[i]; 180 | // if ((j & 0x80) == 0) { 181 | // paramAnonymousMethodHookParam.args[i] = j | 0x80; 182 | // } 183 | // } 184 | // }); 185 | } 186 | if ("com.android.settings".equals(paramLoadPackageParam.packageName)) { 187 | XposedBridge.hookAllMethods(XposedHelpers.findClass("com.android.settings.applications.AppOpsDetails", paramLoadPackageParam.classLoader), "isPlatformSigned", new XC_MethodHook() { 188 | protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 189 | throws Throwable { 190 | prefs.reload(); 191 | if (prefs.getBoolean("CorePatcher", false)) { 192 | paramAnonymousMethodHookParam.setResult(false); 193 | } 194 | } 195 | }); 196 | } 197 | 198 | } 199 | } -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/MiuiRoot.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import android.os.Bundle; 4 | import android.os.Message; 5 | import android.widget.Button; 6 | import android.widget.TextView; 7 | import de.robv.android.xposed.IXposedHookInitPackageResources; 8 | import de.robv.android.xposed.IXposedHookLoadPackage; 9 | import de.robv.android.xposed.IXposedHookZygoteInit; 10 | import de.robv.android.xposed.XC_MethodHook; 11 | import de.robv.android.xposed.XC_MethodReplacement; 12 | import de.robv.android.xposed.XSharedPreferences; 13 | import de.robv.android.xposed.XposedHelpers; 14 | import de.robv.android.xposed.callbacks.XC_InitPackageResources; 15 | import de.robv.android.xposed.callbacks.XC_LayoutInflated; 16 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 17 | 18 | /** 19 | * 去除root25秒等待 20 | * Created by cc on 2016/6/17. 21 | */ 22 | public class MiuiRoot implements IXposedHookInitPackageResources, IXposedHookLoadPackage, IXposedHookZygoteInit{ 23 | public static TextView WarningText; 24 | public static Button accept; 25 | 26 | @Override 27 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { 28 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 29 | prefs.makeWorldReadable(); 30 | prefs.reload(); 31 | if (!prefs.getBoolean("root", false)) { 32 | return; 33 | } 34 | 35 | if (!loadPackageParam.packageName.equals("com.miui.securitycenter")) { 36 | return; 37 | } 38 | //创建弹出ROOT警告activity的方法 39 | XposedHelpers.findAndHookMethod("com.miui.permcenter.root.RootApplyActivity", loadPackageParam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() 40 | { 41 | protected void afterHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 42 | throws Throwable 43 | { 44 | // XposedHelpers.setIntField(paramAnonymousMethodHookParam.thisObject, "TK", 5); 45 | if (MiuiRoot.accept == null) { 46 | return; 47 | } 48 | //模拟用户点击确定 5次 49 | int i = 0; 50 | while (i < 5) 51 | { 52 | MiuiRoot.accept.performClick(); 53 | i += 1; 54 | } 55 | } 56 | }); 57 | //这个方法是修改每次点击确定时显示不同的警告文字的 在miui8上找不到方法 可能不存在 或者已经改名 58 | XposedHelpers.findAndHookMethod("com.miui.permcenter.root.c", loadPackageParam.classLoader, "handleMessage", Message.class, new XC_MethodReplacement() 59 | { 60 | protected Object replaceHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 61 | throws Throwable 62 | { 63 | return null; 64 | } 65 | }); 66 | 67 | //这个方法是修改每次点击确定时显示不同的警告文字的 在miui8上找不到方法 可能不存在 或者已经改名 68 | XposedHelpers.findAndHookMethod("com.miui.permcenter.root.a", loadPackageParam.classLoader, "handleMessage", Message.class, new XC_MethodReplacement() 69 | { 70 | protected Object replaceHookedMethod(MethodHookParam paramAnonymousMethodHookParam) 71 | throws Throwable 72 | { 73 | return null; 74 | } 75 | }); 76 | } 77 | 78 | 79 | @Override 80 | public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam initPackageResourcesParam) throws Throwable { 81 | 82 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 83 | prefs.makeWorldReadable(); 84 | prefs.reload(); 85 | if (!prefs.getBoolean("root", false)) { 86 | return; 87 | } 88 | if (!initPackageResourcesParam.packageName.equals("com.miui.securitycenter")) { 89 | return; 90 | } 91 | initPackageResourcesParam.res.hookLayout("com.miui.securitycenter", "layout", "pm_activity_root_apply", new XC_LayoutInflated() 92 | { 93 | public void handleLayoutInflated(XC_LayoutInflated.LayoutInflatedParam paramAnonymousLayoutInflatedParam) 94 | throws Throwable 95 | { 96 | MiuiRoot.accept = (Button)paramAnonymousLayoutInflatedParam.view.findViewById(paramAnonymousLayoutInflatedParam.res.getIdentifier("accept", "id", "com.miui.securitycenter")); 97 | MiuiRoot.WarningText = (TextView)paramAnonymousLayoutInflatedParam.view.findViewById(paramAnonymousLayoutInflatedParam.res.getIdentifier("warning_info", "id", "com.miui.securitycenter")); 98 | if (MiuiRoot.WarningText != null) { 99 | MiuiRoot.WarningText.setLines(6); 100 | } 101 | } 102 | }); 103 | } 104 | 105 | @Override 106 | public void initZygote(StartupParam startupParam) throws Throwable { 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/RemoveSearchBar.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import de.robv.android.xposed.IXposedHookInitPackageResources; 4 | import de.robv.android.xposed.XSharedPreferences; 5 | import de.robv.android.xposed.callbacks.XC_InitPackageResources; 6 | 7 | 8 | public class RemoveSearchBar implements IXposedHookInitPackageResources { 9 | 10 | public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam paramInitPackageResourcesParam) 11 | throws Throwable { 12 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 13 | prefs.makeWorldReadable(); 14 | prefs.reload(); 15 | if (prefs.getBoolean("RemoveSearchBar", false)) { 16 | if (paramInitPackageResourcesParam.packageName.equals("com.android.systemui")) { 17 | paramInitPackageResourcesParam.res.setReplacement(paramInitPackageResourcesParam.packageName, "bool", "config_show_statusbar_search", false); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/ThemePather.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | 4 | import android.content.Context; 5 | import java.io.File; 6 | import java.io.InputStream; 7 | import de.robv.android.xposed.IXposedHookLoadPackage; 8 | import de.robv.android.xposed.IXposedHookZygoteInit; 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XC_MethodReplacement; 11 | import de.robv.android.xposed.XSharedPreferences; 12 | import de.robv.android.xposed.XposedBridge; 13 | import de.robv.android.xposed.XposedHelpers; 14 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 15 | 16 | public class ThemePather implements IXposedHookLoadPackage, IXposedHookZygoteInit { 17 | private static ClassLoader mClassLoader; 18 | //patch函数 19 | private static void patchCodeTwo(String paramString1, String paramString2, Object... paramVarArgs) { 20 | try { 21 | XposedHelpers.findAndHookMethod(Class.forName(paramString1), paramString2, paramVarArgs); 22 | return; 23 | } catch (ClassNotFoundException paramString3) { 24 | log(" Class "+paramString1+"not found! Skipping..."); 25 | return; 26 | } catch (NoSuchMethodError paramString4) { 27 | log(" Method "+paramString2+"found! Skipping..."); 28 | } 29 | } 30 | //log记录 31 | private static void log(String paramString) { 32 | XposedBridge.log("assistant " + paramString); 33 | } 34 | //主函数 35 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) 36 | throws Throwable { 37 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 38 | prefs.makeWorldReadable(); 39 | prefs.reload(); 40 | if (!prefs.getBoolean("ThemePatcher", false)) { 41 | return; 42 | } 43 | XposedBridge.log("miui7主题破解开始"); 44 | mClassLoader = paramLoadPackageParam.classLoader; 45 | DRM(); 46 | thmemHook(paramLoadPackageParam); 47 | } 48 | //主题-入口 49 | private static void thmemHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) 50 | { 51 | if (paramLoadPackageParam.packageName.equals("com.android.thememanager")) { 52 | zhifu(); 53 | yanzheng(); 54 | tongzhi(); 55 | XposedBridge.log("miui7主题破解完成"); 56 | } 57 | } 58 | 59 | //主题-DRM验证 60 | private static void DRM() { 61 | 62 | patchCodeTwo("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, String.class, "miui.drm.DrmManager$RightObject", XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 63 | patchCodeTwo("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, File.class, File.class, XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 64 | patchCodeTwo("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, String.class, File.class, XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 65 | patchCodeTwo("miui.drm.DrmManager", "isPermanentRights", new Object[]{"miui.drm.DrmManager$RightObject", XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 66 | patchCodeTwo("miui.drm.DrmManager", "isPermanentRights", new Object[]{File.class, XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 67 | patchCodeTwo("miui.drm.DrmManager", "isLegal", new Object[]{File.class, File.class, XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 68 | patchCodeTwo("miui.drm.DrmManager", "isLegal", new Object[]{String.class, File.class, XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 69 | } 70 | //主题-本地验证 71 | private static void yanzheng() { 72 | try { 73 | Class.forName("miui.resourcebrowser.controller.online.DrmService", false, mClassLoader); 74 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.controller.online.DrmService", mClassLoader, "isLegal", new Object[]{"miui.resourcebrowser.model.Resource", new XC_MethodReplacement() { 75 | protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 76 | throws Throwable { 77 | return Boolean.valueOf(true); 78 | } 79 | }}); 80 | try { 81 | 82 | Class.forName("miui.resourcebrowser.view.ResourceOperationHandler", false, mClassLoader); 83 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.view.ResourceOperationHandler", mClassLoader, "isLegal", new Object[]{new XC_MethodReplacement() { 84 | protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 85 | throws Throwable { 86 | return Boolean.valueOf(true); 87 | } 88 | }}); 89 | try { 90 | 91 | Class.forName("miui.resourcebrowser.view.ResourceOperationHandler", false, mClassLoader); 92 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.view.ResourceOperationHandler", mClassLoader, "onCheckResourceRightEventBeforeRealApply", new Object[]{new XC_MethodHook() { 93 | protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 94 | throws Throwable { 95 | XposedHelpers.setBooleanField(paramAnonymousMethodHookParam.thisObject, "mIsLegal", true); 96 | } 97 | }}); 98 | return; 99 | } catch (NoSuchMethodError localNoSuchMethodError1) { 100 | log(localNoSuchMethodError1.getMessage()); 101 | } catch (ClassNotFoundException localClassNotFoundException1) { 102 | log(localClassNotFoundException1.getMessage()); 103 | } 104 | } catch (NoSuchMethodError localClassNotFoundException2) { 105 | log(localClassNotFoundException2.getMessage()); 106 | return; 107 | } catch (ClassNotFoundException localClassNotFoundException2) { 108 | log(localClassNotFoundException2.getMessage()); 109 | return; 110 | } 111 | } catch (NoSuchMethodError localNoSuchMethodError3) { 112 | log(localNoSuchMethodError3.getMessage()); 113 | return; 114 | } catch (ClassNotFoundException localClassNotFoundException3) { 115 | log(localClassNotFoundException3.getMessage()); 116 | return; 117 | } 118 | } 119 | //主题-设置为已购买 120 | private static void tongzhi() { 121 | try { 122 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.model.Resource", mClassLoader, "isProductBought", new Object[]{XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 123 | try { 124 | 125 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.model.ResourceOnlineProperties", mClassLoader, "setProductBought", new Object[]{Boolean.TYPE, new XC_MethodReplacement() { 126 | protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 127 | throws Throwable { 128 | Object[] arrayOfObject = new Object[1]; 129 | arrayOfObject[0] = Boolean.valueOf(true); 130 | paramAnonymousMethodHookParam.args = arrayOfObject; 131 | return XposedBridge.invokeOriginalMethod(paramAnonymousMethodHookParam.method, paramAnonymousMethodHookParam.thisObject, arrayOfObject); 132 | } 133 | }}); 134 | try { 135 | 136 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.model.ResourceOnlineProperties", mClassLoader, "isProductBought", new Object[]{XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 137 | return; 138 | } catch (NoSuchMethodError localNoSuchMethodError1) { 139 | 140 | log(localNoSuchMethodError1.getMessage()); 141 | return; 142 | 143 | 144 | } catch (Exception localException1) { 145 | 146 | log(localException1.getMessage()); 147 | return; 148 | 149 | } 150 | } catch (NoSuchMethodError localNoSuchMethodError2) { 151 | log(localNoSuchMethodError2.getMessage()); 152 | return; 153 | } catch (Exception localException2) { 154 | log(localException2.getMessage()); 155 | return; 156 | } 157 | } catch (NoSuchMethodError localNoSuchMethodError3) { 158 | log(localNoSuchMethodError3.getMessage()); 159 | return; 160 | } catch (Exception localException3) { 161 | log(localException3.getMessage()); 162 | 163 | 164 | return; 165 | } 166 | } 167 | //主题-在线验证 168 | private static void zhifu() { 169 | try { 170 | Class.forName("miui.resourcebrowser.view.ResourceOperationHandler", false, mClassLoader); 171 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.view.ResourceOperationHandler", mClassLoader, "isAuthorizedResource", new Object[]{XC_MethodReplacement.returnConstant(Boolean.valueOf(true))}); 172 | try { 173 | 174 | Class.forName("miui.resourcebrowser.controller.online.NetworkHelper", false, mClassLoader); 175 | XposedHelpers.findAndHookMethod("miui.resourcebrowser.controller.online.NetworkHelper", mClassLoader, "validateResponseResult", new Object[]{Integer.TYPE, InputStream.class, new XC_MethodHook() { 176 | protected void beforeHookedMethod(XC_MethodHook.MethodHookParam paramAnonymousMethodHookParam) 177 | throws Throwable { 178 | paramAnonymousMethodHookParam.setResult((InputStream) paramAnonymousMethodHookParam.args[1]); 179 | } 180 | }}); 181 | 182 | } catch (NoSuchMethodError localNoSuchMethodError1) { 183 | 184 | log(localNoSuchMethodError1.getMessage()); 185 | return; 186 | 187 | } catch (ClassNotFoundException localClassNotFoundException1) { 188 | 189 | log(localClassNotFoundException1.getMessage()); 190 | return; 191 | } 192 | } catch (NoSuchMethodError localNoSuchMethodError2) { 193 | log(localNoSuchMethodError2.getMessage()); 194 | return; 195 | } catch (ClassNotFoundException localClassNotFoundException2) { 196 | log(localClassNotFoundException2.getMessage()); 197 | return; 198 | } 199 | 200 | } 201 | public void initZygote(IXposedHookZygoteInit.StartupParam paramStartupParam) throws Throwable { 202 | } 203 | } -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/ThemePather2.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import de.robv.android.xposed.IXposedHookLoadPackage; 4 | import de.robv.android.xposed.IXposedHookZygoteInit; 5 | import de.robv.android.xposed.XC_MethodReplacement; 6 | import de.robv.android.xposed.XSharedPreferences; 7 | import de.robv.android.xposed.XposedHelpers; 8 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 9 | 10 | /** 11 | * 去你妹的miui8 代码全review了 12 | * Created by CoderStory on 2016/6/10. 13 | */ 14 | public class ThemePather2 implements IXposedHookZygoteInit, IXposedHookLoadPackage { 15 | 16 | 17 | 18 | @Override 19 | public void initZygote(StartupParam startupParam) throws Throwable { 20 | } 21 | 22 | @Override 23 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { 24 | 25 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 26 | prefs.makeWorldReadable(); 27 | prefs.reload(); 28 | if (!prefs.getBoolean("ThemePatcher2", false)) { 29 | return; 30 | } 31 | //XposedBridge.log("Loaded app: " + lpparam.packageName); 32 | //XposedBridge.log("miui8主题破解1"); 33 | if (lpparam.packageName.equals("miui.drm") || lpparam.packageName.equals("com.miui.system")|| lpparam.packageName.equals("miui.system")) { 34 | 35 | //判断是有权限使用 36 | XposedHelpers.findAndHookMethod("miui.drm.DrmManager", lpparam.classLoader, "isPermanentRights", XC_MethodReplacement.returnConstant(true)); 37 | 38 | //验证单个主题的方法 39 | XposedHelpers.findAndHookMethod("miui.drm.ThemeReceiver", lpparam.classLoader, "validateTheme", XC_MethodReplacement.returnConstant(true)); 40 | XposedHelpers.findAndHookMethod("miui.content.res.ThemeRuntimeManager.ThemeReceiver", lpparam.classLoader, "validateTheme", XC_MethodReplacement.returnConstant(true)); 41 | 42 | 43 | //替换主题还原的方法 44 | XposedHelpers.findAndHookMethod("miui.content.res.ThemeRuntimeManager", lpparam.classLoader, "restoreDefault", new XC_MethodReplacement() { 45 | @Override 46 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 47 | return null; 48 | } 49 | }); 50 | 51 | XposedHelpers.findAndHookMethod("miui.drm.ThemeReceiverr", lpparam.classLoader, "restoreDefault", new XC_MethodReplacement() { 52 | @Override 53 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 54 | return null; 55 | } 56 | }); 57 | XposedHelpers.findAndHookMethod("miui.content.res.ThemeRuntimeManager", lpparam.classLoader, "restoreDefault", new XC_MethodReplacement() { 58 | @Override 59 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 60 | return null; 61 | } 62 | }); 63 | 64 | 65 | //DRM验证主题的入口点; 66 | XposedHelpers.findAndHookMethod("miui.drm.ThemeReceiver", lpparam.classLoader, "onReceive", new XC_MethodReplacement() { 67 | @Override 68 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 69 | return null; 70 | } 71 | }); 72 | 73 | 74 | } 75 | if (lpparam.packageName.equals("com.android.thememanager")) { 76 | //是否试用 可以不改 77 | XposedHelpers.findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader, "isTrialable", XC_MethodReplacement.returnConstant(false)); 78 | //是否合法 79 | XposedHelpers.findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader, "isLegal", XC_MethodReplacement.returnConstant(true)); 80 | //是否被篡改(本地导入修改的主题) 81 | XposedHelpers.findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader, "isAuthorizedResource", XC_MethodReplacement.returnConstant(true)); 82 | //判断是有权限使用 83 | XposedHelpers.findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader, "isPermanentRights", XC_MethodReplacement.returnConstant(true)); 84 | 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/ThemePather3.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.File; 6 | 7 | import de.robv.android.xposed.IXposedHookLoadPackage; 8 | import de.robv.android.xposed.IXposedHookZygoteInit; 9 | import de.robv.android.xposed.XC_MethodReplacement; 10 | import de.robv.android.xposed.XSharedPreferences; 11 | import de.robv.android.xposed.XposedBridge; 12 | import de.robv.android.xposed.XposedHelpers; 13 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 14 | 15 | /** 16 | * Created by cc on 2016/6/22. 17 | */ 18 | public class ThemePather3 implements IXposedHookZygoteInit, IXposedHookLoadPackage { 19 | 20 | public static Object getDrmResultSUCCESS() { 21 | try { 22 | Class localString1 = (Class) Class.forName("miui.drm.DrmManager$DrmResult"); 23 | if (localString1 != null) { 24 | return Enum.valueOf(localString1, "DRM_SUCCESS"); 25 | } 26 | } catch (Throwable localString4) { 27 | XposedBridge.log(localString4.toString()); 28 | 29 | } 30 | return null; 31 | } 32 | 33 | @Override 34 | public void initZygote(StartupParam startupParam) throws Throwable { 35 | 36 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 37 | prefs.makeWorldReadable(); 38 | prefs.reload(); 39 | if (!prefs.getBoolean("ThemePatcher3", false)) { 40 | XposedBridge.log("disable DRM Patch"); 41 | return; 42 | } 43 | XposedBridge.log("start DRM Patch"); 44 | MIUI_DRM(); 45 | } 46 | 47 | @Override 48 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { 49 | 50 | XSharedPreferences prefs = new XSharedPreferences("com.coderstory.miui_toolkit", "UserSettings"); 51 | prefs.makeWorldReadable(); 52 | prefs.reload(); 53 | if (!prefs.getBoolean("ThemePatcher3", false)) { 54 | XposedBridge.log("disable thememanager Patch"); 55 | return; 56 | } 57 | // XposedBridge.log("Loaded app: " + lpparam.packageName); 58 | // XposedBridge.log("miui8主题破解2"); 59 | if (lpparam.packageName.equals("miui.drm") || lpparam.packageName.equals("com.miui.system") || lpparam.packageName.equals("miui.system")) { 60 | MIUI_DRM(); 61 | } 62 | if (lpparam.packageName.equals("com.android.thememanager")) { 63 | XposedBridge.log("start thememanager Patch"); 64 | //是否试用 可以不改 65 | findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader,"isTrialable", XC_MethodReplacement.returnConstant(false)); 66 | //是否合法 67 | findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler",lpparam.classLoader, "isLegal", XC_MethodReplacement.returnConstant(true)); 68 | //是否被篡改(本地导入修改的主题) 69 | findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader,"isAuthorizedResource", XC_MethodReplacement.returnConstant(true)); 70 | //判断是有权限使用 71 | findAndHookMethod("com.android.thememanager.util.ThemeOperationHandler", lpparam.classLoader,"isPermanentRights", XC_MethodReplacement.returnConstant(true)); 72 | } 73 | } 74 | 75 | private void MIUI_DRM() { 76 | findAndHookMethod("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, File.class, File.class, XC_MethodReplacement.returnConstant(getDrmResultSUCCESS())}); 77 | findAndHookMethod("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, String.class, File.class, XC_MethodReplacement.returnConstant(getDrmResultSUCCESS())}); 78 | findAndHookMethod("miui.drm.DrmManager", "isLegal", new Object[]{Context.class, String.class, "miui.drm.DrmManager$RightObject", XC_MethodReplacement.returnConstant(getDrmResultSUCCESS())}); 79 | findAndHookMethod("miui.drm.DrmManager", "isPermanentRights", new Object[]{File.class, XC_MethodReplacement.returnConstant(true)}); 80 | findAndHookMethod("miui.drm.DrmManager", "isLegal", new Object[]{"miui.drm.DrmManager$RightObject", XC_MethodReplacement.returnConstant(true)}); 81 | } 82 | 83 | private static void findAndHookMethod(String p1,ClassLoader lpparam ,String p2,Object... parameterTypesAndCallback) { 84 | try { 85 | XposedHelpers.findAndHookMethod(p1,lpparam, p2, parameterTypesAndCallback); 86 | } catch (Throwable localString3) { 87 | XposedBridge.log(localString3.toString()); 88 | } 89 | } 90 | private static void findAndHookMethod(String p1, String p2, Object[] p3) { 91 | try { 92 | XposedHelpers.findAndHookMethod(Class.forName(p1), p2, p3); 93 | } catch (Throwable localString3) { 94 | XposedBridge.log(localString3.toString()); 95 | } 96 | } 97 | 98 | } 99 | 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/XposedModule/isEnable.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.XposedModule; 2 | 3 | import de.robv.android.xposed.IXposedHookLoadPackage; 4 | import de.robv.android.xposed.IXposedHookZygoteInit; 5 | import de.robv.android.xposed.XC_MethodReplacement; 6 | import de.robv.android.xposed.XposedBridge; 7 | import de.robv.android.xposed.XposedHelpers; 8 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 9 | 10 | /** 11 | * Created by CoderStory on 2016/7/12. 12 | */ 13 | 14 | public class isEnable implements IXposedHookZygoteInit, IXposedHookLoadPackage { 15 | @Override 16 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { 17 | if (lpparam.packageName.equals("com.coderstory.miui_toolkit")) { 18 | try { 19 | 20 | XposedBridge.log("插件已激活"); 21 | XposedHelpers. findAndHookMethod("com.coderstory.miui_toolkit.Activity.MainActivity", lpparam.classLoader, "isEnable", XC_MethodReplacement.returnConstant(true)); 22 | } catch (Throwable p1) { 23 | XposedBridge.log(p1); 24 | } 25 | } 26 | } 27 | @Override 28 | public void initZygote(StartupParam startupParam) throws Throwable { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/service/UpdateService.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.service; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.app.Service; 8 | import android.content.Intent; 9 | import android.net.Uri; 10 | import android.os.AsyncTask; 11 | import android.os.Environment; 12 | import android.os.Handler; 13 | import android.os.IBinder; 14 | import android.os.Message; 15 | import android.widget.Toast; 16 | 17 | import com.coderstory.miui_toolkit.Activity.MainActivity; 18 | import com.coderstory.miui_toolkit.R; 19 | import com.coderstory.miui_toolkit.tools.Update.UpdateConfig; 20 | 21 | import java.io.File; 22 | import java.io.FileOutputStream; 23 | import java.io.InputStream; 24 | import java.net.HttpURLConnection; 25 | import java.net.URL; 26 | 27 | 28 | public class UpdateService extends Service { 29 | 30 | // 文件存储 31 | private File updateDir = null; 32 | private File updateFile = null; 33 | // 下载状态 34 | private final static int DOWNLOAD_COMPLETE = 0; 35 | private final static int DOWNLOAD_FAIL = 1; 36 | // 通知栏 37 | private NotificationManager updateNotificationManager = null; 38 | private Notification updateNotification = null; 39 | // 通知栏跳转Intent 40 | private Intent updateIntent = null; 41 | private PendingIntent updatePendingIntent = null; 42 | /*** 43 | * 创建通知栏 44 | */ 45 | // RemoteViews contentView; 46 | // 这样的下载代码很多,我就不做过多的说明 47 | private int downloadCount = 0; 48 | private int currentSize = 0; 49 | private long totalSize = 0; 50 | private int updateTotalSize = 0; 51 | 52 | // 在onStartCommand()方法中准备相关的下载工作: 53 | @SuppressWarnings("deprecation") 54 | @Override 55 | public int onStartCommand(Intent intent, int flags, int startId) { 56 | // 获取传值 57 | updateTotalSize = 0; 58 | currentSize = 0; 59 | int titleId = intent.getIntExtra("titleId", 0); 60 | // 创建文件 61 | if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment 62 | .getExternalStorageState())) { 63 | updateDir = new File(Environment.getExternalStorageDirectory(), 64 | UpdateConfig.saveFileName); 65 | updateFile = new File(updateDir.getPath(), getResources() 66 | .getString(titleId) + ".apk"); 67 | 68 | } 69 | this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 70 | // 设置下载过程中,点击通知栏,回到主界面 71 | updateIntent = new Intent(this, MainActivity.class); 72 | updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent, 73 | 0); 74 | // 设置通知栏显示内容 75 | updateNotification = new Notification.Builder(this) 76 | .setAutoCancel(true) 77 | .setContentTitle(getString(R.string.app_name)) 78 | .setContentText(getString(R.string.Downloading)) 79 | .setContentIntent(updatePendingIntent) 80 | .setSmallIcon(R.mipmap.launcher) 81 | .setWhen(System.currentTimeMillis()) 82 | .build(); 83 | // public void setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) 84 | // 发出通知 85 | updateNotificationManager.notify(0, updateNotification); 86 | // 开启一个新的线程下载,如果使用Service同步下载,会导致ANR问题,Service本身也会阻塞 87 | new Thread(new updateRunnable()).start();// 这个是下载的重点,是下载的过程 88 | return super.onStartCommand(intent, flags, startId); 89 | } 90 | 91 | @Override 92 | public IBinder onBind(Intent arg0) { 93 | // TODO Auto-generated method stub 94 | return null; 95 | } 96 | 97 | @SuppressLint("HandlerLeak") 98 | private Handler updateHandler = new Handler() { 99 | @Override 100 | public void handleMessage(Message msg) { 101 | switch (msg.what) { 102 | case DOWNLOAD_COMPLETE: 103 | // 点击安装PendingIntent 104 | Uri uri = Uri.fromFile(updateFile); 105 | Intent installIntent = new Intent(Intent.ACTION_VIEW); 106 | installIntent.setDataAndType(uri, 107 | "application/vnd.android.package-archive"); 108 | updatePendingIntent = PendingIntent.getActivity( 109 | UpdateService.this, 0, installIntent, 0); 110 | updateNotification.defaults = Notification.DEFAULT_SOUND;// 铃声提醒 111 | // 设置通知栏显示内容 112 | updateNotification = new Notification.Builder(UpdateService.this) 113 | .setAutoCancel(true) 114 | .setContentTitle(getString(R.string.app_name)) 115 | .setContentText(getString(R.string.Download_Success)) 116 | .setContentIntent(updatePendingIntent) 117 | .setSmallIcon(R.mipmap.launcher) 118 | .setWhen(System.currentTimeMillis()) 119 | .build(); 120 | updateNotificationManager.notify(0, updateNotification); 121 | break; 122 | case DOWNLOAD_FAIL: 123 | // 下载失败 124 | updateNotification = new Notification.Builder(UpdateService.this) 125 | .setAutoCancel(true) 126 | .setContentTitle(getString(R.string.app_name)) 127 | .setContentText(getString(R.string.Download_Fail)) 128 | .setContentIntent(updatePendingIntent) 129 | .setSmallIcon(R.mipmap.launcher) 130 | .setWhen(System.currentTimeMillis()) 131 | .build(); 132 | updateNotificationManager.notify(0, updateNotification); 133 | break; 134 | } 135 | stopService(updateIntent); 136 | } 137 | }; 138 | 139 | private long downloadUpdateFile(String downloadUrl, File saveFile) 140 | throws Exception { 141 | HttpURLConnection httpConnection = null; 142 | InputStream is = null; 143 | FileOutputStream fos = null; 144 | try { 145 | URL url = new URL(downloadUrl); 146 | httpConnection = (HttpURLConnection) url.openConnection(); 147 | httpConnection 148 | .setRequestProperty("User-Agent", "PacificHttpClient"); 149 | if (currentSize > 0) { 150 | httpConnection.setRequestProperty("RANGE", "bytes=" 151 | + currentSize + "-"); 152 | } 153 | httpConnection.setConnectTimeout(10000); 154 | httpConnection.setReadTimeout(20000); 155 | updateTotalSize = httpConnection.getContentLength(); 156 | if (httpConnection.getResponseCode() == 404) { 157 | throw new Exception("fail!"); 158 | } 159 | is = httpConnection.getInputStream(); 160 | fos = new FileOutputStream(saveFile, false); 161 | byte buffer[] = new byte[4096]; 162 | int readsize; 163 | while ((readsize = is.read(buffer)) > 0) { 164 | fos.write(buffer, 0, readsize); 165 | totalSize += readsize; 166 | // 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次 167 | if ((downloadCount == 0) 168 | || (int) (totalSize * 100 / updateTotalSize) - 10 > downloadCount) { 169 | downloadCount += 10; 170 | updateNotification = new Notification.Builder(UpdateService.this) 171 | .setAutoCancel(true) 172 | .setContentTitle(getString(R.string.Downloading)) 173 | .setContentText((int) totalSize * 100 / updateTotalSize 174 | + "%") 175 | .setContentIntent(updatePendingIntent) 176 | .setSmallIcon(R.mipmap.launcher) 177 | .setWhen(System.currentTimeMillis()) 178 | .build(); 179 | /*** 180 | * 在这里我们用自定的view来显示Notification 181 | */ 182 | // updateNotification.contentView = new RemoteViews( 183 | // getPackageName(), R.layout.notification_item); 184 | // updateNotification.contentView.setTextViewText( 185 | // R.id.notificationTitle, "正在下载"); 186 | // updateNotification.contentView.setProgressBar( 187 | // R.id.notificationProgress, 100, downloadCount, false); 188 | updateNotificationManager.notify(0, updateNotification); 189 | } 190 | } 191 | } finally { 192 | if (httpConnection != null) { 193 | httpConnection.disconnect(); 194 | } 195 | if (is != null) { 196 | is.close(); 197 | } 198 | if (fos != null) { 199 | fos.close(); 200 | } 201 | } 202 | return totalSize; 203 | } 204 | 205 | private class updateRunnable implements Runnable { 206 | Message message = updateHandler.obtainMessage(); 207 | 208 | public void run() { 209 | message.what = DOWNLOAD_COMPLETE; 210 | try { 211 | // 增加权限; 213 | if (!updateDir.exists()) { 214 | updateDir.mkdirs(); 215 | } 216 | //重新创建一遍 删除之前的旧数据 比如下载失败的不完整文件 217 | if (updateFile.exists()) { 218 | updateFile.delete(); 219 | // new ToastMessageTask().execute(getString(R.string.Delete_OldFile_Fail)); 220 | } 221 | 222 | 223 | updateFile.createNewFile(); 224 | // new ToastMessageTask().execute(getString(R.string.Create_DownlodFile_Fail)); 225 | 226 | 227 | // 下载函数 228 | // 增加权限; 230 | long downloadSize = downloadUpdateFile( 231 | UpdateConfig.URL, 232 | updateFile); 233 | if (downloadSize > 0) { 234 | // 下载成功 235 | updateHandler.sendMessage(message); 236 | } 237 | } catch (Exception ex) { 238 | ex.printStackTrace(); 239 | message.what = DOWNLOAD_FAIL; 240 | // 下载失败 241 | updateHandler.sendMessage(message); 242 | } 243 | } 244 | } 245 | 246 | 247 | // A class that will run Toast messages in the main GUI context 248 | // private class ToastMessageTask extends AsyncTask { 249 | // String toastMessage; 250 | // 251 | // @Override 252 | // protected String doInBackground(String... params) { 253 | // toastMessage = params[0]; 254 | // return toastMessage; 255 | // } 256 | // 257 | // 258 | // // This is executed in the context of the main GUI thread 259 | // protected void onPostExecute(String result) { 260 | // Toast toast = Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT); 261 | // toast.show(); 262 | // } 263 | // } 264 | 265 | 266 | } 267 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/CrashHelper/CrashApplication.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.CrashHelper; 2 | 3 | /** 4 | * Created by cc on 2016/8/1. 5 | */ 6 | 7 | import android.app.Application; 8 | 9 | public class CrashApplication extends Application { 10 | @Override 11 | public void onCreate() { 12 | super.onCreate(); 13 | CrashHandler crashHandler = CrashHandler.getInstance(); 14 | crashHandler.init(getApplicationContext()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/CrashHelper/CrashHandler.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.CrashHelper; 2 | 3 | /** 4 | * Created by cc on 2016/8/1. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.content.pm.PackageInfo; 9 | import android.content.pm.PackageManager; 10 | import android.os.Build; 11 | import android.os.Environment; 12 | import android.os.Looper; 13 | import android.util.Log; 14 | import android.widget.Toast; 15 | 16 | import java.io.File; 17 | import java.io.FileNotFoundException; 18 | import java.io.FileOutputStream; 19 | import java.io.IOException; 20 | import java.io.PrintWriter; 21 | import java.io.StringWriter; 22 | import java.io.Writer; 23 | import java.lang.reflect.Field; 24 | import java.text.SimpleDateFormat; 25 | import java.util.Arrays; 26 | import java.util.Comparator; 27 | import java.util.Date; 28 | import java.util.HashMap; 29 | import java.util.Locale; 30 | import java.util.Map; 31 | 32 | import static com.umeng.analytics.MobclickAgent.reportError; 33 | 34 | /** 35 | * 收集手机全局崩溃时的exception,并log到本地 36 | * 37 | * @author Jackland_zgl 38 | * 39 | */ 40 | public class CrashHandler implements Thread.UncaughtExceptionHandler { 41 | 42 | public static String CrashFilePath ; 43 | 44 | public static final int LogFileLimit = 10; 45 | 46 | public static final String TAG = "CrashHandler"; 47 | 48 | //系统默认的UncaughtException处理类 49 | private Thread.UncaughtExceptionHandler mDefaultHandler; 50 | //CrashHandler实例 51 | private static CrashHandler INSTANCE = new CrashHandler(); 52 | //程序的Context对象 53 | private Context mContext; 54 | //用来存储设备信息和异常信息 55 | private Map infos = new HashMap<>(); 56 | 57 | //用于格式化日期,作为日志文件名的一部分 58 | private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINESE); 59 | 60 | /** 保证只有一个CrashHandler实例 */ 61 | private CrashHandler() { 62 | } 63 | 64 | /** 获取CrashHandler实例 ,单例模式 */ 65 | static CrashHandler getInstance() { 66 | return INSTANCE; 67 | } 68 | 69 | /** 70 | * 初始化 71 | * 72 | * @param context context 73 | */ 74 | void init(Context context) { 75 | mContext = context; 76 | //获取系统默认的UncaughtException处理器 77 | mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 78 | //设置该CrashHandler为程序的默认处理器 79 | Thread.setDefaultUncaughtExceptionHandler(this); 80 | CrashFilePath= Environment.getExternalStorageDirectory().getPath()+"/Mi Kit/crashlog/"; 81 | } 82 | 83 | /** 84 | * 当UncaughtException发生时会转入该函数来处理 85 | */ 86 | @Override 87 | public void uncaughtException(Thread thread, Throwable ex) { 88 | if (!handleException(ex) && mDefaultHandler != null) { 89 | //如果用户没有处理则让系统默认的异常处理器来处理 90 | mDefaultHandler.uncaughtException(thread, ex); 91 | } else { 92 | try { 93 | Thread.sleep(2000); 94 | } catch (InterruptedException e) { 95 | Log.e(TAG, "error : ", e); 96 | } 97 | //退出程序 98 | android.os.Process.killProcess(android.os.Process.myPid()); 99 | System.exit(1); 100 | } 101 | } 102 | 103 | 104 | /** 105 | * 收集设备参数信息 106 | * @param ctx 107 | */ 108 | private void collectDeviceInfo(Context ctx) { 109 | try { 110 | PackageManager pm = ctx.getPackageManager(); 111 | PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); 112 | if (pi != null) { 113 | String versionName = pi.versionName == null ? "null" : pi.versionName; 114 | String versionCode = pi.versionCode + ""; 115 | infos.put("versionName", versionName); 116 | infos.put("versionCode", versionCode); 117 | } 118 | } catch (PackageManager.NameNotFoundException e) { 119 | Log.e(TAG, "an error occured when collect package info", e); 120 | } 121 | Field[] fields = Build.class.getDeclaredFields(); 122 | for (Field field : fields) { 123 | try { 124 | field.setAccessible(true); 125 | infos.put(field.getName(), field.get(null).toString()); 126 | } catch (Exception e) { 127 | Log.e(TAG, "an error occured when collect crash info", e); 128 | } 129 | } 130 | } 131 | 132 | /** 133 | * 保存错误信息到文件中 134 | * 135 | * @param ex Throwable 136 | * @return 返回文件名称,便于将文件传送到服务器 137 | */ 138 | private int saveCrashInfo2File(Throwable ex) { 139 | 140 | //将设备信息变成string 141 | StringBuilder sb = new StringBuilder(); 142 | for (Map.Entry entry : infos.entrySet()) { 143 | String key = entry.getKey(); 144 | String value = entry.getValue(); 145 | sb.append(key).append("=").append(value).append("\n"); 146 | } 147 | 148 | //递归获取全部的exception信息 149 | Writer writer = new StringWriter(); 150 | PrintWriter printWriter = new PrintWriter(writer); 151 | ex.printStackTrace(printWriter); 152 | Throwable cause = ex.getCause(); 153 | while (cause != null) { 154 | cause.printStackTrace(printWriter); 155 | cause = cause.getCause(); 156 | } 157 | printWriter.close(); 158 | String result = writer.toString(); 159 | sb.append(result); //将写入的结果 160 | 161 | //构造文件名 162 | long timestamp = System.currentTimeMillis(); 163 | String time = formatter.format(new Date()); 164 | String fileName = "crash-" + time + "-" + timestamp + ".log"; 165 | 166 | 167 | File dir = new File(CrashFilePath); 168 | 169 | if (!dir.exists()) { 170 | dir.mkdirs(); 171 | } 172 | FileOutputStream fos = null; 173 | try { 174 | fos = new FileOutputStream(CrashFilePath + fileName); 175 | fos.write(sb.toString().getBytes()); 176 | fos.close(); 177 | } catch (IOException e) { 178 | e.printStackTrace(); 179 | } 180 | 181 | cleanLogFileToN(CrashFilePath); 182 | //上传日志到Umeng 183 | //reportError(mContext,sb.toString()); 184 | reportError(mContext,sb.toString()); 185 | Log.d(TAG, "saveCrashInfo2File: "+sb.toString()); 186 | 187 | return 1; 188 | } 189 | 190 | private Comparator newfileFinder = new Comparator(){ 191 | 192 | @Override 193 | public int compare(File x, File y) { 194 | // TODO Auto-generated method stub 195 | if (x.lastModified()>y.lastModified()) return 1; 196 | if (x.lastModified()LogFileLimit){ 207 | Arrays.sort(logFiles,newfileFinder ); //从小到大排 208 | //删掉N个以前的 209 | for (int i=0;i HostsConfig; //hosts的用户配置 19 | 20 | public HostsHelper(Context mContext, Map mMap) { 21 | this.mContext = mContext; 22 | this.HostsConfig = mMap; 23 | } 24 | 25 | /** 26 | * 构造需要root下执行的命令组 27 | * @return 构造好的命令组 28 | * @throws UnsupportedEncodingException 29 | */ 30 | @Override 31 | protected ArrayList getCommandsToExecute() throws UnsupportedEncodingException { 32 | ArrayList list = new ArrayList<>(); 33 | list.add("mount -o rw,remount /system"); 34 | FileHelper fh = new FileHelper(); 35 | String content=fh.getFromAssets("none", mContext); 36 | list.add("echo '"+content+"' > /system/etc/hosts");//清空 37 | 38 | if (HostsConfig.get("NoUpdate").equals("True")){ 39 | content=fh.getFromAssets("hosts_noup", mContext); 40 | list.add("echo '"+content+"' >> /system/etc/hosts");//禁止检测更新 41 | } 42 | if (HostsConfig.get("RemoveAdshosts").equals("True")){ 43 | content=fh.getFromAssets("hosts_noad", mContext); 44 | list.add("echo '"+content+"' >> /system/etc/hosts");//移除广告 45 | } 46 | if (HostsConfig.get("GoogleHosts").equals("True")){ 47 | content=fh.getFromAssets("google", mContext); 48 | list.add("echo '"+content+"' >> /system/etc/hosts");//谷歌hosts 49 | content=fh.getFromAssets("hosts", mContext); 50 | list.add("echo '"+content+"' >> /system/etc/hosts");//谷歌hosts 51 | } 52 | if (HostsConfig.get("NoStore").equals("True")){ 53 | content=fh.getFromAssets("hosts_nostore", mContext); 54 | list.add("echo '"+content+"' >> /system/etc/hosts"); //屏蔽商店 音乐 视频 55 | } 56 | return list; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/RequestPermissions.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | 8 | /** 9 | * Created by CoderStory on 2016/7/30. 10 | */ 11 | 12 | public class RequestPermissions { 13 | 14 | /** 15 | * 申请储存权限 16 | * @param activity context 17 | * @return 权限的查询结果 18 | */ 19 | public static boolean isGrantExternalRW(Activity activity) { 20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.checkSelfPermission( 21 | Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 22 | 23 | activity.requestPermissions(new String[]{ 24 | Manifest.permission.READ_EXTERNAL_STORAGE, 25 | Manifest.permission.WRITE_EXTERNAL_STORAGE 26 | }, 1); 27 | return false; 28 | } 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/Root/ShellUtils.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.Root; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStreamReader; 7 | import java.util.List; 8 | 9 | /** 10 | * ShellUtils 11 | *

15 | * 24 | * 25 | * @author Trinea 2013-5-16 26 | */ 27 | public class ShellUtils { 28 | 29 | public static final String COMMAND_SU = "su"; 30 | public static final String COMMAND_SH = "sh"; 31 | public static final String COMMAND_EXIT = "exit\n"; 32 | public static final String COMMAND_LINE_END = "\n"; 33 | 34 | private ShellUtils() { 35 | throw new AssertionError(); 36 | } 37 | 38 | /** 39 | * check whether has root permission 40 | * 41 | * @return 42 | */ 43 | public static boolean checkRootPermission() { 44 | return execCommand("echo root", true, false).result == 0; 45 | } 46 | 47 | /** 48 | * execute shell command, default return result msg 49 | * 50 | * @param command command 51 | * @param isRoot whether need to run with root 52 | * @return 53 | * @see ShellUtils#execCommand(String[], boolean, boolean) 54 | */ 55 | public static CommandResult execCommand(String command, boolean isRoot) { 56 | return execCommand(new String[] {command}, isRoot, true); 57 | } 58 | 59 | /** 60 | * execute shell commands, default return result msg 61 | * 62 | * @param commands command list 63 | * @param isRoot whether need to run with root 64 | * @return 65 | * @see ShellUtils#execCommand(String[], boolean, boolean) 66 | */ 67 | public static CommandResult execCommand(List commands, boolean isRoot) { 68 | return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true); 69 | } 70 | 71 | /** 72 | * execute shell commands, default return result msg 73 | * 74 | * @param commands command array 75 | * @param isRoot whether need to run with root 76 | * @return 77 | * @see ShellUtils#execCommand(String[], boolean, boolean) 78 | */ 79 | public static CommandResult execCommand(String[] commands, boolean isRoot) { 80 | return execCommand(commands, isRoot, true); 81 | } 82 | 83 | /** 84 | * execute shell command 85 | * 86 | * @param command command 87 | * @param isRoot whether need to run with root 88 | * @param isNeedResultMsg whether need result msg 89 | * @return 90 | * @see ShellUtils#execCommand(String[], boolean, boolean) 91 | */ 92 | public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { 93 | return execCommand(new String[] {command}, isRoot, isNeedResultMsg); 94 | } 95 | 96 | /** 97 | * execute shell commands 98 | * 99 | * @param commands command list 100 | * @param isRoot whether need to run with root 101 | * @param isNeedResultMsg whether need result msg 102 | * @return 103 | * @see ShellUtils#execCommand(String[], boolean, boolean) 104 | */ 105 | public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) { 106 | return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg); 107 | } 108 | 109 | /** 110 | * execute shell commands 111 | * 112 | * @param commands command array 113 | * @param isRoot whether need to run with root 114 | * @param isNeedResultMsg whether need result msg 115 | * @return
    116 | *
  • if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and 117 | * {@link CommandResult#errorMsg} is null.
  • 118 | *
  • if {@link CommandResult#result} is -1, there maybe some excepiton.
  • 119 | *
120 | */ 121 | public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) { 122 | int result = -1; 123 | if (commands == null || commands.length == 0) { 124 | return new CommandResult(result, null, null); 125 | } 126 | 127 | Process process = null; 128 | BufferedReader successResult = null; 129 | BufferedReader errorResult = null; 130 | StringBuilder successMsg = null; 131 | StringBuilder errorMsg = null; 132 | 133 | DataOutputStream os = null; 134 | try { 135 | process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); 136 | os = new DataOutputStream(process.getOutputStream()); 137 | for (String command : commands) { 138 | if (command == null) { 139 | continue; 140 | } 141 | 142 | // donnot use os.writeBytes(commmand), avoid chinese charset error 143 | os.write(command.getBytes()); 144 | os.writeBytes(COMMAND_LINE_END); 145 | os.flush(); 146 | } 147 | os.writeBytes(COMMAND_EXIT); 148 | os.flush(); 149 | 150 | result = process.waitFor(); 151 | // get command result 152 | if (isNeedResultMsg) { 153 | successMsg = new StringBuilder(); 154 | errorMsg = new StringBuilder(); 155 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); 156 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); 157 | String s; 158 | while ((s = successResult.readLine()) != null) { 159 | successMsg.append(s); 160 | } 161 | while ((s = errorResult.readLine()) != null) { 162 | errorMsg.append(s); 163 | } 164 | } 165 | } catch (IOException e) { 166 | e.printStackTrace(); 167 | } catch (Exception e) { 168 | e.printStackTrace(); 169 | } finally { 170 | try { 171 | if (os != null) { 172 | os.close(); 173 | } 174 | if (successResult != null) { 175 | successResult.close(); 176 | } 177 | if (errorResult != null) { 178 | errorResult.close(); 179 | } 180 | } catch (IOException e) { 181 | e.printStackTrace(); 182 | } 183 | 184 | if (process != null) { 185 | process.destroy(); 186 | } 187 | } 188 | return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null 189 | : errorMsg.toString()); 190 | } 191 | 192 | /** 193 | * result of command 194 | *
    195 | *
  • {@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in 196 | * linux shell
  • 197 | *
  • {@link CommandResult#successMsg} means success message of command result
  • 198 | *
  • {@link CommandResult#errorMsg} means error message of command result
  • 199 | *
200 | * 201 | * @author Trinea 2013-5-16 202 | */ 203 | public static class CommandResult { 204 | 205 | /** result of command **/ 206 | public int result; 207 | /** success message of command result **/ 208 | public String successMsg; 209 | /** error message of command result **/ 210 | public String errorMsg; 211 | 212 | public CommandResult(int result) { 213 | this.result = result; 214 | } 215 | 216 | public CommandResult(int result, String successMsg, String errorMsg) { 217 | this.result = result; 218 | this.successMsg = successMsg; 219 | this.errorMsg = errorMsg; 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/Root/SuHelper.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.Root; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.util.Log; 7 | import com.coderstory.miui_toolkit.R; 8 | import java.io.BufferedReader; 9 | import java.io.DataOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.LineNumberReader; 13 | import java.io.UnsupportedEncodingException; 14 | import java.util.ArrayList; 15 | 16 | public abstract class SuHelper { 17 | 18 | /** 19 | * 执行所提交的命令组 20 | * @return 执行结果 21 | */ 22 | public final boolean execute() { 23 | boolean retval = false; 24 | try { 25 | ArrayList commands = getCommandsToExecute(); 26 | if (null != commands && commands.size() > 0) { 27 | Process process = Runtime.getRuntime().exec("su"); 28 | DataOutputStream os = new DataOutputStream(process.getOutputStream()); 29 | for (String currCommand : commands) { 30 | os.writeBytes(currCommand + "\n"); 31 | os.flush(); 32 | } 33 | os.writeBytes("exit\n"); 34 | os.flush(); 35 | BufferedReader reader = new BufferedReader(new InputStreamReader( 36 | process.getInputStream())); 37 | int read; 38 | char[] buffer = new char[4096]; 39 | StringBuilder output = new StringBuilder(); 40 | while ((read = reader.read(buffer)) > 0) { 41 | output.append(buffer, 0, read); 42 | } 43 | reader.close(); 44 | try { 45 | int suProcessRetval = process.waitFor(); 46 | retval = 255 != suProcessRetval; 47 | Log.d("gg", "execute: "+output.toString()); 48 | } catch (Exception ex) { 49 | //Log.e("Error executing root action", ex); 50 | } 51 | } 52 | } catch (IOException ex) { 53 | Log.w("ROOT", "Can't get root access", ex); 54 | } catch (Exception ex) { 55 | Log.w("ROOT", "Error executing internal operation", ex); 56 | } 57 | return retval; 58 | } 59 | protected abstract ArrayList getCommandsToExecute() throws UnsupportedEncodingException; 60 | 61 | 62 | /** 63 | * 弹窗确认后执行root命令 64 | * @param commandText 命令文本 65 | * @param messageText 提示信息 66 | * @param mContext context 67 | */ 68 | public static void showTips(final String commandText, String messageText, final Context mContext) { 69 | 70 | // SharedPreferences prefs = mContext.getSharedPreferences("UserSettings", Context.MODE_WORLD_READABLE); 71 | // final SharedPreferences.Editor editor = prefs.edit(); 72 | AlertDialog builder = new AlertDialog.Builder(mContext) 73 | .setTitle( R.string.Tips_Title) 74 | .setMessage(messageText) 75 | .setPositiveButton(R.string.Btn_Sure, new DialogInterface.OnClickListener() { 76 | @Override 77 | public void onClick(DialogInterface dialog, int which) { 78 | try { 79 | ArrayList strList = new ArrayList(); 80 | Process process = Runtime.getRuntime().exec(new String[]{"su", "-c", commandText}); 81 | // InputStream inputStream = process.getInputStream(); 82 | InputStreamReader ir = new InputStreamReader(process 83 | .getInputStream()); 84 | LineNumberReader input = new LineNumberReader(ir); 85 | String line; 86 | process.waitFor(); 87 | while ((line = input.readLine()) != null){ 88 | System.out.println(line); 89 | strList.add(line); 90 | } 91 | Log.d("aaaa", "onClick: "+strList.toString()); 92 | 93 | } catch (InterruptedException | IOException e1) { 94 | e1.printStackTrace(); 95 | } 96 | } 97 | }) 98 | .setNegativeButton(R.string.Btn_Cancel, new DialogInterface.OnClickListener() { 99 | @Override 100 | public void onClick(DialogInterface dialog, int which) { 101 | dialog.cancel(); 102 | } 103 | }).create(); 104 | builder.show(); 105 | } 106 | 107 | /** 108 | * 判断是否已经被授权root 109 | * @return boolean 110 | */ 111 | public static boolean canRunRootCommands() { 112 | boolean Result ; 113 | Process suProcess; 114 | 115 | try { 116 | suProcess = Runtime.getRuntime().exec("su"); 117 | 118 | DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); 119 | // DataInputStream osRes = new DataInputStream(suProcess.getInputStream()); 120 | BufferedReader din=new BufferedReader(new InputStreamReader(suProcess.getInputStream())); 121 | 122 | // Getting the id of the current user to check if this is root 123 | os.writeBytes("id\n"); 124 | os.flush(); 125 | 126 | String currUid = din.readLine(); 127 | boolean exitSu ; 128 | if (null == currUid) { 129 | Result = false; 130 | exitSu = false; 131 | Log.d("ROOT", "Can't get root access or denied by user"); 132 | } else if (currUid.contains("uid=0")) { 133 | Result = true; 134 | exitSu = true; 135 | Log.d("ROOT", "Root access granted"); 136 | } else { 137 | Result = false; 138 | exitSu = true; 139 | Log.d("ROOT", "Root access rejected: " + currUid); 140 | } 141 | 142 | if (exitSu) { 143 | os.writeBytes("exit\n"); 144 | os.flush(); 145 | } 146 | 147 | } catch (Exception e) { 148 | // Can't get root ! 149 | // Probably broken pipe exception on trying to write to output 150 | // stream after su failed, meaning that the device is not rooted 151 | Result = false; 152 | Log.d("ROOT", 153 | "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage()); 154 | } 155 | 156 | return Result; 157 | } 158 | } -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/Update/CheckUpdate.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.Update; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.Context; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.Message; 11 | import android.util.Log; 12 | import android.widget.Toast; 13 | 14 | import com.coderstory.miui_toolkit.R; 15 | import com.coderstory.miui_toolkit.service.UpdateService; 16 | 17 | import org.json.JSONException; 18 | import org.json.JSONObject; 19 | 20 | 21 | public class CheckUpdate { 22 | 23 | private Context mcontext = null; 24 | 25 | public CheckUpdate(Context context) { 26 | this.mcontext = context; 27 | } 28 | 29 | 30 | /** 31 | * 检测app的更新信息并保存到UpdateConfig中 32 | * 33 | */ 34 | private static void initUpdateInfo() { 35 | HttpHelper HH = new HttpHelper(); 36 | String result = HH.RequestUrl(UpdateConfig.UpdateServer); 37 | 38 | if (!result.equals("")) { 39 | 40 | JSONObject JsonString ;//转换为JSONObject 41 | try { 42 | JsonString = new JSONObject(result); 43 | UpdateConfig.URL = JsonString.getString("URL"); 44 | UpdateConfig.Version = JsonString.getString("Version"); 45 | UpdateConfig.Info = JsonString.getString("info"); 46 | } catch (JSONException e) { 47 | UpdateConfig.errorMsg = "Oops...软件更新服务器请求数据异常.."; 48 | } 49 | } 50 | } 51 | 52 | 53 | private Handler handler = new Handler() { 54 | @Override 55 | public void handleMessage(Message msg) { 56 | super.handleMessage(msg); 57 | Bundle data = msg.getData(); 58 | String val = data.getString("value"); 59 | Log.i("mylog", "请求结果为-->" + val); 60 | if (!UpdateConfig.errorMsg.equals("")) { 61 | Toast.makeText(mcontext, UpdateConfig.errorMsg, Toast.LENGTH_LONG).show(); 62 | } else { 63 | 64 | 65 | try { 66 | UpdateConfig.localVersion = mcontext.getPackageManager().getPackageInfo( 67 | mcontext.getPackageName(), 0).versionCode; // 设置本地版本号 68 | UpdateConfig.serverVersion = Integer.parseInt(UpdateConfig.Version); 69 | } catch (Exception ex) { 70 | ex.printStackTrace(); 71 | } 72 | 73 | if (UpdateConfig.localVersion < UpdateConfig.serverVersion) { 74 | 75 | // 发现新版本,提示用户更新 76 | AlertDialog.Builder alert = new AlertDialog.Builder(mcontext); 77 | alert.setTitle(R.string.App_Update) 78 | .setMessage(UpdateConfig.Info) 79 | .setPositiveButton(R.string.Update, 80 | new DialogInterface.OnClickListener() { 81 | public void onClick(DialogInterface dialog, 82 | int which) { 83 | // 开启更新服务UpdateService 84 | // 这里为了把update更好模块化,可以传一些updateService依赖的值 85 | // 如布局ID,资源ID,动态获取的标题,这里以app_name为例 86 | Intent updateIntent = new Intent( 87 | mcontext, 88 | UpdateService.class); 89 | updateIntent.putExtra("titleId", 90 | R.string.app_name); 91 | mcontext.startService(updateIntent); 92 | } 93 | }) 94 | .setNegativeButton(R.string.Btn_Cancel, 95 | new DialogInterface.OnClickListener() { 96 | public void onClick(DialogInterface dialog, 97 | int which) { 98 | dialog.dismiss(); 99 | } 100 | }); 101 | if (!((Activity) mcontext).isDestroyed() && ((Activity) mcontext).isFinishing()) { 102 | alert.create().show(); 103 | } 104 | } 105 | } 106 | } 107 | 108 | }; 109 | 110 | /** 111 | * 网络操作相关的子线程 112 | */ 113 | public Runnable networkTask = new Runnable() { 114 | 115 | @Override 116 | public void run() { 117 | // TODO 118 | // 在这里进行 http request.网络请求相关操作 119 | try { 120 | Thread.sleep(2000); 121 | } catch (InterruptedException e) { 122 | e.printStackTrace(); 123 | } 124 | initUpdateInfo(); 125 | Message msg = new Message(); 126 | Bundle data = new Bundle(); 127 | data.putString("value", "OK"); 128 | handler.sendMessage(msg); 129 | } 130 | }; 131 | 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/Update/HttpHelper.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.Update; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | /** 9 | * app更新 10 | */ 11 | class HttpHelper { 12 | /** 13 | * 调用接口 14 | * @param UpdateUrl 更新url地址 15 | * @return 16 | */ 17 | 18 | public String RequestUrl(String UpdateUrl) { 19 | String rvalue = ""; 20 | try { 21 | //声明URL 22 | URL url = new URL(UpdateUrl); 23 | //打开连接 24 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 25 | //设置连接方式 26 | conn.setRequestMethod("POST"); 27 | //获取返回值 28 | InputStream inStream = conn.getInputStream(); 29 | //流转化为字符串 30 | rvalue = streamToStr(inStream); 31 | } catch (Exception e) { 32 | // TODO Auto-generated catch block 33 | UpdateConfig.errorMsg = "Oops...软件更新服务器似乎挂掉了.."; 34 | // e.printStackTrace(); 35 | } 36 | return rvalue; 37 | } 38 | 39 | /** 40 | * 把流对象转换成字符串对象 41 | 42 | */ 43 | private String streamToStr(InputStream is) { 44 | try { 45 | // 定义字节数组输出流对象 46 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 47 | // 定义读取的长度 48 | int len ; 49 | // 定义读取的缓冲区 50 | byte buffer[] = new byte[1024]; 51 | // 按照定义的缓冲区进行循环读取,直到读取完毕为止 52 | while ((len = is.read(buffer)) != -1) { 53 | // 根据读取的长度写入到字节数组输出流对象中 54 | os.write(buffer, 0, len); 55 | } 56 | // 关闭流 57 | is.close(); 58 | os.close(); 59 | // 把读取的字节数组输出流对象转换成字节数组 60 | byte data[] = os.toByteArray(); 61 | // 按照指定的编码进行转换成字符串(此编码要与服务端的编码一致就不会出现乱码问题了,android默认的编码为UTF-8) 62 | return new String(data, "UTF-8"); 63 | } catch (IOException e) { 64 | UpdateConfig.errorMsg = "更新服务器访问失败,请稍后再试。。。"; 65 | e.printStackTrace(); 66 | return null; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/coderstory/miui_toolkit/tools/Update/UpdateConfig.java: -------------------------------------------------------------------------------- 1 | package com.coderstory.miui_toolkit.tools.Update; 2 | 3 | /** 4 | * APP在线功能的检测配置信息 5 | */ 6 | 7 | public class UpdateConfig { 8 | //版本信息 9 | static int localVersion = 0; 10 | static int serverVersion = 0; 11 | /* 下载包安装路径 */ 12 | public static final String saveFileName = "/Mi Kit/"; 13 | public static String URL = "";//app的下载地址 14 | public static String Version = "";//最新版的versionCode 15 | static String Info = ""; //更新内容 16 | static String errorMsg = ""; //错误提示 17 | static String UpdateServer = "http://blog.coderstory.cn/info"; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/src/main/res/drawable/launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/qr_alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/src/main/res/drawable/qr_alipay.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shooter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/src/main/res/drawable/shooter.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 32 | 33 | 44 | 45 | 58 | 59 | 72 | 73 | 83 | 84 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_disable_app.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_helper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 20 | 21 | 30 | 31 | 35 | 42 | 51 | 52 | 57 | 63 | 64 | 65 | 66 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_info_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 20 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 17 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderstory/Mi-Ki/6548edbfedcdc281e231dfd65620101848e5305c/app/src/main/res/mipmap-xxhdpi/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | #27b6d2 10 | #27b6d2 11 | #d027b6d2 12 | #d027b6d2 13 | #d027b6d2 14 | #b337ae60 15 | #00f7f7f7 16 | #cacaca 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Mi Kit 3 | 温馨提示 4 | 5 | 尚未获取Root权限,部分功能将被禁用! 6 | 取消 7 | 确定 8 | 错误 9 | 你确定要重启吗? 10 | 你确定要快速重启吗? 11 | 软件运行需要ROOT权限,\n点击确定开始授权. 12 | 隐藏应用图标 13 | 常见国外网站Hosts 14 | 屏蔽MIUI更新检测 15 | Android核心校验破解 16 | 屏蔽一些常见的广告 17 | 屏蔽大部分MIUI广告 18 | 移除下拉菜单搜索框 19 | MIUI主题和谐(旧版本通用) 20 | 快速重启系统 21 | 重启系统 22 | 通用设置 23 | 通用设置 24 | MIUI相关 25 | 关于 26 | 作者:油炸包子 27 | 版本:1.7.7正式版 28 | 1.7.7 29 | 我的博客:blog.coderstory.cn 30 | 特别说明 31 | SplashActivity 32 | <h6>1、先决条件</h6> <p>&emsp;&emsp;为使模块工作所需要 <a href=http://forum.xda-developers.com/xposed/unofficial-xposed-miui-t3367634>Xposed</a> 框架和安装 <a href=http://repo.xposed.info/module/de.robv.android.xposed.installer>Xposed Installer</a> 应用程序. <b>如果没有这个模块将无法正常工作!</b><br> 有关如何在您的设备安装Xposed框架请寻找与您的设备相关的论坛的信息。</p> <h6>2、设置您的设备</h6> <p>&emsp;&emsp;在安装Xposed框架和Xposed应用程序后,你必须在安全中心允许Xposed开机启动,神隐模式下设置为无限制。</p> <h6>3、模块的安装</h6> <p>&emsp;&emsp;该模块会安装为一个常规应用程序。<br> &emsp;&emsp;该模块第一次安装后,必须在Xposed模块界面勾选激活,然后重新启动设备。<br> &emsp;&emsp;如果执行步骤 2,你应该在Xposed看到新的模块已安装,但尚未激活的通知。</p> <h6>4、更新模块</h6> <p>&emsp;&emsp;更新模块也发生在常规应用程序更新。<br> &emsp;&emsp;如果你执行了步骤2,那么Xposed应该会发出新的模块已安装,需要重启你的设备的通知。<br> &emsp;&emsp;<b>如果不出现此通知,升级后模块需要手动打开Xposed,去模块选项卡,取消勾选,然后再重新勾选再重新启动设备!</b></p> <h6>5、卸载模块</h6> <p>&emsp;&emsp;把该模块当做是一个普通的应用程序正常卸载即可。</p> 33 | https://qr.qr_alipay.com/aex087445gnaa6gawjaohe8 34 | http://blog.coderstory.cn 35 | 软件升级 36 | 更新 37 | 创建下载文件失败! 38 | 旧数据删除失败! 39 | 正在下载 40 | 下载失败,请重试。 41 | 下载完成,点击安装。 42 | 正在处理中 43 | 可能需要花费数分钟时间... 44 | 尚未获得存储卡的读写权限,App在线功能已被禁用! 45 | 您是第一次打开本软件,是否阅读使用帮助? 46 | 警告 47 | 本软件的正常运行需要root权限,点击确定开始授权。\r\n\r\nPS:点击确定后无反应基本是禁止supersu自启导致的 48 | 检测到本模块未在Xposed框架中激活,部分功能将无法使用!\r\n\r\n请在Xposed中勾选本模块并重启系统,如还是出现提示则请卸载后重新安装. 49 |   冻结应用   50 | 冻结应用 51 | 提示:点击应用名可切换冻结状态 52 | 正在加载,请稍后。。。 53 | 正在加载应用信息。。。 54 | 你确定要解除   55 | 你确定要冻结  56 | 解冻 57 | 冻结 58 |  吗? 59 |  的冻结状态吗? 60 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 16 | 17 |