├── .gitignore ├── .travis.yml ├── README.md ├── art └── screenshot.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library-no-op ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── sloydev │ └── preferator │ └── Preferator.kt ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── sloydev │ │ └── preferator │ │ ├── Preferator.kt │ │ ├── PreferatorActivity.kt │ │ ├── SdkFilter.kt │ │ └── editor │ │ ├── BooleanPrefEditor.kt │ │ ├── FloatPrefEditor.kt │ │ ├── IntPrefEditor.kt │ │ ├── LongPrefEditor.kt │ │ ├── SetPrefEditor.kt │ │ └── StringPrefEditor.kt │ └── res │ ├── drawable │ ├── ic_arrow_collapse_black_24dp.xml │ ├── ic_arrow_expand_black_24dp.xml │ └── ic_more_vert_black_24dp.xml │ ├── layout │ ├── activity_prefereitor.xml │ ├── item_editor_boolean.xml │ ├── item_editor_float.xml │ ├── item_editor_int.xml │ ├── item_editor_string.xml │ ├── item_preference.xml │ └── item_section.xml │ ├── menu │ └── pref_more_options.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── styles.xml ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── sloydev │ │ └── preferator │ │ └── demo │ │ └── DemoActivity.kt │ └── res │ ├── layout │ └── activity_demo.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── scripts └── bintrayUpload.sh └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/intellij,android,gradle,java 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff: 9 | .idea 10 | .idea/workspace.xml 11 | .idea/tasks.xml 12 | .idea/dictionaries 13 | .idea/vcs.xml 14 | .idea/jsLibraryMappings.xml 15 | 16 | # Sensitive or high-churn files: 17 | .idea/dataSources.ids 18 | .idea/dataSources.xml 19 | .idea/dataSources.local.xml 20 | .idea/sqlDataSources.xml 21 | .idea/dynamic.xml 22 | .idea/uiDesigner.xml 23 | 24 | # Gradle: 25 | .idea/gradle.xml 26 | .idea/libraries 27 | 28 | # Mongo Explorer plugin: 29 | .idea/mongoSettings.xml 30 | 31 | ## File-based project format: 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | fabric.properties 50 | 51 | ### Intellij Patch ### 52 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 53 | 54 | # *.iml 55 | # modules.xml 56 | 57 | 58 | ### Android ### 59 | # Built application files 60 | *.apk 61 | *.ap_ 62 | 63 | # Files for the ART/Dalvik VM 64 | *.dex 65 | 66 | # Java class files 67 | *.class 68 | 69 | # Generated files 70 | bin/ 71 | gen/ 72 | out/ 73 | 74 | # Gradle files 75 | .gradle/ 76 | build/ 77 | 78 | # Local configuration file (sdk path, etc) 79 | local.properties 80 | 81 | # Proguard folder generated by Eclipse 82 | proguard/ 83 | 84 | # Log Files 85 | *.log 86 | 87 | # Android Studio Navigation editor temp files 88 | .navigation/ 89 | 90 | # Android Studio captures folder 91 | captures/ 92 | 93 | # Intellij 94 | *.iml 95 | .idea/workspace.xml 96 | 97 | # Keystore files 98 | *.jks 99 | 100 | ### Android Patch ### 101 | gen-external-apklibs 102 | 103 | 104 | ### Java ### 105 | *.class 106 | 107 | # Mobile Tools for Java (J2ME) 108 | .mtj.tmp/ 109 | 110 | # Package Files # 111 | *.jar 112 | *.war 113 | *.ear 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | 118 | 119 | ### Gradle ### 120 | .gradle 121 | build/ 122 | 123 | # Ignore Gradle GUI config 124 | gradle-app.setting 125 | 126 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 127 | !gradle-wrapper.jar 128 | 129 | # Cache of project 130 | .gradletasknamecache 131 | 132 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 133 | # gradle/wrapper/gradle-wrapper.properties 134 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | branches: 4 | only: 5 | - master 6 | - /^v\d+\.\d+\.\d+$/ 7 | 8 | jdk: 9 | - oraclejdk8 10 | 11 | env: 12 | global: 13 | - TERM=dumb 14 | - GRADLE_OPTS="-Xmx512m -XX:MaxPermSize=512m" 15 | 16 | android: 17 | components: 18 | - tools 19 | - tools 20 | - platform-tools 21 | - build-tools-28.0.3 22 | - android-29 23 | - extra 24 | - addon 25 | 26 | licenses: 27 | - 'android-sdk-license-.+' 28 | 29 | install: /bin/true 30 | 31 | script: ./gradlew build 32 | 33 | deploy: 34 | - provider: script 35 | script: scripts/bintrayUpload.sh 36 | skip_cleanup: true 37 | on: 38 | tags: true 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Preferator 2 | 3 | [![Bintray](https://img.shields.io/bintray/v/sloy/maven/preferator.svg)](https://bintray.com/sloy/maven/preferator/) [![Build Status](https://travis-ci.org/Sloy/preferator.svg?branch=master)](https://travis-ci.org/Sloy/preferator) 4 | 5 | This Android library let's you edit your application SharedPreferences from the device itself. 6 | 7 | # Screenshot 8 | 9 | 10 | ## Usage 11 | 12 | It's a one-liner: 13 | 14 | ```java 15 | // From a button click in your debug menu or something 16 | Preferator.launch(context); 17 | ``` 18 | And you're good to go! 19 | 20 | ## Download 21 | 22 | Add it to your build.gradle: 23 | 24 | ```groovy 25 | dependencies{ 26 | debugCompile 'com.sloydev:preferator:1.4.0' 27 | releaseCompile 'com.sloydev:preferator-no-op:1.4.0' 28 | } 29 | ``` 30 | 31 | ## License 32 | 33 | ``` 34 | Copyright 2016 Rafa Vázquez 35 | 36 | 37 | Licensed under the Apache License, Version 2.0 (the "License"); 38 | you may not use this file except in compliance with the License. 39 | You may obtain a copy of the License at 40 | 41 | http://www.apache.org/licenses/LICENSE-2.0 42 | 43 | Unless required by applicable law or agreed to in writing, software 44 | distributed under the License is distributed on an "AS IS" BASIS, 45 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 46 | See the License for the specific language governing permissions and 47 | limitations under the License. 48 | ``` 49 | -------------------------------------------------------------------------------- /art/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sloy/preferator/891d8e22f06d4ff8dd5a6a93da9d82936d347e86/art/screenshot.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.4.0' 3 | repositories { 4 | jcenter() 5 | google() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.4.1' 9 | classpath 'com.novoda:bintray-release:0.9.1' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | jcenter() 17 | google() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | org.gradle.jvmargs=-Xmx1536m -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sloy/preferator/891d8e22f06d4ff8dd5a6a93da9d82936d347e86/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library-no-op/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'com.novoda.bintray-release' 4 | 5 | android { 6 | compileSdkVersion 29 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | } 15 | lintOptions { 16 | abortOnError false 17 | } 18 | compileOptions { 19 | sourceCompatibility JavaVersion.VERSION_1_8 20 | targetCompatibility JavaVersion.VERSION_1_8 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 26 | 27 | implementation 'androidx.appcompat:appcompat:1.2.0' 28 | } 29 | 30 | publish { 31 | userOrg = 'sloy' 32 | groupId = 'com.sloydev' 33 | artifactId = 'preferator-no-op' 34 | publishVersion = '1.4.0' 35 | desc = 'Edit your app\'s SharedPreferences from your device' 36 | website = 'https://github.com/sloy/preferator' 37 | } -------------------------------------------------------------------------------- /library-no-op/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /library-no-op/src/main/java/com/sloydev/preferator/Preferator.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator 2 | 3 | import android.content.Context 4 | 5 | object Preferator { 6 | @JvmStatic 7 | fun launch(context: Context?) { 8 | // no-op 9 | } 10 | } -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'com.novoda.bintray-release' 4 | 5 | android { 6 | compileSdkVersion 29 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | lintOptions { 21 | abortOnError false 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 31 | 32 | implementation 'androidx.appcompat:appcompat:1.2.0' 33 | } 34 | 35 | publish { 36 | userOrg = 'sloy' 37 | groupId = 'com.sloydev' 38 | artifactId = 'preferator' 39 | publishVersion = '1.4.0' 40 | desc = 'Edit your app\'s SharedPreferences from your device' 41 | website = 'https://github.com/sloy/preferator' 42 | } -------------------------------------------------------------------------------- /library/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 /Users/rafa/Library/Android/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 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/Preferator.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | 6 | object Preferator { 7 | @JvmStatic 8 | fun launch(context: Context) { 9 | context.startActivity(Intent(context, PreferatorActivity::class.java)) 10 | } 11 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/PreferatorActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.MenuItem 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.widget.ImageView 11 | import android.widget.TextView 12 | import androidx.appcompat.app.AppCompatActivity 13 | import androidx.appcompat.widget.PopupMenu 14 | import androidx.core.app.ShareCompat 15 | import com.sloydev.preferator.editor.* 16 | import java.io.File 17 | 18 | class PreferatorActivity : AppCompatActivity() { 19 | private var sectionsView: ViewGroup? = null 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | setContentView(R.layout.activity_prefereitor) 24 | supportActionBar!!.setDisplayHomeAsUpEnabled(true) 25 | supportActionBar!!.subtitle = getApplicationName() 26 | 27 | sectionsView = findViewById(R.id.sections) as ViewGroup 28 | parsePreferences() 29 | } 30 | 31 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 32 | if (item.itemId == android.R.id.home) { 33 | finish() 34 | return true 35 | } else { 36 | return super.onOptionsItemSelected(item) 37 | } 38 | } 39 | 40 | private fun parsePreferences() { 41 | //TODO 42 | val rootPath = this.applicationInfo.dataDir + "/shared_prefs" 43 | val prefsFolder = File(rootPath) 44 | prefsFolder.list() 45 | .map { 46 | truncateXmlExtension(it) 47 | } 48 | .sortedWith(compareBy({ SdkFilter.isSdkPreference(it) }, { it })) 49 | .forEach { 50 | generateForm(it) 51 | } 52 | } 53 | 54 | private fun truncateXmlExtension(it: String): String { 55 | return if (it.endsWith(".xml")) 56 | it.substring(0, it.indexOf(".xml")) 57 | else 58 | it 59 | } 60 | 61 | private fun generateForm(prefsName: String) { 62 | val preferences = getSharedPreferences(prefsName) 63 | 64 | val filterValues = preferences.all.filterValues { 65 | it != null 66 | } as Map 67 | 68 | addSection(prefsName, filterValues.toList(), preferences) 69 | } 70 | 71 | private fun addSection(sectionTitle: String, entries: List>, preferences: SharedPreferences) { 72 | val sectionView = LayoutInflater.from(this).inflate(R.layout.item_section, sectionsView, false) 73 | val sectionNameContainer = sectionView.findViewById(R.id.section_name_container) 74 | val sectionNameView = sectionView.findViewById(R.id.section_name) as TextView 75 | val sectionArrowView = sectionView.findViewById(R.id.section_arrow) as ImageView 76 | val itemsView = sectionView.findViewById(R.id.section_items) as ViewGroup 77 | 78 | sectionNameView.text = sectionTitle 79 | sectionNameContainer.setOnClickListener { 80 | if (itemsView.visibility == View.VISIBLE) { 81 | itemsView.visibility = View.GONE 82 | sectionArrowView.setImageResource(R.drawable.ic_arrow_expand_black_24dp) 83 | } else { 84 | itemsView.visibility = View.VISIBLE 85 | sectionArrowView.setImageResource(R.drawable.ic_arrow_collapse_black_24dp) 86 | } 87 | } 88 | 89 | // Auto-collapse sdks 90 | if (SdkFilter.isSdkPreference(sectionTitle)) { 91 | itemsView.visibility = View.GONE 92 | sectionArrowView.setImageResource(R.drawable.ic_arrow_expand_black_24dp) 93 | } 94 | 95 | for (pref in entries) { 96 | val prefKey = pref.first 97 | val prefValue = pref.second 98 | val prefType = Type.of(prefValue) 99 | 100 | val itemView = LayoutInflater.from(this).inflate(R.layout.item_preference, itemsView, false) 101 | val nameView = itemView.findViewById(R.id.pref_name) 102 | val typeView = itemView.findViewById(R.id.pref_type) 103 | val moreView = itemView.findViewById(R.id.pref_more) 104 | 105 | nameView.text = prefKey 106 | typeView.text = prefType.typeName 107 | 108 | val editorContainer = itemView.findViewById(R.id.pref_value_editor_container) as ViewGroup 109 | val editorView = createEditorView(preferences, prefKey, prefValue, prefType) 110 | editorContainer.addView(editorView) 111 | 112 | val moreOptionsMenu = PopupMenu(this, moreView) 113 | moreOptionsMenu.inflate(R.menu.pref_more_options) 114 | moreOptionsMenu.setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item -> 115 | if (item.itemId == R.id.menu_pref_delete) { 116 | preferences.edit().remove(prefKey).apply() 117 | itemsView.removeView(itemView) 118 | return@OnMenuItemClickListener true 119 | } else if (item.itemId == R.id.menu_pref_share) { 120 | val sharedMessage = String.format("\"%s\":\"%s\"", prefKey, prefValue.toString()) 121 | ShareCompat.IntentBuilder.from(this@PreferatorActivity) 122 | .setText(sharedMessage) 123 | .setType("text/plain") 124 | .startChooser() 125 | return@OnMenuItemClickListener true 126 | } 127 | false 128 | }) 129 | moreView.setOnClickListener { moreOptionsMenu.show() } 130 | 131 | itemsView.addView(itemView) 132 | } 133 | 134 | sectionsView!!.addView(sectionView) 135 | } 136 | 137 | private fun createEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Any, prefType: Type): View { 138 | return when (prefType) { 139 | Type.STRING -> createStringEditorView(preferences, prefKey, prefValue as String) 140 | Type.INT -> createIntEditorView(preferences, prefKey, prefValue as Int) 141 | Type.LONG -> createLongEditorView(preferences, prefKey, prefValue as Long) 142 | Type.FLOAT -> createFloatEditorView(preferences, prefKey, prefValue as Float) 143 | Type.BOOLEAN -> createBooleanEditorView(preferences, prefKey, prefValue as Boolean) 144 | Type.SET -> createSetEditorView(preferences, prefKey, prefValue as Set) 145 | } 146 | } 147 | 148 | private fun createStringEditorView(preferences: SharedPreferences, prefKey: String, prefValue: String): StringPrefEditor { 149 | val stringEditor = StringPrefEditor(this) 150 | stringEditor.value = prefValue 151 | stringEditor.onStringValueChangeListener = { newValue -> preferences.edit().putString(prefKey, newValue).apply() } 152 | return stringEditor 153 | } 154 | 155 | private fun createIntEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Int?): IntPrefEditor { 156 | val intEditor = IntPrefEditor(this) 157 | intEditor.value = prefValue 158 | intEditor.onIntValueChangeListener = { newValue -> preferences.edit().putInt(prefKey, newValue).apply() } 159 | return intEditor 160 | } 161 | 162 | private fun createLongEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Long?): LongPrefEditor { 163 | val longEditor = LongPrefEditor(this) 164 | longEditor.value = prefValue 165 | longEditor.onLongValueChangeListener = { newValue -> preferences.edit().putLong(prefKey, newValue!!).apply() } 166 | return longEditor 167 | } 168 | 169 | private fun createFloatEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Float?): FloatPrefEditor { 170 | val floatEditor = FloatPrefEditor(this) 171 | floatEditor.value = prefValue 172 | floatEditor.onFloatValueChangeListener = { newValue -> preferences.edit().putFloat(prefKey, newValue).apply() } 173 | return floatEditor 174 | } 175 | 176 | private fun createBooleanEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Boolean?): BooleanPrefEditor { 177 | val booleanEditor = BooleanPrefEditor(this) 178 | booleanEditor.value = prefValue 179 | booleanEditor.onBooleanValueChangeListener = { newValue -> preferences.edit().putBoolean(prefKey, newValue).apply() } 180 | return booleanEditor 181 | } 182 | 183 | private fun createSetEditorView(preferences: SharedPreferences, prefKey: String, prefValue: Set): SetPrefEditor { 184 | val booleanEditor = SetPrefEditor(this) 185 | booleanEditor.value = prefValue 186 | booleanEditor.onSetValueChangeListener = { newValue -> preferences.edit().putStringSet(prefKey, newValue).apply() } 187 | return booleanEditor 188 | } 189 | 190 | private fun getSharedPreferences(name: String): SharedPreferences { 191 | return this.getSharedPreferences(name, Context.MODE_MULTI_PROCESS) 192 | } 193 | 194 | private enum class Type constructor(val typeName: String) { 195 | BOOLEAN("boolean"), 196 | INT("int"), 197 | LONG("long"), 198 | FLOAT("float"), 199 | STRING("string"), 200 | SET("set"); 201 | 202 | companion object { 203 | 204 | fun of(value: Any): Type { 205 | return when (value) { 206 | is String -> STRING 207 | is Int -> INT 208 | is Boolean -> BOOLEAN 209 | is Long -> LONG 210 | is Float -> FLOAT 211 | is Set<*> -> SET 212 | else -> { 213 | throw IllegalStateException("Not type matching found for " + value.javaClass.name) 214 | } 215 | } 216 | } 217 | } 218 | } 219 | 220 | private fun getApplicationName(): String { 221 | val applicationInfo = applicationInfo 222 | val stringId = applicationInfo.labelRes 223 | return if (stringId == 0) applicationInfo.nonLocalizedLabel.toString() else getString(stringId) 224 | } 225 | 226 | companion object { 227 | private val TAG = "Preferator" 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/SdkFilter.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator 2 | 3 | import org.intellij.lang.annotations.Language 4 | 5 | object SdkFilter { 6 | 7 | // HEY! YOU! Add your sdk here if you want it to be ignored :D 8 | @Language("RegExp") 9 | val ignoredSdkNamePatterns = listOf( 10 | // Adobe Analytics 11 | "APP_MEASUREMENT_CACHE", 12 | // Apptimize 13 | "apptimizenet.(.*)", 14 | // Braze 15 | "com.appboy.(.*)", 16 | // Chromium 17 | "WebViewChromiumPrefs", 18 | // Chuck 19 | "chuck_preferences", 20 | // ComScore 21 | "cSPrefs", 22 | // Custom Activity on Crash 23 | "custom_activity_on_crash", 24 | // Debug drawer 25 | "debug_drawer_(.*)", 26 | // Fabric 27 | "TwitterAdvertisingInfoPreferences", 28 | "io.fabric.sdk.android(.*)", 29 | "com.crashlytics.(.*)", 30 | // Google 31 | "com.google.(.*)", 32 | "fcm.(.*)", 33 | // Layer 34 | "layer(.*)", 35 | // Schibsted 36 | "com.schibsted.spt.tracking.(.*)", 37 | // Swrve 38 | "swrve_(.*)", 39 | // Xiti 40 | "ATPrefs" 41 | ) 42 | 43 | private val ignoredSdkNameRegexs = ignoredSdkNamePatterns.map { it.toRegex() } 44 | 45 | fun isSdkPreference(name: String): Boolean { 46 | return ignoredSdkNameRegexs.find { it.matches(name) } != null 47 | } 48 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/BooleanPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.LayoutInflater 6 | import android.widget.FrameLayout 7 | import android.widget.Switch 8 | import com.sloydev.preferator.R 9 | import java.lang.Boolean.FALSE 10 | 11 | class BooleanPrefEditor @JvmOverloads constructor( 12 | context: Context, 13 | attrs: AttributeSet? = null, 14 | defStyleAttr: Int = 0 15 | ) : FrameLayout(context, attrs, defStyleAttr) { 16 | 17 | private var valueView: Switch 18 | var onBooleanValueChangeListener: ((newValue: Boolean) -> Unit)? = null 19 | 20 | init { 21 | LayoutInflater.from(context).inflate(R.layout.item_editor_boolean, this, true) 22 | valueView = findViewById(R.id.pref_value_boolean) 23 | valueView.setOnCheckedChangeListener { _, isChecked -> 24 | onBooleanValueChangeListener?.invoke(isChecked) 25 | 26 | } 27 | } 28 | 29 | var value: Boolean? 30 | get() = valueView.isChecked 31 | set(value) { 32 | valueView.isChecked = value != FALSE 33 | } 34 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/FloatPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.text.Editable 5 | import android.text.TextWatcher 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import android.widget.EditText 9 | import android.widget.FrameLayout 10 | import com.sloydev.preferator.R 11 | 12 | class FloatPrefEditor @JvmOverloads constructor( 13 | context: Context, 14 | attrs: AttributeSet? = null, 15 | defStyleAttr: Int = 0 16 | ) : FrameLayout(context, attrs, defStyleAttr) { 17 | private var valueView: EditText 18 | var onFloatValueChangeListener: ((newValue: Float) -> Unit)? = null 19 | 20 | init { 21 | LayoutInflater.from(context).inflate(R.layout.item_editor_float, this, true) 22 | valueView = findViewById(R.id.pref_value) as EditText 23 | valueView.addTextChangedListener(object : TextWatcher { 24 | override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { 25 | onFloatValueChangeListener?.let { 26 | try { 27 | val number = charSequence.toString().toFloat() 28 | it.invoke(number) 29 | valueView.error = null 30 | } catch (e: NumberFormatException) { 31 | valueView.error = "Wrong float format" 32 | } 33 | } 34 | } 35 | 36 | override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} 37 | override fun afterTextChanged(editable: Editable) {} 38 | }) 39 | } 40 | 41 | var value: Float? 42 | get() = valueView.text.toString().toFloat() 43 | set(value) { 44 | valueView.setText(value?.toString()) 45 | } 46 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/IntPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.text.Editable 5 | import android.text.TextWatcher 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import android.widget.EditText 9 | import android.widget.FrameLayout 10 | import com.sloydev.preferator.R 11 | 12 | class IntPrefEditor @JvmOverloads constructor( 13 | context: Context, 14 | attrs: AttributeSet? = null, 15 | defStyleAttr: Int = 0 16 | ) : FrameLayout(context, attrs, defStyleAttr) { 17 | private var valueView: EditText 18 | var onIntValueChangeListener: ((newValue: Int) -> Unit)? = null 19 | 20 | init { 21 | LayoutInflater.from(context).inflate(R.layout.item_editor_int, this, true) 22 | valueView = findViewById(R.id.pref_value) as EditText 23 | valueView.addTextChangedListener(object : TextWatcher { 24 | override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { 25 | onIntValueChangeListener?.let { 26 | try { 27 | val number = charSequence.toString().toInt() 28 | it.invoke(number) 29 | valueView.error = null 30 | } catch (e: NumberFormatException) { 31 | valueView.error = "Wrong integer format" 32 | } 33 | } 34 | } 35 | 36 | override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} 37 | override fun afterTextChanged(editable: Editable) {} 38 | }) 39 | } 40 | 41 | var value: Int? 42 | get() = valueView.text.toString().toInt() 43 | set(value) { 44 | valueView.setText(value?.toString()) 45 | } 46 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/LongPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.text.Editable 5 | import android.text.TextWatcher 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import android.widget.EditText 9 | import android.widget.FrameLayout 10 | import com.sloydev.preferator.R 11 | 12 | class LongPrefEditor @JvmOverloads constructor( 13 | context: Context, 14 | attrs: AttributeSet? = null, 15 | defStyleAttr: Int = 0 16 | ) : FrameLayout(context, attrs, defStyleAttr) { 17 | private val valueView: EditText 18 | var onLongValueChangeListener: ((newValue: Long?) -> Unit)? = null 19 | 20 | init { 21 | LayoutInflater.from(context).inflate(R.layout.item_editor_int, this, true) 22 | valueView = findViewById(R.id.pref_value) as EditText 23 | valueView.addTextChangedListener(object : TextWatcher { 24 | override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { 25 | onLongValueChangeListener?.let { 26 | try { 27 | val number: Long = charSequence.toString().toLong() 28 | it.invoke(number) 29 | valueView.error = null 30 | } catch (e: NumberFormatException) { 31 | valueView.error = "Wrong long format" 32 | } 33 | } 34 | } 35 | 36 | override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} 37 | override fun afterTextChanged(editable: Editable) {} 38 | }) 39 | } 40 | 41 | var value: Long? 42 | get() = valueView.text.toString().toLong() 43 | set(value) { 44 | valueView.setText(value.toString()) 45 | } 46 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/SetPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.text.Editable 5 | import android.text.TextUtils 6 | import android.text.TextWatcher 7 | import android.util.AttributeSet 8 | import android.view.LayoutInflater 9 | import android.widget.EditText 10 | import android.widget.FrameLayout 11 | import com.sloydev.preferator.R 12 | import java.util.HashSet 13 | 14 | class SetPrefEditor @JvmOverloads constructor( 15 | context: Context, 16 | attrs: AttributeSet? = null, 17 | defStyleAttr: Int = 0 18 | ) : FrameLayout(context, attrs, defStyleAttr) { 19 | private val valueView: EditText 20 | var onSetValueChangeListener: ((Set) -> Unit)? = null 21 | 22 | init { 23 | LayoutInflater.from(context).inflate(R.layout.item_editor_string, this, true) 24 | valueView = findViewById(R.id.pref_value) as EditText 25 | valueView.addTextChangedListener(object : TextWatcher { 26 | override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { 27 | onSetValueChangeListener?.invoke(stringToSet(charSequence.toString())) 28 | } 29 | 30 | override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} 31 | override fun afterTextChanged(editable: Editable) {} 32 | }) 33 | } 34 | 35 | var value: Set 36 | get() { 37 | val rawValue = valueView.text.toString() 38 | return stringToSet(rawValue) 39 | } 40 | set(value) { 41 | valueView.setText(setToString(value)) 42 | } 43 | 44 | private fun stringToSet(rawValue: String): Set { 45 | val items = rawValue.split(",".toRegex()).toTypedArray() 46 | return HashSet(listOf(*items)) 47 | } 48 | 49 | private fun setToString(set: Set): String { 50 | return TextUtils.join(",", set) 51 | } 52 | } -------------------------------------------------------------------------------- /library/src/main/java/com/sloydev/preferator/editor/StringPrefEditor.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.editor 2 | 3 | import android.content.Context 4 | import android.text.Editable 5 | import android.text.TextWatcher 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import android.widget.EditText 9 | import android.widget.FrameLayout 10 | import com.sloydev.preferator.R 11 | 12 | class StringPrefEditor @JvmOverloads constructor( 13 | context: Context, 14 | attrs: AttributeSet? = null, 15 | defStyleAttr: Int = 0 16 | ) : FrameLayout(context, attrs, defStyleAttr) { 17 | private val valueView: EditText 18 | var onStringValueChangeListener: ((newValue: String) -> Unit)? = null 19 | 20 | init { 21 | LayoutInflater.from(context).inflate(R.layout.item_editor_string, this, true) 22 | valueView = findViewById(R.id.pref_value) as EditText 23 | valueView.addTextChangedListener(object : TextWatcher { 24 | override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) { 25 | onStringValueChangeListener?.invoke(charSequence.toString()) 26 | } 27 | 28 | override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {} 29 | override fun afterTextChanged(editable: Editable) {} 30 | }) 31 | } 32 | 33 | var value: String? 34 | get() = valueView.text.toString() 35 | set(value) { 36 | valueView.setText(value) 37 | } 38 | } -------------------------------------------------------------------------------- /library/src/main/res/drawable/ic_arrow_collapse_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/ic_arrow_expand_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/ic_more_vert_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/layout/activity_prefereitor.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_editor_boolean.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_editor_float.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_editor_int.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_editor_string.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 16 | 17 | 26 | 27 | 28 | 36 | 37 | 40 | 41 | 42 | 43 | 53 | 54 | 59 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 21 | 30 | 31 | 40 | 41 | 42 | 48 | 49 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /library/src/main/res/menu/pref_more_options.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /library/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #dadada 4 | 5 | #000000 6 | #ffffff 7 | #00000000 8 | #212121 9 | #757575 10 | 11 | @color/black_87 12 | @color/black_54 13 | 14 | -------------------------------------------------------------------------------- /library/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 8dp 4 | 5 | 20sp 6 | 20sp 7 | 16sp 8 | 9 | -------------------------------------------------------------------------------- /library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 12 | 13 | 17 | 18 | 23 | 24 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | 4 | sourceCompatibility = 1.7 5 | 6 | android { 7 | compileSdkVersion 29 8 | 9 | defaultConfig { 10 | applicationId "com.sloydev.preferator.demo" 11 | minSdkVersion 15 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_7 24 | targetCompatibility JavaVersion.VERSION_1_7 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 30 | 31 | implementation 'androidx.appcompat:appcompat:1.2.0' 32 | implementation 'androidx.preference:preference:1.1.1' 33 | 34 | debugImplementation project(':library') 35 | releaseImplementation project(':library-no-op') 36 | } -------------------------------------------------------------------------------- /sample/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 /Users/rafa/Library/Android/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 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /sample/src/main/java/com/sloydev/preferator/demo/DemoActivity.kt: -------------------------------------------------------------------------------- 1 | package com.sloydev.preferator.demo 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.os.Bundle 6 | import android.view.View 7 | import android.widget.Toast 8 | import androidx.appcompat.app.AppCompatActivity 9 | import androidx.preference.PreferenceManager 10 | import com.sloydev.preferator.Preferator 11 | import java.util.Arrays 12 | import java.util.HashSet 13 | 14 | class DemoActivity : AppCompatActivity() { 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | setContentView(R.layout.activity_demo) 18 | findViewById(R.id.demo_edit).setOnClickListener { Preferator.launch(this@DemoActivity) } 19 | findViewById(R.id.demo_prefill).setOnClickListener { prefillPreferences() } 20 | } 21 | 22 | private fun prefillPreferences() { 23 | fill(getPreferences(Context.MODE_PRIVATE)) 24 | fill(PreferenceManager.getDefaultSharedPreferences(this)) 25 | fill(getSharedPreferences("another file", Context.MODE_PRIVATE)) 26 | } 27 | 28 | private fun fill(preferences: SharedPreferences) { 29 | preferences 30 | .edit() 31 | .putString("some_string", "a string value") 32 | .putInt("some_int", 42) 33 | .putLong("some_long", System.currentTimeMillis()) 34 | .putBoolean("some_boolean", true) 35 | .putFloat("some_float", 3.14f) 36 | .putStringSet("some_set", HashSet(Arrays.asList("a", "b", "c"))) 37 | .apply() 38 | Toast.makeText(this, "Done", Toast.LENGTH_SHORT).show() 39 | } 40 | } -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 |