├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── xml │ │ │ ├── pref_aod.xml │ │ │ ├── pref_power.xml │ │ │ ├── pref_main.xml │ │ │ ├── pref_others.xml │ │ │ └── pref_colors.xml │ │ ├── layout │ │ │ ├── fragment_log.xml │ │ │ ├── activity_main.xml │ │ │ ├── vh.xml │ │ │ ├── activity_power_menu.xml │ │ │ └── item_view_layout.xml │ │ ├── drawable │ │ │ ├── ic_drag_handle_black_24dp.xml │ │ │ └── ic_close_black_24dp.xml │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── java │ │ └── com │ │ │ └── zacharee1 │ │ │ └── modcontrolredesign │ │ │ ├── util │ │ │ ├── BuildProp.kt │ │ │ ├── Stuff.kt │ │ │ └── SuUtils.kt │ │ │ ├── views │ │ │ └── NavBarDragItemView.kt │ │ │ ├── fragments │ │ │ ├── PowerFragment.kt │ │ │ ├── MainFragment.kt │ │ │ ├── OthersFragment.kt │ │ │ └── ColorsFragment.kt │ │ │ ├── activities │ │ │ └── PowerMenuActivity.kt │ │ │ └── StarterActivity.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .idea ├── vcs.xml ├── compiler.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml ├── misc.xml ├── codeStyles │ └── Project.xml └── assetWizardSettings.xml ├── gradle.properties ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zacharee/ModControlRedesign/master/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /app/src/main/res/xml/pref_aod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 18 21:41:49 EST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_log.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_drag_handle_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #311b92 4 | #000063 5 | #6746c3 6 | #1976d2 7 | #004ba0 8 | #63a4ff 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/vh.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/xml/pref_power.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_power_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/util/BuildProp.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.util 2 | 3 | object BuildProp { 4 | val c: Class<*> = Class.forName("android.os.SystemProperties") 5 | 6 | fun readValueOfKey(key: String): String { 7 | return try { 8 | val method = c.getMethod("get", String::class.java) 9 | method.invoke(null, key).toString() 10 | } catch (e: Exception) { 11 | SuUtils.sudoForResult("getprop $key") 12 | } 13 | } 14 | 15 | fun setValueForKey(key: String, value: String) { 16 | try { 17 | val method = c.getMethod("set", String::class.java, String::class.java) 18 | method.invoke(null, key, value) 19 | } catch (e: Exception) { 20 | SuUtils.sudo("setprop $key $value") 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\Android_Studio\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_view_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | 19 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/views/NavBarDragItemView.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.views 2 | 3 | import android.content.Context 4 | import android.support.constraint.ConstraintLayout 5 | import android.util.AttributeSet 6 | import android.view.View 7 | import android.widget.LinearLayout 8 | import android.widget.Switch 9 | import com.zacharee1.modcontrolredesign.R 10 | import com.zacharee1.modcontrolredesign.activities.PowerMenuActivity 11 | 12 | class NavBarDragItemView : LinearLayout { 13 | val switch: Switch 14 | 15 | var button: PowerMenuActivity.PowerButton? = null 16 | set(value) { 17 | field = value 18 | switch.text = context.resources.getText(value?.name ?: R.string.blank) 19 | switch.isChecked = value?.enabled ?: false 20 | } 21 | 22 | 23 | constructor(context: Context) : this(context, null) 24 | constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet) { 25 | View.inflate(context, R.layout.item_view_layout, this) 26 | switch = findViewById(R.id.toggle) 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/util/Stuff.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.util 2 | 3 | import android.os.Build 4 | 5 | object Stuff { 6 | const val V20 = "V20" 7 | const val G5 = "G5" 8 | 9 | const val V20_CODE = "elsa" 10 | const val G5_CODE = "h1" 11 | 12 | val isV20 = Build.DEVICE == V20_CODE 13 | val isSupportedDevice = Build.DEVICE == V20_CODE || Build.DEVICE == G5_CODE 14 | 15 | const val SS_CAPTURE = "sys.capture_signboard.enabled" 16 | 17 | const val BAT_STAT = "minbatsui" 18 | const val BAT_IMM = "battery_min_imm" 19 | const val BAT_AOD = "min_bat_aod" 20 | 21 | const val CLOCK_STAT = "minclocksui" 22 | const val CLOCK_IMM = "minclockimm" 23 | const val CLOCK_AOD = "minclockaod" 24 | 25 | const val STOCK_SIGNAL = "wide_data" 26 | const val WAKE_ON_PLUG = "wake_on_plug" 27 | const val CHARGE_WARN = "charge_warning" 28 | 29 | const val STATUS_BAR_HEIGHT = "status_bar_height" 30 | const val NAV_BAR_HEIGHT = "nav_bar_height" 31 | const val NAV_BAR_BUTTON_PADDING = "nav_bar_button_padding" 32 | 33 | const val NAV_COLOR_ENABLED = "nav_color_enabled" 34 | const val IMMERSIVE_SB_ENABLED = "allow_immersive_statusbar" 35 | 36 | const val ALLOW_HOME_SCREEN_WIDGETS = "allow_home_screen_widgets" 37 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | project.version = 16 8 | 9 | android { 10 | compileSdkVersion 27 11 | buildToolsVersion '27.0.3' 12 | defaultConfig { 13 | applicationId "com.zacharee1.modcontrolredesign" 14 | minSdkVersion 24 15 | targetSdkVersion 27 16 | versionCode project.version 17 | versionName project.version + "" 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.41" 30 | implementation 'com.android.support:appcompat-v7:27.1.1' 31 | implementation 'com.android.support:support-v4:27.1.1' 32 | implementation 'com.android.support.constraint:constraint-layout:1.1.0' 33 | implementation 'com.jaredrummler:colorpicker:1.0.1' 34 | implementation 'com.github.zacharee:SliderPreferenceEmbedded:5bef0529b0' 35 | implementation 'com.jmedeisis:draglinearlayout:1.1.0' 36 | implementation 'org.jsoup:jsoup:1.11.2' 37 | implementation 'io.reactivex.rxjava2:rxjava:2.1.12' 38 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 39 | implementation group: 'commons-io', name: 'commons-io', version: '2.4' 40 | } 41 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/assetWizardSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/xml/pref_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | 46 | 47 | 49 | 50 | 54 | 55 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/fragments/PowerFragment.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.fragments 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.graphics.Color 6 | import android.preference.Preference 7 | import android.preference.PreferenceFragment 8 | import android.preference.SwitchPreference 9 | import android.provider.Settings 10 | import android.support.v7.app.AppCompatActivity 11 | import com.jaredrummler.android.colorpicker.ColorPreference 12 | 13 | import com.zacharee1.modcontrolredesign.R 14 | import com.zacharee1.modcontrolredesign.activities.PowerMenuActivity 15 | import com.zacharee1.modcontrolredesign.util.Stuff 16 | 17 | class PowerFragment : PreferenceFragment() { 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | 22 | addPreferencesFromResource(R.xml.pref_power) 23 | (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) 24 | setSwitchListeners() 25 | setClickListeners() 26 | } 27 | 28 | private fun setSwitchListeners() { 29 | val aospPower = findPreference("aosp_power_menu") as SwitchPreference 30 | aospPower.setOnPreferenceChangeListener { pref, newValue -> 31 | Settings.Global.putInt(context.contentResolver, pref.key, if (newValue.toString().toBoolean()) 1 else 0) 32 | } 33 | aospPower.isChecked = Settings.Global.getInt(context.contentResolver, aospPower.key, 1) != 0 34 | 35 | val confirmPower = findPreference("should_confirm_poweroff") as SwitchPreference 36 | confirmPower.setOnPreferenceChangeListener { preference, newValue -> 37 | Settings.Global.putInt(context.contentResolver, preference.key, if (newValue.toString().toBoolean()) 1 else 0) 38 | } 39 | confirmPower.isChecked = Settings.Global.getInt(context.contentResolver, confirmPower.key, 1) != 0 40 | } 41 | 42 | private fun setClickListeners() { 43 | val edit = findPreference("edit_power_buttons") 44 | edit.setOnPreferenceClickListener { 45 | startActivity(Intent(context, PowerMenuActivity::class.java)) 46 | true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /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/src/main/java/com/zacharee1/modcontrolredesign/util/SuUtils.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.util 2 | 3 | import android.util.Log 4 | import java.io.* 5 | 6 | object SuUtils { 7 | @JvmStatic fun sudo(vararg strings: String) { 8 | try { 9 | val su = Runtime.getRuntime().exec("su") 10 | val outputStream = DataOutputStream(su.outputStream) 11 | 12 | for (s in strings) { 13 | outputStream.writeBytes(s + "\n") 14 | outputStream.flush() 15 | } 16 | 17 | outputStream.writeBytes("exit\n") 18 | outputStream.flush() 19 | try { 20 | su.waitFor() 21 | } catch (e: InterruptedException) { 22 | e.printStackTrace() 23 | Log.e("No Root?", e.message) 24 | } 25 | 26 | outputStream.close() 27 | } catch (e: IOException) { 28 | e.printStackTrace() 29 | } 30 | } 31 | 32 | @JvmStatic fun sudoForResult(vararg strings: String): String { 33 | return try { 34 | val su = Runtime.getRuntime().exec("su") 35 | val outputStream = DataOutputStream(su.outputStream) 36 | val reader = BufferedReader(InputStreamReader(su.inputStream)) 37 | 38 | for (s in strings) { 39 | outputStream.writeBytes(s + "\n") 40 | outputStream.flush() 41 | } 42 | 43 | outputStream.writeBytes("exit\n") 44 | outputStream.flush() 45 | 46 | val builder = StringBuilder() 47 | 48 | reader.forEachLine { 49 | builder.append(it + "\n") 50 | } 51 | 52 | outputStream.close() 53 | reader.close() 54 | 55 | builder.toString() 56 | } catch (e: IOException) { 57 | e.printStackTrace() 58 | "" 59 | } 60 | } 61 | 62 | fun testSudo(): Boolean { 63 | var st: StackTraceElement? = null 64 | 65 | try { 66 | val su = Runtime.getRuntime().exec("su") 67 | val outputStream = DataOutputStream(su.outputStream) 68 | 69 | outputStream.writeBytes("exit\n") 70 | outputStream.flush() 71 | 72 | val inputStream = DataInputStream(su.inputStream) 73 | val bufferedReader = BufferedReader(InputStreamReader(inputStream)) 74 | 75 | while (bufferedReader.readLine() != null) { 76 | bufferedReader.readLine() 77 | } 78 | 79 | su.waitFor() 80 | } catch (e: Exception) { 81 | e.printStackTrace() 82 | for (s in e.stackTrace) { 83 | st = s 84 | if (st != null) break 85 | } 86 | } 87 | 88 | return st == null 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/fragments/MainFragment.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.fragments 2 | 3 | import android.content.ComponentName 4 | import android.content.pm.PackageManager 5 | import android.os.Build 6 | import android.os.Bundle 7 | import android.preference.ListPreference 8 | import android.preference.PreferenceFragment 9 | import android.preference.SwitchPreference 10 | import android.support.v7.app.AppCompatActivity 11 | import com.zacharee1.modcontrolredesign.R 12 | import com.zacharee1.modcontrolredesign.StarterActivity 13 | import com.zacharee1.modcontrolredesign.util.Stuff 14 | import com.zacharee1.modcontrolredesign.util.SuUtils 15 | 16 | class MainFragment : PreferenceFragment() { 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | addPreferencesFromResource(R.xml.pref_main) 22 | setListeners() 23 | 24 | (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(false) 25 | } 26 | 27 | private fun setListeners() { 28 | findPreference("device").summary = resources.getString(R.string.current_device) + " " + if (Stuff.isV20) Stuff.V20 else Stuff.G5 29 | 30 | val restartSystemUI = findPreference("restart_sysui") 31 | restartSystemUI.setOnPreferenceClickListener { 32 | SuUtils.sudo("killall com.android.systemui") 33 | true 34 | } 35 | 36 | val hotReboot = findPreference("hot_reboot") 37 | hotReboot.setOnPreferenceClickListener { 38 | SuUtils.sudo("killall system_server") 39 | true 40 | } 41 | 42 | val checkForUpdates = findPreference("check_for_updates") 43 | checkForUpdates.setOnPreferenceClickListener { 44 | (activity as StarterActivity).checkVersion() 45 | true 46 | } 47 | 48 | val openColors = findPreference("color_mods") 49 | openColors.setOnPreferenceClickListener { 50 | activity.fragmentManager.beginTransaction().replace(R.id.content_main, ColorsFragment()).commit() 51 | true 52 | } 53 | 54 | val openOthers = findPreference("other_mods") 55 | openOthers.setOnPreferenceClickListener { 56 | activity.fragmentManager.beginTransaction().replace(R.id.content_main, OthersFragment()).commit() 57 | true 58 | } 59 | 60 | val openPower = findPreference("power_menu") 61 | openPower.setOnPreferenceClickListener { 62 | activity.fragmentManager.beginTransaction().replace(R.id.content_main, PowerFragment()).commit() 63 | true 64 | } 65 | 66 | val darkMode = findPreference("dark_mode") as SwitchPreference 67 | darkMode.setOnPreferenceChangeListener { _, _ -> 68 | activity.recreate() 69 | true 70 | } 71 | 72 | val showLauncher = findPreference("show_launcher") as SwitchPreference 73 | showLauncher.setOnPreferenceChangeListener { preference, any -> 74 | context.applicationContext.packageManager.setComponentEnabledSetting( 75 | ComponentName(context.packageName, 76 | context.packageName + ".LauncherActivity"), 77 | if (java.lang.Boolean.valueOf(any.toString())) 78 | PackageManager.COMPONENT_ENABLED_STATE_ENABLED 79 | else 80 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 81 | PackageManager.DONT_KILL_APP 82 | ) 83 | true 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/res/xml/pref_others.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 16 | 17 | 20 | 21 | 27 | 28 | 29 | 30 | 33 | 34 | 40 | 41 | 47 | 48 | 49 | 50 | 53 | 54 | 57 | 58 | 59 | 60 | 63 | 64 | 67 | 68 | 72 | 73 | 77 | 78 | 79 | 80 | 83 | 84 | 88 | 89 | 92 | 93 | 96 | 97 | 98 | 99 | 102 | 103 | 106 | 107 | 110 | 111 | 114 | 115 | 118 | 119 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/activities/PowerMenuActivity.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.activities 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.support.v7.app.AppCompatActivity 6 | import android.os.Bundle 7 | import android.provider.Settings 8 | import android.text.TextUtils 9 | import android.view.LayoutInflater 10 | import android.view.MenuItem 11 | import com.jmedeisis.draglinearlayout.DragLinearLayout 12 | import com.zacharee1.modcontrolredesign.R 13 | import com.zacharee1.modcontrolredesign.views.NavBarDragItemView 14 | import java.util.* 15 | import kotlin.collections.ArrayList 16 | 17 | class PowerMenuActivity : AppCompatActivity() { 18 | companion object { 19 | val ALL_KEYS = arrayListOf( 20 | "power", 21 | "reboot", 22 | "recovery", 23 | "airplane", 24 | "settings", 25 | "lockdown", 26 | "bugreport", 27 | "users", 28 | "assist", 29 | "voiceassist", 30 | "silent" 31 | ) 32 | } 33 | 34 | override fun onCreate(savedInstanceState: Bundle?) { 35 | super.onCreate(savedInstanceState) 36 | setContentView(R.layout.activity_power_menu) 37 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 38 | setUpDragger() 39 | } 40 | 41 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 42 | item?.let { 43 | when (it.itemId) { 44 | android.R.id.home -> finish() 45 | } 46 | } 47 | return super.onOptionsItemSelected(item) 48 | } 49 | 50 | private fun setUpDragger() { 51 | val orderer = findViewById(R.id.content_main) 52 | val buttons = ArrayList() 53 | 54 | val defaultOrder = getDefaultOrder() 55 | val customOrder = getCustomOrder() 56 | val order = ArrayList() 57 | 58 | if (customOrder.isEmpty()) order.addAll(defaultOrder) else order.addAll(customOrder) 59 | 60 | ALL_KEYS 61 | .map { PowerButton(it, false) } 62 | .filterNot { order.contains(it) } 63 | .forEach { order.add(it) } 64 | 65 | order.forEach { 66 | val buttonView = LayoutInflater.from(this).inflate(R.layout.vh, orderer, false) as NavBarDragItemView 67 | buttonView.button = it 68 | buttonView.switch.setOnCheckedChangeListener { _, isChecked -> 69 | buttonView.button?.enabled = isChecked 70 | updateOrder(buttons) 71 | } 72 | buttons.add(buttonView) 73 | 74 | orderer.addDragView(buttonView, buttonView.findViewById(R.id.handle)) 75 | orderer.setOnViewSwapListener { _, firstPosition, _, secondPosition -> 76 | Collections.swap(buttons, firstPosition, secondPosition) 77 | updateOrder(buttons) 78 | } 79 | orderer.setContainerScrollView(findViewById(R.id.container)) 80 | } 81 | } 82 | 83 | private fun updateOrder(list: ArrayList) { 84 | val enabled = ArrayList() 85 | 86 | list 87 | .filter { it.button?.enabled ?: false } 88 | .mapTo(enabled) { it.button?.key } 89 | 90 | Settings.Global.putString(contentResolver, "power_menu_buttons", TextUtils.join(",", enabled)) 91 | } 92 | 93 | @SuppressLint("PrivateApi") 94 | private fun getDefaultOrder(): ArrayList { 95 | val clazz = Class.forName("com.android.internal.R\$array") 96 | val arrayField = clazz.getField("config_globalActionsList") 97 | val arrayInt = arrayField.getInt(null) 98 | 99 | val ret = ArrayList() 100 | resources.getStringArray(arrayInt).forEach { 101 | ret.add(PowerButton(it, true)) 102 | } 103 | 104 | return ret 105 | } 106 | 107 | private fun getCustomOrder(): ArrayList { 108 | val ret = ArrayList() 109 | 110 | Settings.Global.getString(contentResolver, "power_menu_buttons")?.split(",")?.toTypedArray()?.filter { it.isNotEmpty() }?.forEach { 111 | ret.add(PowerButton(it, true)) 112 | } 113 | 114 | return ret 115 | } 116 | 117 | class PowerButton(var key: String?, var enabled: Boolean) { 118 | var name = when (key) { 119 | "power" -> R.string.power 120 | "reboot" -> R.string.reboot 121 | "recovery" -> R.string.recovery 122 | "airplane" -> R.string.airplane 123 | "settings" -> R.string.settings 124 | "lockdown" -> R.string.lockdown 125 | "bugreport" -> R.string.bugreport 126 | "users" -> R.string.users 127 | "silent" -> R.string.silent 128 | "assist" -> R.string.assist 129 | "voiceassist" -> R.string.voiceassist 130 | else -> R.string.blank 131 | } 132 | 133 | override fun equals(other: Any?): Boolean { 134 | if (other is PowerButton) { 135 | return name == other.name && key == other.key 136 | } 137 | 138 | return false 139 | } 140 | 141 | override fun hashCode(): Int { 142 | return name.hashCode() + (key?.hashCode() ?: 0) 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /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/src/main/res/xml/pref_colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 | 39 | 42 | 45 | 46 | 47 | 48 | 51 | 52 | 55 | 58 | 59 | 60 | 61 | 64 | 65 | 68 | 69 | 72 | 73 | 75 | 76 | 79 | 80 | 84 | 85 | 88 | 89 | 93 | 94 | 97 | 98 | 102 | 103 | 106 | 107 | 108 | 109 | 112 | 113 | 116 | 117 | 121 | 122 | 125 | 126 | 130 | 131 | 134 | 135 | 139 | 140 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Mod Control 3 | 4 | Device 5 | Color Mods 6 | Other Mods 7 | Power Menu Mods 8 | Dark Mode 9 | Signature Color 10 | AOD Signature Color 11 | NavBar Button Color 12 | First Toggle 13 | Second Toggle 14 | Third Toggle 15 | Fourth Toggle 16 | Fifth Toggle 17 | Sixth Toggle 18 | Seventh Toggle 19 | Eighth Toggle 20 | Ninth Toggle 21 | Tenth Toggle 22 | Eleventh Toggle 23 | Twelfth Toggle 24 | 3Minit Battery in Status Bar 25 | 3Minit Clock in Status Bar 26 | AOSP Signal Icon 27 | 3Minit Battery in AOD 28 | 3Minit Clock in AOD 29 | 3Minit Battery in Immersive Mode 30 | 3Minit Clock in Immersive Mode 31 | Wake On Plug 32 | Slow Charger Warning 33 | SignBoard in Screenshot 34 | Restart System UI 35 | Hot Reboot 36 | Reply From Lock Screen 37 | 38 | Detected Device: 39 | Change the color of certain elements of the UI. 40 | Toggle various UI options. 41 | Customize the power menu. 42 | Use dark theme in app. 43 | 3Minit Clock won\'t update in the AOD on the V20! 44 | Allow usage of notifications\' inline reply function while on the lock screen 45 | 46 | General 47 | Mods 48 | Other 49 | QuickTools 50 | Signatures 51 | Navigation Bar 52 | Status Bar 53 | AOD 54 | Immersive Status Bar 55 | Navigation Bar 56 | Enable 57 | 58 | Status Bar Size 59 | Navigation Bar Size 60 | Navigation Bar Button Padding 61 | Confirm Power-Off/Reboot 62 | 63 | 64 | Please grant the following permission to com.zacharee1.modcontrolredesign:\n\nandroid.permission.WRITE_SECURE_SETTINGS 65 | 66 | Your device, (%s), is unsupported. You need either an LG V20 (%s) or LG G5 (%s) to use this app. 67 | 68 | 69 | V20 70 | G5 71 | 72 | 73 | 0 74 | 1 75 | 76 | 77 | Force Back to First Screen 78 | Opaque 79 | Semi-Transparent 80 | Transparent 81 | Reset 82 | Force Use of Opaque Color 83 | Enable Button Coloring 84 | Second Screen 85 | You need to reboot to install the mods. Would you like to do that now? If not, the installation will happen when you next reboot to Recovery. 86 | 87 | Show Home Screen Widgets In Settings 88 | 89 | Power Off 90 | Reboot 91 | Recovery 92 | Airplane Mode 93 | Settings 94 | Lock Device 95 | Capture Bug Report 96 | Users 97 | Ringer Volume 98 | Assistant 99 | Voice Assistant 100 | 101 | AOSP Power Menu 102 | Edit Buttons 103 | 104 | 105 | Download Only 106 | 107 | Update Available! 108 | Check for Updates 109 | Missing Mods! 110 | Checking for updates… 111 | No updates found. 112 | 113 | An update for the mod pack, dated %s, is available. Would you like to download it now? 114 | It appears that you don\'t have any mods installed. This app won\'t do anything without them. Would you like to download them now? 115 | 116 | Always Allow Fingerprint Unlock 117 | Unable to check for updates. 118 | 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/fragments/OthersFragment.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.fragments 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.preference.PreferenceActivity 6 | import android.preference.PreferenceCategory 7 | import android.preference.PreferenceFragment 8 | import android.preference.SwitchPreference 9 | import android.provider.Settings 10 | import android.support.v7.app.AppCompatActivity 11 | import com.zacharee1.modcontrolredesign.R 12 | import com.zacharee1.modcontrolredesign.util.Stuff 13 | import com.zacharee1.modcontrolredesign.util.BuildProp 14 | import com.zacharee1.modcontrolredesign.util.SuUtils 15 | import com.zacharee1.sliderpreferenceembedded.SliderPreferenceEmbedded 16 | 17 | class OthersFragment : PreferenceFragment() { 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | addPreferencesFromResource(R.xml.pref_others) 22 | (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) 23 | 24 | setSwitchListeners() 25 | setSliderListeners() 26 | } 27 | 28 | private fun setSwitchListeners() { 29 | val minbatstat = Settings.Global.getInt(activity.contentResolver, Stuff.BAT_STAT, 0) 30 | val minclockstat = Settings.Global.getInt(activity.contentResolver, Stuff.CLOCK_STAT, 0) 31 | val aospsignal = Settings.Global.getInt(activity.contentResolver, Stuff.STOCK_SIGNAL, 1) 32 | 33 | val minbatimm = Settings.Global.getInt(activity.contentResolver, Stuff.BAT_IMM, 0) 34 | val minclockimm = Settings.Global.getInt(activity.contentResolver, Stuff.CLOCK_IMM, 0) 35 | 36 | val minbataod = Settings.Global.getInt(activity.contentResolver, Stuff.BAT_AOD, 0) 37 | val minclockaod = Settings.Global.getInt(activity.contentResolver, Stuff.CLOCK_AOD, 0) 38 | 39 | val wakeonplug = Settings.Global.getInt(activity.contentResolver, Stuff.WAKE_ON_PLUG, 1) 40 | val slowchargewarn = Settings.Global.getInt(activity.contentResolver, Stuff.CHARGE_WARN, 1) 41 | val ssScreenshot = BuildProp.readValueOfKey(Stuff.SS_CAPTURE) 42 | 43 | val homeWidgetsInSettings = Settings.Global.getInt(activity.contentResolver, Stuff.ALLOW_HOME_SCREEN_WIDGETS, 0) 44 | 45 | val immersiveSBEnabled = Settings.Global.getInt(activity.contentResolver, Stuff.IMMERSIVE_SB_ENABLED, 1) 46 | 47 | val overrideFingerprint = Settings.Global.getInt(activity.contentResolver, "override_allow_fingerprint", 0) 48 | 49 | if (Stuff.isV20) { 50 | val minbatimmSwitch = findPreference("minbatimm") as SwitchPreference 51 | val minclockimmSwitch = findPreference("minclockimm") as SwitchPreference 52 | val ssScreenshotSwitch = findPreference("sbscreen") as SwitchPreference 53 | val immersiveSB = findPreference(Stuff.IMMERSIVE_SB_ENABLED) as SwitchPreference 54 | val homeWidgetsInSettignsSwitch = findPreference(Stuff.ALLOW_HOME_SCREEN_WIDGETS) as SwitchPreference 55 | 56 | minbatimmSwitch.isChecked = minbatimm == 1 57 | minbatimmSwitch.setOnPreferenceChangeListener { _, any -> 58 | val newVal = java.lang.Boolean.valueOf(any.toString()) 59 | Settings.Global.putInt(activity.contentResolver, Stuff.BAT_IMM, if (newVal) 1 else 0) 60 | true 61 | } 62 | 63 | minclockimmSwitch.isChecked = minclockimm == 1 64 | minclockimmSwitch.setOnPreferenceChangeListener { _, any -> 65 | val newVal = java.lang.Boolean.valueOf(any.toString()) 66 | Settings.Global.putInt(activity.contentResolver, Stuff.CLOCK_IMM, if (newVal) 1 else 0) 67 | true 68 | } 69 | 70 | ssScreenshotSwitch.isChecked = ssScreenshot.contains("true") 71 | ssScreenshotSwitch.setOnPreferenceChangeListener { _, any -> 72 | val newVal = any.toString() 73 | BuildProp.setValueForKey(Stuff.SS_CAPTURE, newVal) 74 | true 75 | } 76 | 77 | immersiveSB.isChecked = immersiveSBEnabled == 1 78 | immersiveSB.setOnPreferenceChangeListener { _, any -> 79 | Settings.Global.putInt(activity.contentResolver, Stuff.IMMERSIVE_SB_ENABLED, if (any.toString().toBoolean()) 1 else 0) 80 | true 81 | } 82 | 83 | homeWidgetsInSettignsSwitch.isChecked = homeWidgetsInSettings == 1 84 | homeWidgetsInSettignsSwitch.setOnPreferenceChangeListener { _, any -> 85 | Settings.Global.putInt(activity.contentResolver, Stuff.ALLOW_HOME_SCREEN_WIDGETS, if (any.toString().toBoolean()) 1 else 0) 86 | true 87 | } 88 | } else { 89 | val immCategory = findPreference("immersive") as PreferenceCategory 90 | immCategory.isEnabled = false 91 | 92 | findPreference("sbscreen").isEnabled = false 93 | } 94 | 95 | val minbatstatSwitch = findPreference("minbatstat") as SwitchPreference 96 | val minclockstatSwitch = findPreference("minclockstat") as SwitchPreference 97 | val aospsignalSwitch = findPreference("aospsignal") as SwitchPreference 98 | 99 | minbatstatSwitch.isChecked = minbatstat == 1 100 | minbatstatSwitch.setOnPreferenceChangeListener { _, any -> 101 | val newVal = java.lang.Boolean.valueOf(any.toString()) 102 | Settings.Global.putInt(activity.contentResolver, Stuff.BAT_STAT, if (newVal) 1 else 0) 103 | true 104 | } 105 | 106 | minclockstatSwitch.isChecked = minclockstat == 1 107 | minclockstatSwitch.setOnPreferenceChangeListener { _, any -> 108 | val newVal = java.lang.Boolean.valueOf(any.toString()) 109 | Settings.Global.putInt(activity.contentResolver, Stuff.CLOCK_STAT, if (newVal) 1 else 0) 110 | true 111 | } 112 | 113 | aospsignalSwitch.isChecked = aospsignal != 1 114 | aospsignalSwitch.setOnPreferenceChangeListener { _, any -> 115 | val newVal = java.lang.Boolean.valueOf(any.toString()) 116 | Settings.Global.putInt(activity.contentResolver, Stuff.STOCK_SIGNAL, if (newVal) 0 else 1) 117 | SuUtils.sudo("killall com.android.systemui") 118 | true 119 | } 120 | 121 | val minbataodSwitch = findPreference("minbataod") as SwitchPreference 122 | val minclockaodSwitch = findPreference("minclockaod") as SwitchPreference 123 | 124 | minbataodSwitch.isChecked = minbataod == 1 125 | minbataodSwitch.setOnPreferenceChangeListener { _, any -> 126 | val newVal = java.lang.Boolean.valueOf(any.toString()) 127 | Settings.Global.putInt(activity.contentResolver, Stuff.BAT_AOD, if (newVal) 1 else 0) 128 | true 129 | } 130 | 131 | minclockaodSwitch.isChecked = minclockaod == 1 132 | minclockaodSwitch.setOnPreferenceChangeListener { _, any -> 133 | val newVal = java.lang.Boolean.valueOf(any.toString()) 134 | Settings.Global.putInt(activity.contentResolver, Stuff.CLOCK_AOD, if (newVal) 1 else 0) 135 | true 136 | } 137 | 138 | val slowchargewarnSwitch = findPreference("chargewarn") as SwitchPreference 139 | 140 | slowchargewarnSwitch.isChecked = slowchargewarn == 1 141 | slowchargewarnSwitch.setOnPreferenceChangeListener { _, any -> 142 | val newVal = java.lang.Boolean.valueOf(any.toString()) 143 | Settings.Global.putInt(activity.contentResolver, Stuff.CHARGE_WARN, if (newVal) 1 else 0) 144 | true 145 | } 146 | 147 | val wakeonplugSwitch = findPreference("wakeplug") as SwitchPreference 148 | 149 | wakeonplugSwitch.isChecked = wakeonplug == 1 150 | wakeonplugSwitch.setOnPreferenceChangeListener { _, any -> 151 | val newVal = java.lang.Boolean.valueOf(any.toString()) 152 | Settings.Global.putInt(activity.contentResolver, Stuff.WAKE_ON_PLUG, if (newVal) 1 else 0) 153 | true 154 | } 155 | 156 | val forceBasicInfo = Settings.Global.getInt(context.contentResolver, "force_show_basic_info", 1) == 1 157 | val forceBasicInfoSwitch = findPreference("force_basic_info") as SwitchPreference 158 | 159 | forceBasicInfoSwitch.isChecked = forceBasicInfo 160 | forceBasicInfoSwitch.setOnPreferenceChangeListener { _, any -> 161 | val newVal = any.toString().toBoolean() 162 | Settings.Global.putInt(context.contentResolver, "force_show_basic_info", if (newVal) 1 else 0) 163 | true 164 | } 165 | 166 | val lockReplySwitch = findPreference("lock_screen_allow_remote_input") as SwitchPreference 167 | lockReplySwitch.isChecked = Settings.Secure.getInt(activity.contentResolver, lockReplySwitch.key, 0) == 1 168 | lockReplySwitch.setOnPreferenceChangeListener { _, newValue -> 169 | Settings.Secure.putInt(activity.contentResolver, lockReplySwitch.key, if (newValue.toString().toBoolean()) 1 else 0) 170 | true 171 | } 172 | 173 | val overrideFingerprintSwitch = findPreference("override_allow_fingerprint") as SwitchPreference 174 | overrideFingerprintSwitch.isChecked = overrideFingerprint != 0 175 | overrideFingerprintSwitch.setOnPreferenceChangeListener { preference, newValue -> 176 | Settings.Global.putInt(context.contentResolver, preference.key, if (newValue.toString().toBoolean()) 1 else 0) 177 | true 178 | } 179 | } 180 | 181 | private fun setSliderListeners() { 182 | val statBarSize = findPreference("status_bar_height") as SliderPreferenceEmbedded 183 | val navBarSize = findPreference("nav_bar_height") as SliderPreferenceEmbedded 184 | val navBarButtonPadding = findPreference("nav_bar_button_padding") as SliderPreferenceEmbedded 185 | 186 | statBarSize.progress = Settings.Global.getInt(activity.contentResolver, Stuff.STATUS_BAR_HEIGHT, 24) 187 | navBarSize.progress = Settings.Global.getInt(activity.contentResolver, Stuff.NAV_BAR_HEIGHT, 42) 188 | navBarButtonPadding.progress = Settings.Global.getInt(activity.contentResolver, Stuff.NAV_BAR_BUTTON_PADDING, 0) 189 | 190 | statBarSize.setOnPreferenceChangeListener { _, any -> 191 | Settings.Global.putInt(activity.contentResolver, Stuff.STATUS_BAR_HEIGHT, Integer.valueOf(any.toString())) 192 | true 193 | } 194 | 195 | navBarSize.setOnPreferenceChangeListener { _, any -> 196 | Settings.Global.putInt(activity.contentResolver, Stuff.NAV_BAR_HEIGHT, Integer.valueOf(any.toString())) 197 | true 198 | } 199 | 200 | navBarButtonPadding.setOnPreferenceChangeListener { _, any -> 201 | Settings.Global.putInt(activity.contentResolver, Stuff.NAV_BAR_BUTTON_PADDING, Integer.valueOf(any.toString())) 202 | true 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/fragments/ColorsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign.fragments 2 | 3 | import android.os.Bundle 4 | import android.graphics.Color 5 | import android.preference.Preference 6 | import android.preference.PreferenceFragment 7 | import android.preference.SwitchPreference 8 | import android.provider.Settings 9 | import android.support.v7.app.AppCompatActivity 10 | import com.jaredrummler.android.colorpicker.ColorPreference 11 | 12 | import com.zacharee1.modcontrolredesign.R 13 | import com.zacharee1.modcontrolredesign.util.Stuff 14 | 15 | class ColorsFragment : PreferenceFragment() { 16 | 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | 20 | addPreferencesFromResource(R.xml.pref_colors) 21 | (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) 22 | 23 | setQTColors() 24 | setSigColors() 25 | setNavBarColors() 26 | setUpEnableDisableNavBarButtonColor() 27 | setUpBarColors() 28 | } 29 | 30 | private fun setQTColors() { 31 | if (Stuff.isV20) { 32 | val baseKeyRed = "redqt_" 33 | val baseKeyGreen = "greenqt_" 34 | val baseKeyBlue = "blueqt_" 35 | val prefKey = "qt_" 36 | 37 | for (i in 0..11) { 38 | val pref = findPreference(prefKey + i) as ColorPreference 39 | val colorRed = Settings.Global.getInt(activity.contentResolver, baseKeyRed + i, 0xff) 40 | val colorGreen = Settings.Global.getInt(activity.contentResolver, baseKeyGreen + i, 0xff) 41 | val colorBlue = Settings.Global.getInt(activity.contentResolver, baseKeyBlue + i, 0xff) 42 | val color = Color.argb(0xff, colorRed, colorGreen, colorBlue) 43 | pref.saveValue(color) 44 | 45 | pref.setOnPreferenceChangeListener { _, any -> 46 | val colorInt = Integer.valueOf(any.toString()) 47 | val red = Color.red(colorInt) 48 | val green = Color.green(colorInt) 49 | val blue = Color.blue(colorInt) 50 | 51 | Settings.Global.putInt(activity.contentResolver, baseKeyRed + i, red) 52 | Settings.Global.putInt(activity.contentResolver, baseKeyGreen + i, green) 53 | Settings.Global.putInt(activity.contentResolver, baseKeyBlue + i, blue) 54 | true 55 | } 56 | } 57 | } else { 58 | findPreference("quick_tools").isEnabled = false 59 | } 60 | } 61 | 62 | private fun setSigColors() { 63 | val sig = findPreference("sig_color") as ColorPreference 64 | val sigAod = findPreference("aod_sig_color") as ColorPreference 65 | val baseRed = "redsig" 66 | val baseGreen = "greensig" 67 | val baseBlue = "bluesig" 68 | val aod = "aod" 69 | 70 | if (!Stuff.isV20) sig.isEnabled = false 71 | 72 | val colorRed = Settings.Global.getInt(activity.contentResolver, baseRed, 0xff) 73 | val colorGreen = Settings.Global.getInt(activity.contentResolver, baseGreen, 0xff) 74 | val colorBlue = Settings.Global.getInt(activity.contentResolver, baseBlue, 0xff) 75 | val colorRedAod = Settings.Global.getInt(activity.contentResolver, baseRed + aod, 0xff) 76 | val colorGreenAod = Settings.Global.getInt(activity.contentResolver, baseGreen + aod, 0xff) 77 | val colorBlueAod = Settings.Global.getInt(activity.contentResolver, baseBlue + aod, 0xff) 78 | 79 | if (Stuff.isV20) sig.saveValue(Color.argb(0xff, colorRed, colorGreen, colorBlue)) 80 | sigAod.saveValue(Color.argb(0xff, colorRedAod, colorGreenAod, colorBlueAod)) 81 | 82 | if (Stuff.isV20) sig.setOnPreferenceChangeListener { _, any -> 83 | val color = Integer.valueOf(any.toString()) 84 | val red = Color.red(color) 85 | val green = Color.green(color) 86 | val blue = Color.blue(color) 87 | 88 | Settings.Global.putInt(activity.contentResolver, baseRed, red) 89 | Settings.Global.putInt(activity.contentResolver, baseGreen, green) 90 | Settings.Global.putInt(activity.contentResolver, baseBlue, blue) 91 | true 92 | } 93 | 94 | sigAod.setOnPreferenceChangeListener { _, any -> 95 | val color = Integer.valueOf(any.toString()) 96 | val red = Color.red(color) 97 | val green = Color.green(color) 98 | val blue = Color.blue(color) 99 | 100 | Settings.Global.putInt(activity.contentResolver, baseRed + aod, red) 101 | Settings.Global.putInt(activity.contentResolver, baseGreen + aod, green) 102 | Settings.Global.putInt(activity.contentResolver, baseBlue + aod, blue) 103 | true 104 | } 105 | } 106 | 107 | private fun setNavBarColors() { //using same method as QuickTools to allow for future changes (ie individual button coloring if I ever figure that out) 108 | val baseKeyRed = "rednav_" 109 | val baseKeyGreen = "greennav_" 110 | val baseKeyBlue = "bluenav_" 111 | val prefKey = "nav_" 112 | 113 | for (i in 0..0) { 114 | val pref = findPreference(prefKey + i) as ColorPreference 115 | val colorRed = Settings.Global.getInt(activity.contentResolver, baseKeyRed + i, 0xff) 116 | val colorGreen = Settings.Global.getInt(activity.contentResolver, baseKeyGreen + i, 0xff) 117 | val colorBlue = Settings.Global.getInt(activity.contentResolver, baseKeyBlue + i, 0xff) 118 | val color = Color.argb(0xff, colorRed, colorGreen, colorBlue) 119 | pref.saveValue(color) 120 | 121 | pref.setOnPreferenceChangeListener { _, any -> 122 | val colorInt = Integer.valueOf(any.toString()) 123 | val red = Color.red(colorInt) 124 | val green = Color.green(colorInt) 125 | val blue = Color.blue(colorInt) 126 | 127 | Settings.Global.putInt(activity.contentResolver, baseKeyRed + i, red) 128 | Settings.Global.putInt(activity.contentResolver, baseKeyGreen + i, green) 129 | Settings.Global.putInt(activity.contentResolver, baseKeyBlue + i, blue) 130 | true 131 | } 132 | } 133 | } 134 | 135 | private fun setUpEnableDisableNavBarButtonColor() { 136 | val navPref = findPreference("nav_0") as ColorPreference 137 | val enablePref = findPreference("enable_nav_color") as SwitchPreference 138 | 139 | val isEnabled = Settings.Global.getInt(activity.contentResolver, Stuff.NAV_COLOR_ENABLED, 0) != 0 140 | 141 | navPref.isEnabled = isEnabled 142 | enablePref.isChecked = isEnabled 143 | 144 | enablePref.setOnPreferenceChangeListener { _, any -> 145 | val enabled = java.lang.Boolean.valueOf(any.toString()) 146 | 147 | Settings.Global.putInt(activity.contentResolver, Stuff.NAV_COLOR_ENABLED, if (enabled) 1 else 0) 148 | navPref.isEnabled = enabled 149 | true 150 | } 151 | } 152 | 153 | private fun setUpBarColors() { 154 | val opaque = findPreference("nav_bar_color_opaque") as ColorPreference 155 | val semiTrans = findPreference("nav_bar_color_semi_transparent") as ColorPreference 156 | val trans = findPreference("nav_bar_color_transparent") as ColorPreference 157 | 158 | val opS = findPreference("stat_bar_color_opaque") as ColorPreference 159 | val stS = findPreference("stat_bar_color_semi_transparent") as ColorPreference 160 | val trS = findPreference("stat_bar_color_transparent") as ColorPreference 161 | 162 | val forceOpaque = findPreference("force_nav_bar_color") as SwitchPreference 163 | 164 | val forceOpS = findPreference("force_stat_bar_color") as SwitchPreference 165 | 166 | val resetO = findPreference("reset_nav_bar_color_opaque") 167 | val resetS = findPreference("reset_nav_bar_color_semi_transparent") 168 | val resetT = findPreference("reset_nav_bar_color_transparent") 169 | 170 | val resOS = findPreference("reset_stat_bar_color_opaque") 171 | val resSS = findPreference("reset_stat_bar_color_semi_transparent") 172 | val resTS = findPreference("reset_stat_bar_color_transparent") 173 | 174 | val savedOpaque = Settings.Global.getInt(context.contentResolver, "nav_bar_color_opaque", Color.BLACK) 175 | val savedSemi = Settings.Global.getInt(context.contentResolver, "nav_bar_color_semi_transparent", Color.parseColor("#66000000")) 176 | val savedTransparent = Settings.Global.getInt(context.contentResolver, "nav_bar_color_transparent", Color.TRANSPARENT) 177 | 178 | val savedOS = Settings.Global.getInt(context.contentResolver, "stat_bar_color_opaque", Color.BLACK) 179 | val savedSS = Settings.Global.getInt(context.contentResolver, "stat_bar_color_semi_transparent", Color.parseColor("#66000000")) 180 | val savedTS = Settings.Global.getInt(context.contentResolver, "stat_bar_color_transparent", Color.TRANSPARENT) 181 | 182 | opaque.saveValue(savedOpaque) 183 | semiTrans.saveValue(savedSemi) 184 | trans.saveValue(savedTransparent) 185 | 186 | opS.saveValue(savedOS) 187 | stS.saveValue(savedSS) 188 | trS.saveValue(savedTS) 189 | 190 | val listener = Preference.OnPreferenceChangeListener { preference, newValue -> 191 | Settings.Global.putInt(context.contentResolver, preference.key, newValue.toString().toInt()) 192 | true 193 | } 194 | 195 | opaque.onPreferenceChangeListener = listener 196 | semiTrans.onPreferenceChangeListener = listener 197 | trans.onPreferenceChangeListener = listener 198 | 199 | opS.onPreferenceChangeListener = listener 200 | stS.onPreferenceChangeListener = listener 201 | trS.onPreferenceChangeListener = listener 202 | 203 | val savedForce = Settings.Global.getInt(context.contentResolver, "force_nav_bar_color", 0) != 0 204 | 205 | val savedFS = Settings.Global.getInt(context.contentResolver, "force_stat_bar_color", 0) != 0 206 | 207 | forceOpaque.isChecked = savedForce 208 | 209 | forceOpS.isChecked = savedFS 210 | 211 | val forceListener = Preference.OnPreferenceChangeListener { preference, newValue -> 212 | var toSave = 0 213 | if (newValue.toString().toBoolean()) { 214 | toSave = 1 215 | } 216 | 217 | Settings.Global.putInt(context.contentResolver, preference.key, toSave) 218 | true 219 | } 220 | 221 | forceOpaque.onPreferenceChangeListener = forceListener 222 | 223 | forceOpS.onPreferenceChangeListener = forceListener 224 | 225 | val resetListener = Preference.OnPreferenceClickListener { preference -> 226 | val key = preference.key.replace("reset_", "") 227 | Settings.Global.putString(context.contentResolver, key, null) 228 | 229 | if (key.contains("opaque")) { 230 | if (key.contains("nav")) { 231 | opaque.saveValue(Color.BLACK) 232 | } else { 233 | opS.saveValue(Color.BLACK) 234 | } 235 | } else if (key.contains("semi")) { 236 | if (key.contains("nav")) { 237 | semiTrans.saveValue(Color.parseColor("#66000000")) 238 | } else { 239 | stS.saveValue(Color.parseColor("#66000000")) 240 | } 241 | } else { 242 | if (key.contains("nav")) { 243 | trans.saveValue(Color.TRANSPARENT) 244 | } else { 245 | trS.saveValue(Color.TRANSPARENT) 246 | } 247 | } 248 | 249 | true 250 | } 251 | 252 | resetO.onPreferenceClickListener = resetListener 253 | resetS.onPreferenceClickListener = resetListener 254 | resetT.onPreferenceClickListener = resetListener 255 | 256 | resOS.onPreferenceClickListener = resetListener 257 | resSS.onPreferenceClickListener = resetListener 258 | resTS.onPreferenceClickListener = resetListener 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /app/src/main/java/com/zacharee1/modcontrolredesign/StarterActivity.kt: -------------------------------------------------------------------------------- 1 | package com.zacharee1.modcontrolredesign 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.app.DownloadManager 6 | import android.content.* 7 | import android.content.pm.PackageManager 8 | import android.net.Uri 9 | import android.os.Build 10 | import android.support.v7.app.AppCompatActivity 11 | import android.os.Bundle 12 | import android.os.Environment 13 | import android.preference.PreferenceManager 14 | import android.provider.Settings 15 | import android.support.v7.app.AlertDialog 16 | import android.util.Log 17 | import android.view.MenuItem 18 | import android.widget.Toast 19 | import com.android.internal.R.id.date 20 | import com.zacharee1.modcontrolredesign.fragments.MainFragment 21 | import com.zacharee1.modcontrolredesign.util.Stuff 22 | import com.zacharee1.modcontrolredesign.util.SuUtils 23 | import io.reactivex.Observable 24 | import io.reactivex.Scheduler 25 | import io.reactivex.android.schedulers.AndroidSchedulers 26 | import io.reactivex.schedulers.Schedulers 27 | import org.apache.commons.io.IOUtils 28 | import org.json.JSONObject 29 | import org.jsoup.Jsoup 30 | import java.io.File 31 | import java.io.FileInputStream 32 | import java.io.FileNotFoundException 33 | import java.io.InputStream 34 | import java.net.URL 35 | import java.nio.charset.StandardCharsets 36 | import java.text.SimpleDateFormat 37 | import java.util.* 38 | 39 | class StarterActivity : AppCompatActivity() { 40 | companion object { 41 | const val REQ = 1001 42 | } 43 | 44 | private var date = ModDate() 45 | private var install = false 46 | 47 | override fun onCreate(savedInstanceState: Bundle?) { 48 | checkVersion() 49 | 50 | val useDark = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_mode", false) 51 | setTheme(if (useDark) R.style.AppTheme_Dark else R.style.AppTheme) 52 | 53 | super.onCreate(savedInstanceState) 54 | setContentView(R.layout.activity_main) 55 | 56 | if (!Stuff.isSupportedDevice) { 57 | AlertDialog.Builder(this) 58 | .setMessage(String.format(resources.getString(R.string.unsupported_device), Build.DEVICE, Stuff.V20_CODE, Stuff.G5_CODE)) 59 | .setPositiveButton("OK", null) 60 | .setOnDismissListener { 61 | finish() 62 | } 63 | .setCancelable(false) 64 | .show() 65 | } 66 | 67 | try { 68 | Settings.Global.putInt(contentResolver, "Mod Control", 1) 69 | goHome() 70 | } catch (e: Exception) { 71 | if (SuUtils.testSudo()) { 72 | try { 73 | SuUtils.sudo("pm grant com.zacharee1.modcontrolredesign android.permission.WRITE_SECURE_SETTINGS") 74 | goHome() 75 | } catch (e: Exception) { 76 | e.printStackTrace() 77 | } 78 | } else { 79 | AlertDialog.Builder(this) 80 | .setMessage(R.string.grant_perm_message) 81 | .setPositiveButton("OK", null) 82 | .setOnDismissListener { 83 | recreate() 84 | } 85 | .show() 86 | } 87 | } 88 | } 89 | 90 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 91 | if (item?.itemId == android.R.id.home) { 92 | goHome() 93 | return true 94 | } 95 | 96 | return false 97 | } 98 | 99 | override fun onBackPressed() { 100 | if (fragmentManager.findFragmentByTag("home") == null) { 101 | goHome() 102 | } else { 103 | super.onBackPressed() 104 | } 105 | } 106 | 107 | private fun goHome() { 108 | fragmentManager.beginTransaction().replace(R.id.content_main, MainFragment(), "home").commit() 109 | } 110 | 111 | fun checkVersion() { 112 | Toast.makeText(this, resources.getText(R.string.checking_for_updates), Toast.LENGTH_SHORT).show() 113 | Observable.fromCallable { loadAndParseAsync() } 114 | .subscribeOn(Schedulers.io()) 115 | .observeOn(AndroidSchedulers.mainThread()) 116 | .subscribe { 117 | if (it != null) { 118 | try { 119 | val currentDate = IOUtils.toString(FileInputStream("/system/mod_version_mdy"), StandardCharsets.UTF_8).split("_") 120 | val currentModDate = ModDate() 121 | currentModDate.month = currentDate[0].toInt() 122 | currentModDate.day = currentDate[1].toInt() 123 | currentModDate.year = currentDate[2].trim().toInt() 124 | 125 | if (currentModDate < it) { 126 | askToUpdate(it) 127 | } else { 128 | Toast.makeText(this, resources.getText(R.string.no_updates_found), Toast.LENGTH_SHORT).show() 129 | } 130 | } catch (e: FileNotFoundException) { 131 | askToInstall(it) 132 | } catch (e: NullPointerException) { 133 | askToInstall(it) 134 | } 135 | } else { 136 | Toast.makeText(this, resources.getText(R.string.check_updates_failed), Toast.LENGTH_SHORT).show() 137 | } 138 | } 139 | } 140 | 141 | private fun loadAndParseAsync(): ModDate? { 142 | 143 | return try { 144 | val modDate = ModDate() 145 | 146 | val content = IOUtils.toString(URL("https://api.github.com/repos/zacharee/V20Mods_Releases/releases/latest")) 147 | val json = JSONObject(content) 148 | 149 | val tag = json["tag_name"].toString().split("_") 150 | 151 | val asset = json.getJSONArray("assets").getJSONObject(0) 152 | val file = asset["browser_download_url"].toString() 153 | val name = asset["name"].toString() 154 | 155 | modDate.month = tag[0].toInt() 156 | modDate.day = tag[1].toInt() 157 | modDate.year = tag[2].toInt() 158 | modDate.url = file 159 | modDate.fileName = name 160 | 161 | modDate 162 | } catch (e: Exception) { 163 | null 164 | } 165 | 166 | } 167 | 168 | private fun askToUpdate(date: ModDate) { 169 | val dateFormat = SimpleDateFormat("MMMM dd, YYYY", Locale.getDefault()) 170 | 171 | AlertDialog.Builder(this) 172 | .setTitle(R.string.update_available) 173 | .setMessage(String.format(Locale.getDefault(), resources.getString(R.string.update_available_desc), dateFormat.format(date.time))) 174 | .setPositiveButton(android.R.string.yes, { _, _ -> 175 | openUrl(date, true) 176 | }) 177 | .setNeutralButton(R.string.download_only, { _, _ -> 178 | openUrl(date, false) 179 | }) 180 | .setNegativeButton(android.R.string.no, null) 181 | .setCancelable(false) 182 | .show() 183 | } 184 | 185 | private fun askToInstall(date: ModDate) { 186 | AlertDialog.Builder(this) 187 | .setTitle(R.string.mods_not_installed) 188 | .setMessage(R.string.mods_not_installed_desc) 189 | .setPositiveButton(android.R.string.yes, { _, _ -> 190 | openUrl(date, true) 191 | }) 192 | .setNeutralButton(R.string.download_only, { _, _ -> 193 | openUrl(date, false) 194 | }) 195 | .setNegativeButton(android.R.string.no, null) 196 | .setCancelable(false) 197 | .show() 198 | } 199 | 200 | private fun askToReboot() { 201 | AlertDialog.Builder(this) 202 | .setTitle(R.string.reboot) 203 | .setMessage(R.string.reboot_needed) 204 | .setCancelable(false) 205 | .setPositiveButton(android.R.string.yes, { _, _ -> 206 | SuUtils.sudo("reboot recovery") 207 | }) 208 | .setNegativeButton(android.R.string.no, null) 209 | .show() 210 | } 211 | 212 | private fun openUrl(date: ModDate, install: Boolean) { 213 | this.date = date 214 | this.install = install 215 | 216 | if (checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 217 | requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQ) 218 | } else { 219 | startDownload(date, install) 220 | } 221 | } 222 | 223 | private fun startDownload(date: ModDate, install: Boolean) { 224 | val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager 225 | 226 | val receiver = object : BroadcastReceiver() { 227 | override fun onReceive(context: Context?, intent: Intent?) { 228 | if (intent?.action == DownloadManager.ACTION_DOWNLOAD_COMPLETE) { 229 | unregisterReceiver(this) 230 | 231 | val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) 232 | if (id != -1L) { 233 | val query = DownloadManager.Query() 234 | query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL) 235 | val cursor = downloadManager.query(query) 236 | if (!cursor.moveToFirst()) { 237 | cursor.close() 238 | return 239 | } 240 | do { 241 | val reference = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID)) 242 | if (id == reference) { 243 | performInstall() 244 | } 245 | } while (cursor.moveToNext()) 246 | cursor.close() 247 | } 248 | } 249 | } 250 | } 251 | makeDirectoryIfNeeded() 252 | 253 | if (!fileExists(date.fileName)) { 254 | if (install) registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) 255 | 256 | val request = DownloadManager.Request(Uri.parse(date.url)) 257 | 258 | request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) 259 | request.setDestinationInExternalPublicDir("/V20Mods", date.fileName) 260 | downloadManager.enqueue(request) 261 | } else { 262 | if (install) performInstall() 263 | } 264 | } 265 | 266 | private fun performInstall() { 267 | SuUtils.sudo("echo '--update_package=/sdcard/0/V20Mods/${date.fileName}' >> /cache/recovery/command") 268 | askToReboot() 269 | } 270 | 271 | private fun makeDirectoryIfNeeded() { 272 | val directory = File(Environment.getExternalStorageDirectory().path + "/V20Mods") 273 | directory.mkdirs() 274 | } 275 | 276 | private fun fileExists(name: String): Boolean { 277 | val file = File(Environment.getExternalStorageDirectory().path + "/V20Mods/" + name) 278 | return file.exists() 279 | } 280 | 281 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { 282 | if (requestCode == REQ) { 283 | if (permissions.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE) 284 | && grantResults[permissions.indexOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)] == PackageManager.PERMISSION_GRANTED) { 285 | startDownload(date, install) 286 | } 287 | } 288 | } 289 | 290 | class ModDate : GregorianCalendar() { 291 | var month: Int 292 | get() { 293 | return get(Calendar.MONTH) + 1 294 | } 295 | set(value) { 296 | set(Calendar.MONTH, value - 1) 297 | } 298 | 299 | var day: Int 300 | get() { 301 | return get(Calendar.DATE) 302 | } 303 | set(value) { 304 | set(Calendar.DATE, value) 305 | } 306 | 307 | var year: Int 308 | get() { 309 | return get(Calendar.YEAR) 310 | } 311 | set(value) { 312 | var v = value 313 | if (value < 2000) v += 2000 314 | set(Calendar.YEAR, v) 315 | } 316 | 317 | var fileName: String = "" 318 | var url: String = "" 319 | 320 | override fun toString(): String { 321 | return "Month: ${month + 1}, Day: $day, Year: $year, URL: $url" 322 | } 323 | } 324 | } 325 | --------------------------------------------------------------------------------