├── .github ├── FUNDING.yml └── workflows │ └── android.yml ├── .gitignore ├── AndroidResourceExtensions ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── net │ │ └── kibotu │ │ └── resourceextension │ │ ├── ManifestPermission.kt │ │ └── Resource+Extensions.kt │ └── res │ ├── values-ldltr │ └── ltr-config.xml │ ├── values-ldrtl │ └── rtl-config.xml │ └── values │ ├── colors.xml │ └── ltr-config.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── my_text.json │ ├── java │ └── net │ │ └── kibotu │ │ └── resourceextensions │ │ └── demo │ │ └── MainActivity.kt │ └── res │ ├── anim │ ├── grow.xml │ └── layout_animation.xml │ ├── animator │ └── flip_animation.xml │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── ic_launcher_background.xml │ └── ic_share.xml │ ├── font │ └── lato.ttf │ ├── layout │ └── activity_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── raw │ └── my_raw.json │ ├── values-de │ └── localized.xml │ ├── values │ ├── colors.xml │ ├── strings.xml │ ├── styles.xml │ └── values.xml │ └── xml │ └── lorem_ipsum.xml ├── build.gradle ├── dependencies.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── proguard-debug.pro ├── proguard-release.pro └── settings.gradle /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://paypal.me/janrabe/5 2 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | tags: [ "*" ] 7 | pull_request: 8 | branches: [ "master" ] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: set up JDK 17 17 | uses: actions/setup-java@v4 18 | with: 19 | java-version: '17' 20 | distribution: 'temurin' 21 | cache: gradle 22 | 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Build with Gradle 26 | run: ./gradlew build --refresh-dependencies --s 27 | 28 | publish: 29 | needs: build # Ensures that the 'publish' job runs after the 'build' job is successful 30 | if: startsWith(github.ref, 'refs/tags/') # Ensure this job only runs for tags 31 | runs-on: ubuntu-latest 32 | env: 33 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USER_NAME }} 34 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} 35 | ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }} 36 | ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_IN_MEMORY_KEY_ID }} 37 | ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }} 38 | steps: 39 | - uses: actions/checkout@v4 40 | - name: Extract version from tag 41 | id: extract_version 42 | run: | 43 | TAG_NAME=${GITHUB_REF#refs/tags/} 44 | if [[ $TAG_NAME =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 45 | echo "SEMVER_TAG=$TAG_NAME" >> $GITHUB_STATE 46 | else 47 | echo "Not a semver tag. Exiting..." 48 | exit 1 # Exit if it is not a semver tag. 49 | fi 50 | 51 | - name: Set up Maven Central Repository 52 | uses: actions/setup-java@v4 53 | with: 54 | java-version: '17' 55 | distribution: 'temurin' 56 | - name: Publish package to Maven Central Repository 57 | run: ./gradlew publishToMavenCentral --no-configuration-cache --s -Pversion=$GITHUB_REF_NAME 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bintray.properties 2 | 3 | # Created by https://www.gitignore.io/api/macos,gradle,windows,android,jetbrains,androidstudio 4 | 5 | ### Android ### 6 | # Built application files 7 | *.apk 8 | *.ap_ 9 | 10 | # Files for the ART/Dalvik VM 11 | *.dex 12 | 13 | # Java class files 14 | *.class 15 | 16 | # Generated files 17 | bin/ 18 | gen/ 19 | out/ 20 | 21 | # Gradle files 22 | .gradle/ 23 | build/ 24 | 25 | # Local configuration file (sdk path, etc) 26 | local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # Intellij 41 | *.iml 42 | .idea/workspace.xml 43 | .idea/tasks.xml 44 | .idea/gradle.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | 48 | # External native build folder generated in Android Studio 2.2 and later 49 | .externalNativeBuild 50 | 51 | # Freeline 52 | freeline.py 53 | freeline/ 54 | freeline_project_description.json 55 | 56 | ### Android Patch ### 57 | gen-external-apklibs 58 | 59 | ### AndroidStudio ### 60 | # Covers files to be ignored for android development using Android Studio. 61 | 62 | # Built application files 63 | 64 | # Files for the ART/Dalvik VM 65 | 66 | # Java class files 67 | 68 | # Generated files 69 | 70 | # Gradle files 71 | .gradle 72 | 73 | # Signing files 74 | .signing/ 75 | 76 | # Local configuration file (sdk path, etc) 77 | 78 | # Proguard folder generated by Eclipse 79 | 80 | # Log Files 81 | 82 | # Android Studio 83 | /*/build/ 84 | /*/local.properties 85 | /*/out 86 | /*/*/build 87 | /*/*/production 88 | *.ipr 89 | *~ 90 | *.swp 91 | 92 | # Android Patch 93 | 94 | # External native build folder generated in Android Studio 2.2 and later 95 | 96 | # NDK 97 | obj/ 98 | 99 | # IntelliJ IDEA 100 | *.iws 101 | /out/ 102 | 103 | # User-specific configurations 104 | .idea/libraries/ 105 | .idea/.name 106 | .idea/compiler.xml 107 | .idea/copyright/profiles_settings.xml 108 | .idea/encodings.xml 109 | .idea/misc.xml 110 | .idea/modules.xml 111 | .idea/scopes/scope_settings.xml 112 | .idea/vcs.xml 113 | .idea/jsLibraryMappings.xml 114 | .idea/datasources.xml 115 | .idea/dataSources.ids 116 | .idea/sqlDataSources.xml 117 | .idea/dynamic.xml 118 | .idea/uiDesigner.xml 119 | 120 | # OS-specific files 121 | .DS_Store 122 | .DS_Store? 123 | ._* 124 | .Spotlight-V100 125 | .Trashes 126 | ehthumbs.db 127 | Thumbs.db 128 | 129 | # Legacy Eclipse project files 130 | .classpath 131 | .project 132 | 133 | # Mobile Tools for Java (J2ME) 134 | .mtj.tmp/ 135 | 136 | # Package Files # 137 | *.war 138 | *.ear 139 | 140 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 141 | hs_err_pid* 142 | 143 | ## Plugin-specific files: 144 | 145 | # mpeltonen/sbt-idea plugin 146 | .idea_modules/ 147 | 148 | # JIRA plugin 149 | atlassian-ide-plugin.xml 150 | 151 | # Mongo Explorer plugin 152 | .idea/mongoSettings.xml 153 | 154 | # Crashlytics plugin (for Android Studio and IntelliJ) 155 | com_crashlytics_export_strings.xml 156 | crashlytics.properties 157 | crashlytics-build.properties 158 | fabric.properties 159 | 160 | ### AndroidStudio Patch ### 161 | 162 | !/gradle/wrapper/gradle-wrapper.jar 163 | 164 | ### JetBrains ### 165 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 166 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 167 | 168 | # User-specific stuff: 169 | .idea/**/workspace.xml 170 | .idea/**/tasks.xml 171 | 172 | # Sensitive or high-churn files: 173 | .idea/**/dataSources/ 174 | .idea/**/dataSources.ids 175 | .idea/**/dataSources.xml 176 | .idea/**/dataSources.local.xml 177 | .idea/**/sqlDataSources.xml 178 | .idea/**/dynamic.xml 179 | .idea/**/uiDesigner.xml 180 | 181 | # Gradle: 182 | .idea/**/gradle.xml 183 | .idea/**/libraries 184 | 185 | # CMake 186 | cmake-build-debug/ 187 | 188 | # Mongo Explorer plugin: 189 | .idea/**/mongoSettings.xml 190 | 191 | ## File-based project format: 192 | 193 | ## Plugin-specific files: 194 | 195 | # IntelliJ 196 | 197 | # mpeltonen/sbt-idea plugin 198 | 199 | # JIRA plugin 200 | 201 | # Cursive Clojure plugin 202 | .idea/replstate.xml 203 | 204 | # Ruby plugin and RubyMine 205 | /.rakeTasks 206 | 207 | # Crashlytics plugin (for Android Studio and IntelliJ) 208 | 209 | ### JetBrains Patch ### 210 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 211 | 212 | # *.iml 213 | # modules.xml 214 | # .idea/misc.xml 215 | # *.ipr 216 | 217 | # Sonarlint plugin 218 | .idea/sonarlint 219 | 220 | ### macOS ### 221 | *.DS_Store 222 | .AppleDouble 223 | .LSOverride 224 | 225 | # Icon must end with two \r 226 | Icon 227 | 228 | # Thumbnails 229 | 230 | # Files that might appear in the root of a volume 231 | .DocumentRevisions-V100 232 | .fseventsd 233 | .TemporaryItems 234 | .VolumeIcon.icns 235 | .com.apple.timemachine.donotpresent 236 | 237 | # Directories potentially created on remote AFP share 238 | .AppleDB 239 | .AppleDesktop 240 | Network Trash Folder 241 | Temporary Items 242 | .apdisk 243 | 244 | ### Windows ### 245 | # Windows thumbnail cache files 246 | ehthumbs_vista.db 247 | 248 | # Folder config file 249 | Desktop.ini 250 | 251 | # Recycle Bin used on file shares 252 | $RECYCLE.BIN/ 253 | 254 | # Windows Installer files 255 | *.cab 256 | *.msi 257 | *.msm 258 | *.msp 259 | 260 | # Windows shortcuts 261 | *.lnk 262 | 263 | ### Gradle ### 264 | **/build/ 265 | 266 | # Ignore Gradle GUI config 267 | gradle-app.setting 268 | 269 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 270 | !gradle-wrapper.jar 271 | 272 | # Cache of project 273 | .gradletasknamecache 274 | 275 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 276 | # gradle/wrapper/gradle-wrapper.properties 277 | 278 | # End of https://www.gitignore.io/api/macos,gradle,windows,android,jetbrains,androidstudio 279 | 280 | .idea/ -------------------------------------------------------------------------------- /AndroidResourceExtensions/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | namespace "net.kibotu.resourceextension" 6 | compileSdk compileSdkVer 7 | buildToolsVersion = buildToolsVer 8 | 9 | defaultConfig { 10 | minSdk minSdkVer 11 | targetSdk targetSdkVer 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'consumer-rules.pro' 15 | } 16 | 17 | buildTypes { 18 | debug { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', '../proguard-debug.pro' 21 | } 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', '../proguard-release.pro' 25 | } 26 | } 27 | 28 | // region java compile options 29 | 30 | java { 31 | toolchain { 32 | languageVersion.set(JavaLanguageVersion.of(17)) 33 | } 34 | } 35 | 36 | compileOptions { 37 | sourceCompatibility JavaVersion.VERSION_17 38 | targetCompatibility JavaVersion.VERSION_17 39 | } 40 | 41 | // endregion 42 | 43 | // region kotlin compile options 44 | 45 | kotlinOptions { 46 | jvmTarget = "17" 47 | allWarningsAsErrors = false 48 | kotlinOptions.verbose = true 49 | freeCompilerArgs += [ 50 | "-Xjvm-default=all-compatibility" 51 | ] 52 | } 53 | 54 | // endregion 55 | 56 | // region exclude duplicated meta inf files 57 | 58 | packagingOptions { 59 | // DebugProbesKt.bin is used for java debugging (not needed for android) 60 | // Hint: https://github.com/Kotlin/kotlinx.coroutines/issues/2274 61 | exclude 'DebugProbesKt.bin' 62 | 63 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 64 | // https://stackoverflow.com/a/61893957/1006741 65 | excludes -= "/META-INF/*.kotlin_module" 66 | } 67 | 68 | // endregion 69 | } 70 | 71 | dependencies { 72 | coreLibraryDesugaring desugaring.jdk 73 | implementation libs.supportAppCompat 74 | implementation libs.applicationProvider 75 | } 76 | 77 | if (!isJitpack) { 78 | apply plugin: 'com.vanniktech.maven.publish' 79 | mavenPublishing { 80 | publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.CENTRAL_PORTAL, true) 81 | signAllPublications() 82 | } 83 | } 84 | 85 | if (isJitpack) { 86 | apply plugin: 'maven-publish' 87 | afterEvaluate { 88 | publishing { 89 | publications { 90 | release(MavenPublication) { 91 | from components.release 92 | groupId = GROUP 93 | artifactId = POM_ARTIFACT_ID 94 | version = version 95 | } 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/AndroidResourceExtensions/consumer-rules.pro -------------------------------------------------------------------------------- /AndroidResourceExtensions/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/java/net/kibotu/resourceextension/ManifestPermission.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("DEPRECATION") 2 | 3 | /** 4 | * Created by [Jan Rabe](https://kibotu.net/). 5 | */ 6 | 7 | package net.kibotu.resourceextension 8 | 9 | import android.Manifest 10 | import android.Manifest.permission.* 11 | import android.annotation.TargetApi 12 | import android.content.pm.PackageManager 13 | import android.os.Build 14 | import androidx.annotation.StringDef 15 | import androidx.core.app.ActivityCompat 16 | 17 | 18 | @TargetApi(Build.VERSION_CODES.TIRAMISU) 19 | @StringDef( 20 | value = [ 21 | ACCEPT_HANDOVER, 22 | ACCESS_BACKGROUND_LOCATION, 23 | ACCESS_BLOBS_ACROSS_USERS, 24 | ACCESS_CHECKIN_PROPERTIES, 25 | ACCESS_COARSE_LOCATION, 26 | ACCESS_FINE_LOCATION, 27 | ACCESS_LOCATION_EXTRA_COMMANDS, 28 | ACCESS_MEDIA_LOCATION, 29 | ACCESS_NETWORK_STATE, 30 | ACCESS_NOTIFICATION_POLICY, 31 | ACCESS_WIFI_STATE, 32 | ACCOUNT_MANAGER, 33 | ACTIVITY_RECOGNITION, 34 | ADD_VOICEMAIL, 35 | ANSWER_PHONE_CALLS, 36 | BATTERY_STATS, 37 | BIND_ACCESSIBILITY_SERVICE, 38 | BIND_APPWIDGET, 39 | BIND_AUTOFILL_SERVICE, 40 | BIND_CALL_REDIRECTION_SERVICE, 41 | BIND_CARRIER_MESSAGING_CLIENT_SERVICE, 42 | BIND_CARRIER_MESSAGING_SERVICE, 43 | BIND_CARRIER_SERVICES, 44 | BIND_CHOOSER_TARGET_SERVICE, 45 | BIND_COMPANION_DEVICE_SERVICE, 46 | BIND_CONDITION_PROVIDER_SERVICE, 47 | BIND_CONTROLS, 48 | BIND_DEVICE_ADMIN, 49 | BIND_DREAM_SERVICE, 50 | BIND_INCALL_SERVICE, 51 | BIND_INPUT_METHOD, 52 | BIND_MIDI_DEVICE_SERVICE, 53 | BIND_NFC_SERVICE, 54 | BIND_NOTIFICATION_LISTENER_SERVICE, 55 | BIND_PRINT_SERVICE, 56 | BIND_QUICK_ACCESS_WALLET_SERVICE, 57 | BIND_QUICK_SETTINGS_TILE, 58 | BIND_REMOTEVIEWS, 59 | BIND_SCREENING_SERVICE, 60 | BIND_TELECOM_CONNECTION_SERVICE, 61 | BIND_TEXT_SERVICE, 62 | BIND_TV_INPUT, 63 | BIND_VISUAL_VOICEMAIL_SERVICE, 64 | BIND_VOICE_INTERACTION, 65 | BIND_VPN_SERVICE, 66 | BIND_VR_LISTENER_SERVICE, 67 | BIND_WALLPAPER, 68 | BLUETOOTH, 69 | BLUETOOTH_ADMIN, 70 | BLUETOOTH_ADVERTISE, 71 | BLUETOOTH_CONNECT, 72 | BLUETOOTH_PRIVILEGED, 73 | BLUETOOTH_SCAN, 74 | BODY_SENSORS, 75 | BROADCAST_PACKAGE_REMOVED, 76 | BROADCAST_SMS, 77 | BROADCAST_STICKY, 78 | BROADCAST_WAP_PUSH, 79 | CALL_COMPANION_APP, 80 | CALL_PHONE, 81 | CALL_PRIVILEGED, 82 | CAMERA, 83 | CAPTURE_AUDIO_OUTPUT, 84 | CHANGE_COMPONENT_ENABLED_STATE, 85 | CHANGE_CONFIGURATION, 86 | CHANGE_NETWORK_STATE, 87 | CHANGE_WIFI_MULTICAST_STATE, 88 | CHANGE_WIFI_STATE, 89 | CLEAR_APP_CACHE, 90 | CONTROL_LOCATION_UPDATES, 91 | DELETE_CACHE_FILES, 92 | DELETE_PACKAGES, 93 | DIAGNOSTIC, 94 | DISABLE_KEYGUARD, 95 | DUMP, 96 | EXPAND_STATUS_BAR, 97 | FACTORY_TEST, 98 | FOREGROUND_SERVICE, 99 | GET_ACCOUNTS, 100 | GET_ACCOUNTS_PRIVILEGED, 101 | GET_PACKAGE_SIZE, 102 | GET_TASKS, 103 | GLOBAL_SEARCH, 104 | HIDE_OVERLAY_WINDOWS, 105 | HIGH_SAMPLING_RATE_SENSORS, 106 | INSTALL_LOCATION_PROVIDER, 107 | INSTALL_PACKAGES, 108 | INSTALL_SHORTCUT, 109 | INSTANT_APP_FOREGROUND_SERVICE, 110 | INTERACT_ACROSS_PROFILES, 111 | INTERNET, 112 | KILL_BACKGROUND_PROCESSES, 113 | LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK, 114 | LOADER_USAGE_STATS, 115 | LOCATION_HARDWARE, 116 | MANAGE_DOCUMENTS, 117 | MANAGE_EXTERNAL_STORAGE, 118 | MANAGE_MEDIA, 119 | MANAGE_ONGOING_CALLS, 120 | MANAGE_OWN_CALLS, 121 | MASTER_CLEAR, 122 | MEDIA_CONTENT_CONTROL, 123 | MODIFY_AUDIO_SETTINGS, 124 | MODIFY_PHONE_STATE, 125 | MOUNT_FORMAT_FILESYSTEMS, 126 | MOUNT_UNMOUNT_FILESYSTEMS, 127 | NFC, 128 | NFC_PREFERRED_PAYMENT_INFO, 129 | NFC_TRANSACTION_EVENT, 130 | PACKAGE_USAGE_STATS, 131 | PERSISTENT_ACTIVITY, 132 | PROCESS_OUTGOING_CALLS, 133 | QUERY_ALL_PACKAGES, 134 | READ_CALENDAR, 135 | READ_CALL_LOG, 136 | READ_CONTACTS, 137 | READ_EXTERNAL_STORAGE, 138 | READ_INPUT_STATE, 139 | READ_LOGS, 140 | READ_PHONE_NUMBERS, 141 | READ_PHONE_STATE, 142 | READ_PRECISE_PHONE_STATE, 143 | READ_SMS, 144 | READ_SYNC_SETTINGS, 145 | READ_SYNC_STATS, 146 | READ_VOICEMAIL, 147 | REBOOT, 148 | RECEIVE_BOOT_COMPLETED, 149 | RECEIVE_MMS, 150 | RECEIVE_SMS, 151 | RECEIVE_WAP_PUSH, 152 | RECORD_AUDIO, 153 | REORDER_TASKS, 154 | REQUEST_COMPANION_PROFILE_WATCH, 155 | REQUEST_COMPANION_RUN_IN_BACKGROUND, 156 | REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND, 157 | REQUEST_COMPANION_USE_DATA_IN_BACKGROUND, 158 | REQUEST_DELETE_PACKAGES, 159 | REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, 160 | REQUEST_INSTALL_PACKAGES, 161 | REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE, 162 | REQUEST_PASSWORD_COMPLEXITY, 163 | RESTART_PACKAGES, 164 | SCHEDULE_EXACT_ALARM, 165 | SEND_RESPOND_VIA_MESSAGE, 166 | SEND_SMS, 167 | SET_ALARM, 168 | SET_ALWAYS_FINISH, 169 | SET_ANIMATION_SCALE, 170 | SET_DEBUG_APP, 171 | SET_PREFERRED_APPLICATIONS, 172 | SET_PROCESS_LIMIT, 173 | SET_TIME, 174 | SET_TIME_ZONE, 175 | SET_WALLPAPER, 176 | SET_WALLPAPER_HINTS, 177 | SIGNAL_PERSISTENT_PROCESSES, 178 | SMS_FINANCIAL_TRANSACTIONS, 179 | START_FOREGROUND_SERVICES_FROM_BACKGROUND, 180 | START_VIEW_PERMISSION_USAGE, 181 | STATUS_BAR, 182 | SYSTEM_ALERT_WINDOW, 183 | TRANSMIT_IR, 184 | UNINSTALL_SHORTCUT, 185 | UPDATE_DEVICE_STATS, 186 | UPDATE_PACKAGES_WITHOUT_USER_ACTION, 187 | USE_BIOMETRIC, 188 | USE_FINGERPRINT, 189 | USE_FULL_SCREEN_INTENT, 190 | USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, 191 | USE_SIP, 192 | UWB_RANGING, 193 | VIBRATE, 194 | WAKE_LOCK, 195 | WRITE_APN_SETTINGS, 196 | WRITE_CALENDAR, 197 | WRITE_CALL_LOG, 198 | WRITE_CONTACTS, 199 | WRITE_EXTERNAL_STORAGE, 200 | WRITE_GSERVICES, 201 | WRITE_SECURE_SETTINGS, 202 | WRITE_SETTINGS, 203 | WRITE_SYNC_SETTINGS, 204 | WRITE_VOICEMAIL, 205 | ] 206 | ) 207 | @Retention(AnnotationRetention.SOURCE) 208 | @Target( 209 | allowedTargets = [AnnotationTarget.TYPE_PARAMETER, 210 | AnnotationTarget.PROPERTY, 211 | AnnotationTarget.FIELD, 212 | AnnotationTarget.LOCAL_VARIABLE, 213 | AnnotationTarget.VALUE_PARAMETER, 214 | AnnotationTarget.PROPERTY_GETTER, 215 | AnnotationTarget.PROPERTY_SETTER 216 | ] 217 | ) 218 | annotation class Permission 219 | 220 | @JvmInline 221 | value class ManifestPermission(@Permission val permission: String) 222 | 223 | /** 224 | * [Manifest.permission] 225 | */ 226 | val ManifestPermission.isGranted: Boolean 227 | get() { 228 | return ActivityCompat.checkSelfPermission( 229 | context, 230 | this.permission 231 | ) == PackageManager.PERMISSION_GRANTED 232 | } 233 | 234 | /** 235 | * [Manifest.permission] 236 | */ 237 | val String.isGranted: Boolean 238 | get() = ManifestPermission(this).isGranted 239 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/java/net/kibotu/resourceextension/Resource+Extensions.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("ResourceExtensions") 2 | 3 | package net.kibotu.resourceextension 4 | 5 | 6 | import android.animation.Animator 7 | import android.animation.AnimatorInflater 8 | import android.annotation.SuppressLint 9 | import android.content.Context 10 | import android.content.ContextWrapper 11 | import android.content.res.ColorStateList 12 | import android.content.res.Configuration 13 | import android.content.res.Resources 14 | import android.content.res.XmlResourceParser 15 | import android.graphics.Typeface 16 | import android.graphics.drawable.ColorDrawable 17 | import android.graphics.drawable.Drawable 18 | import android.graphics.drawable.GradientDrawable 19 | import android.net.Uri 20 | import android.os.Build 21 | import android.os.Build.VERSION.SDK_INT 22 | import android.os.Build.VERSION_CODES.JELLY_BEAN_MR1 23 | import android.os.Build.VERSION_CODES.N 24 | import android.text.Html 25 | import android.text.Spanned 26 | import android.transition.Transition 27 | import android.transition.TransitionInflater 28 | import android.util.TypedValue 29 | import android.view.LayoutInflater 30 | import android.view.View 31 | import android.view.ViewGroup 32 | import android.view.ViewParent 33 | import android.view.animation.Animation 34 | import android.view.animation.AnimationUtils 35 | import android.view.animation.Interpolator 36 | import android.view.animation.LayoutAnimationController 37 | import android.widget.TextView 38 | import androidx.annotation.* 39 | import androidx.core.content.ContextCompat 40 | import androidx.core.content.res.ResourcesCompat 41 | import androidx.core.content.res.use 42 | import com.github.florent37.application.provider.ActivityProvider.currentActivity 43 | import com.github.florent37.application.provider.application 44 | import java.io.ByteArrayOutputStream 45 | import java.io.InputStream 46 | import java.util.* 47 | 48 | 49 | /** 50 | * Created by [Jan Rabe](https://kibotu.net/). 51 | */ 52 | 53 | internal inline val context: ContextWrapper 54 | get() = currentActivity ?: requireNotNull(application) 55 | 56 | // region Values 57 | 58 | val @receiver:BoolRes Int.resBoolean: Boolean 59 | get() = context.resources.getBoolean(this) 60 | 61 | 62 | val @receiver:IntegerRes Int.resInt: Int 63 | get() = context.resources.getInteger(this) 64 | 65 | val @receiver:IntegerRes Int.resLong: Long 66 | get() = this.resInt.toLong() 67 | 68 | val @receiver:StringRes Int.resString: String 69 | get() = context.resources.getString(this) 70 | 71 | inline fun @receiver:StringRes Int.resString(vararg formatArgs: T): String { 72 | val context: ContextWrapper = currentActivity ?: requireNotNull(application) 73 | return context.resources.getString(this, *formatArgs) 74 | } 75 | 76 | /** 77 | * https://stackoverflow.com/a/9475663/1006741 78 | * 79 | * @param id string resource id 80 | * @param locale locale 81 | * @return localized string 82 | */ 83 | fun @receiver:StringRes Int.localizedString(locale: Locale = Locale.UK): String { 84 | 85 | if (SDK_INT > JELLY_BEAN_MR1) { 86 | return localizedResources(context, locale).getString(this) 87 | } 88 | 89 | val res = context.resources 90 | val conf = res.configuration 91 | val savedLocale = conf.locale 92 | conf.locale = locale // whatever you want here 93 | res.updateConfiguration(conf, null) // second arg null means don't change 94 | 95 | // retrieve resources from desired locale 96 | val text = res.getString(this) 97 | 98 | // restore original locale 99 | conf.locale = savedLocale 100 | res.updateConfiguration(conf, null) 101 | 102 | return text 103 | } 104 | 105 | fun @receiver:PluralsRes Int.quantityString(amount: Int): String = 106 | context.resources.getQuantityString(this, amount) 107 | 108 | inline fun @receiver:PluralsRes Int.quantityString( 109 | amount: Int, 110 | vararg formatArgs: T 111 | ): String { 112 | val context: ContextWrapper = currentActivity ?: requireNotNull(application) 113 | return context.resources.getQuantityString(this, amount, *formatArgs) 114 | } 115 | 116 | @RequiresApi(api = JELLY_BEAN_MR1) 117 | fun localizedResources( 118 | ctx: Context = context, 119 | desiredLocale: Locale = Locale.UK 120 | ): Resources { 121 | var conf = ctx.resources.configuration 122 | conf = Configuration(conf) 123 | conf.setLocale(desiredLocale) 124 | val localizedContext = ctx.createConfigurationContext(conf) 125 | return localizedContext.resources 126 | } 127 | 128 | val @receiver:ColorRes Int.resColorStateList: ColorStateList? 129 | get() = ContextCompat.getColorStateList(context, this) 130 | 131 | @get:ColorInt 132 | val @receiver:ColorRes Int.resColor: Int 133 | get() = ContextCompat.getColor(context, this) 134 | 135 | @get:ColorLong 136 | val @receiver:ColorRes Int.resColorLong: Long 137 | get() = ContextCompat.getColor(context, this).toLong() 138 | 139 | @get:Dimension 140 | val @receiver:DimenRes Int.resDimension: Float 141 | get() = context.resources.getDimension(this) 142 | 143 | fun @receiver:FractionRes Int.resFraction(base: Int, pbase: Int): Float = 144 | context.resources.getFraction(this, base, pbase) 145 | 146 | val @receiver:StringRes Int.html: Spanned 147 | get() = resString.html 148 | 149 | val String.html: Spanned 150 | get() = if (SDK_INT >= N) { 151 | Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY) 152 | } else { 153 | @Suppress("DEPRECATION") 154 | Html.fromHtml(this) 155 | } 156 | 157 | val @receiver:StringRes Int.csv: List 158 | get() = resString.split(",").map(String::trim) 159 | 160 | val @receiver:XmlRes Int.resXml: XmlResourceParser 161 | get() = context.resources.getXml(this) 162 | 163 | // endregion 164 | 165 | // region Arrays 166 | 167 | val @receiver:ArrayRes Int.resIntArray: IntArray 168 | get() = context.resources.getIntArray(this) 169 | 170 | val @receiver:ArrayRes Int.resStringArray: Array 171 | get() = context.resources.getStringArray(this) 172 | 173 | val @receiver:ArrayRes Int.resTextArray: Array 174 | get() = context.resources.getTextArray(this) 175 | 176 | /** 177 | * Returns -1 if not found 178 | */ 179 | @get:ColorRes 180 | val @receiver:ColorRes Int.resColorArray: List 181 | @SuppressLint("Recycle") 182 | get() = context.resources.obtainTypedArray(this).use { array -> 183 | (0 until array.length()).map { array.getResourceId(it, -1) } 184 | } 185 | 186 | @get:ColorInt 187 | val @receiver:ArrayRes Int.resColorIntArray: List 188 | get() = resColorArray.map { it.resColor } 189 | 190 | /** 191 | * Returns -1 if not found 192 | */ 193 | @get:DrawableRes 194 | val @receiver:ArrayRes Int.resDrawableIdArray: List 195 | @SuppressLint("Recycle") 196 | get() = context.resources.obtainTypedArray(this).use { array -> 197 | (0 until array.length()).map { array.getResourceId(it, -1) } 198 | } 199 | 200 | val @receiver:ArrayRes Int.resDrawableArray: List 201 | @SuppressLint("Recycle") 202 | get() = resDrawableIdArray.map { it.resDrawable } 203 | 204 | // endregion 205 | 206 | // region Ids 207 | 208 | /** 209 | * Returns -1 if not found 210 | */ 211 | @get:IdRes 212 | val String.resId: Int 213 | get() = context.resources.getIdentifier(this, "id", context.packageName) 214 | 215 | val @receiver:AnyRes Int.resName: String 216 | get() = context.resources.getResourceEntryName(this) 217 | 218 | val @receiver:AnyRes Int.resTypeName: String 219 | get() = context.resources.getResourceTypeName(this) 220 | 221 | val @receiver:AnyRes Int.resPackageName: String 222 | get() = context.resources.getResourcePackageName(this) 223 | 224 | @StringRes 225 | fun String.resStringId(onError: ((Exception) -> Unit)? = null): Int { 226 | try { 227 | return context.resources.getIdentifier(this, "string", context.packageName) 228 | } catch (e: Exception) { 229 | onError?.invoke(e) 230 | } 231 | return 0 232 | } 233 | 234 | @get:DrawableRes 235 | val String.resDrawableId: Int 236 | get() = context.resources.getIdentifier(this, "drawable", context.packageName) 237 | 238 | @DrawableRes 239 | fun String.resDrawableId(onError: ((Exception) -> Unit)? = null): Int { 240 | try { 241 | return context.resources.getIdentifier(this, "drawable", context.packageName) 242 | } catch (e: Exception) { 243 | onError?.invoke(e) 244 | } 245 | return 0 246 | } 247 | 248 | // endregion 249 | 250 | // region Objects 251 | 252 | val @receiver:DrawableRes Int.resDrawable: Drawable 253 | get() = requireNotNull(ContextCompat.getDrawable(context, this)) 254 | 255 | val @receiver:ColorRes Int.resColorDrawable: ColorDrawable 256 | get() = resColor.colorDrawable 257 | 258 | val @receiver:ColorRes Int.resGradientDrawable: GradientDrawable 259 | get() = ContextCompat.getDrawable(context, this) as GradientDrawable 260 | 261 | val @receiver:ColorInt Int.colorDrawable 262 | get() = ColorDrawable(this) 263 | 264 | val @receiver:AnimatorRes Int.resAnim: Animation 265 | get() = AnimationUtils.loadAnimation(context, this) 266 | 267 | val @receiver:AnimRes Int.resAnimator: Animator 268 | get() = AnimatorInflater.loadAnimator(context, this) 269 | 270 | val @receiver:FontRes Int.resFont: Typeface? 271 | @RequiresApi(Build.VERSION_CODES.O) 272 | get() = ResourcesCompat.getFont(context, this) 273 | 274 | val @receiver:RawRes Int.resRaw: InputStream 275 | get() = context.resources.openRawResource(this) 276 | 277 | val @receiver:InterpolatorRes Int.resInterpolator: Interpolator 278 | get() = AnimationUtils.loadInterpolator(context, this) 279 | 280 | val @receiver:AnimRes Int.resLayoutAnimation: LayoutAnimationController 281 | get() = AnimationUtils.loadLayoutAnimation(context, this) 282 | 283 | val @receiver:TransitionRes Int.resTransition: Transition 284 | @RequiresApi(Build.VERSION_CODES.KITKAT) 285 | get() = TransitionInflater.from(context).inflateTransition(this) 286 | 287 | // endregion 288 | 289 | // region Layout 290 | 291 | val @receiver:LayoutRes Int.resLayout: XmlResourceParser 292 | get() = context.resources.getLayout(this) 293 | 294 | fun @receiver:LayoutRes Int.inflate(parent: ViewParent?, attachToRoot: Boolean = false): View = 295 | LayoutInflater.from((parent as ViewGroup).context).inflate(this, parent, attachToRoot) 296 | 297 | // endregion 298 | 299 | // region Screen 300 | 301 | val Float.pt: Float 302 | get() = TypedValue.applyDimension( 303 | TypedValue.COMPLEX_UNIT_PT, 304 | this, 305 | context.resources.displayMetrics 306 | ) 307 | 308 | val Int.pt: Int get() = toFloat().pt.toInt() 309 | 310 | val Float.inches: Float 311 | get() = TypedValue.applyDimension( 312 | TypedValue.COMPLEX_UNIT_IN, 313 | this, 314 | context.resources.displayMetrics 315 | ) 316 | 317 | val Int.inches: Int get() = toFloat().inches.toInt() 318 | 319 | val Float.mm: Float 320 | get() = TypedValue.applyDimension( 321 | TypedValue.COMPLEX_UNIT_MM, 322 | this, 323 | context.resources.displayMetrics 324 | ) 325 | 326 | val Int.mm: Int get() = toFloat().mm.toInt() 327 | 328 | /** 329 | * Converts dp to pixel. 330 | */ 331 | val Float.dp: Float 332 | get() = TypedValue.applyDimension( 333 | TypedValue.COMPLEX_UNIT_DIP, 334 | this, 335 | context.resources.displayMetrics 336 | ) 337 | 338 | /** 339 | * Converts pixel to dp. 340 | */ 341 | val Float.px: Float get() = this / Resources.getSystem().displayMetrics.density // TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, this, context.resources.displayMetrics) 342 | 343 | /** 344 | * Converts dp to pixel. 345 | */ 346 | val Int.dp: Int get() = toFloat().dp.toInt() 347 | 348 | /** 349 | * Converts pixel to dp. 350 | */ 351 | val Int.px: Int get() = toFloat().px.toInt() 352 | 353 | val Int.sp: Float 354 | get() = TypedValue.applyDimension( 355 | TypedValue.COMPLEX_UNIT_SP, 356 | this.toFloat(), 357 | context.resources.displayMetrics 358 | ) 359 | 360 | val Float.sp: Float 361 | get() = TypedValue.applyDimension( 362 | TypedValue.COMPLEX_UNIT_SP, 363 | this, 364 | context.resources.displayMetrics 365 | ) 366 | 367 | var TextView.sp: Float 368 | set(value) = setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 369 | get() = textSize.sp 370 | 371 | val screenWidthDp: Int 372 | get() = Resources.getSystem().configuration.screenWidthDp 373 | 374 | val screenHeightDp: Int 375 | get() = Resources.getSystem().configuration.screenHeightDp 376 | 377 | val screenWidthPixels: Int 378 | get() = Resources.getSystem().displayMetrics.widthPixels 379 | 380 | val screenHeightPixels: Int 381 | get() = Resources.getSystem().displayMetrics.heightPixels 382 | 383 | // endregion 384 | 385 | // region Assets 386 | 387 | private val BUFFER_SIZE by lazy { 16 * 1024 } 388 | 389 | private val copyBuffer by lazy { ThreadLocal() } 390 | 391 | /** 392 | * Thread-Safe 393 | */ 394 | fun String.bytesFromAssets( 395 | ctx: Context? = context, 396 | onError: ((Exception) -> Unit)? = null 397 | ): ByteArray? = try { 398 | 399 | ctx?.assets?.open(this)?.use { inputStream -> 400 | 401 | ByteArrayOutputStream().use { buffer -> 402 | 403 | var byteBuffer = copyBuffer.get() 404 | if (byteBuffer == null) { 405 | byteBuffer = ByteArray(BUFFER_SIZE) 406 | copyBuffer.set(byteBuffer) 407 | } 408 | 409 | var readBytes: Int 410 | do { 411 | readBytes = inputStream.read(byteBuffer, 0, byteBuffer.size) 412 | if (readBytes != -1) 413 | buffer.write(byteBuffer, 0, readBytes) 414 | } while (readBytes != -1) 415 | 416 | buffer.flush() 417 | 418 | buffer.toByteArray() 419 | } 420 | } 421 | 422 | } catch (e: Exception) { 423 | onError?.invoke(e) 424 | null 425 | } 426 | 427 | fun String.stringFromAssets(ctx: Context? = context): String? = try { 428 | ctx?.assets?.open(this)?.bufferedReader()?.use { it.readText() } 429 | } catch (e: Exception) { 430 | e.printStackTrace() 431 | null 432 | } 433 | 434 | fun String.fontFromAssets(ctx: Context? = context) = Typeface.createFromAsset(requireNotNull(ctx).assets, this) 435 | 436 | // endregion 437 | 438 | // region Misc 439 | 440 | val isRightToLeft: Boolean 441 | get() = R.bool.rtl.resBoolean 442 | 443 | val Uri.isTelephoneLink: Boolean 444 | get() = toString().startsWith("tel:") 445 | 446 | val Uri.isMailToLink: Boolean 447 | get() = toString().startsWith("mailto:") 448 | 449 | // endregion 450 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/res/values-ldltr/ltr-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 1 5 | -1 6 | false 7 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/res/values-ldrtl/rtl-config.xml: -------------------------------------------------------------------------------- 1 | 2 | true 3 | -1 4 | 1 5 | 180 6 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 27 | -------------------------------------------------------------------------------- /AndroidResourceExtensions/src/main/res/values/ltr-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 0 3 | 1 4 | -1 5 | false 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Donation](https://img.shields.io/badge/buy%20me%20a%20coffee-brightgreen.svg)](https://www.paypal.me/janrabe/5) [![About Jan Rabe](https://img.shields.io/badge/about-me-green.svg)](https://kibotu.net) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-AndroidResourceExtensions-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/7880) 2 | 3 | # Android Resource Extensions 4 | [![Maven Central Version](https://img.shields.io/maven-central/v/net.kibotu/AndroidResourceExtensions)](https://central.sonatype.com/artifact/net.kibotu/AndroidResourceExtensions) [![](https://jitpack.io/v/kibotu/AndroidResourceExtensions.svg)](https://jitpack.io/#kibotu/AndroidResourceExtensions) [![Android CI](https://github.com/kibotu/AndroidResourceExtensions/actions/workflows/android.yml/badge.svg)](https://github.com/kibotu/AndroidResourceExtensions/actions/workflows/android.yml) [![API](https://img.shields.io/badge/Min%20API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21) [![API](https://img.shields.io/badge/Target%20API-35%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=35) [![API](https://img.shields.io/badge/Java-17-brightgreen.svg?style=flat)](https://www.oracle.com/java/technologies/javase/17all-relnotes.html) [![Gradle Version](https://img.shields.io/badge/gradle-8.11.1-green.svg)](https://docs.gradle.org/current/release-notes) [![Kotlin](https://img.shields.io/badge/kotlin-2.1.0-green.svg)](https://kotlinlang.org/) [![](https://jitpack.io/v/kibotu/AndroidResourceExtensions/month.svg)](https://jitpack.io/#kibotu/AndroidResourceExtensions) [![Hits-of-Code](https://hitsofcode.com/github/kibotu/AndroidResourceExtensions)](https://hitsofcode.com/view/github/kibotu/AndroidResourceExtensions) 5 | 6 | Convenience extension methods for android's auto-generated /res folder *R.* class. 7 | 8 | Basically everything in your res/ and /assets folder can be accessed via an extension function. *Note: everything gets loaded with current activity context, if that is not available it uses application context.* 9 | 10 | # How to install 11 | 12 | ## MavenCentral 13 | 14 | ```groovy 15 | allprojects { 16 | repositories { 17 | mavenCentral() 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation 'net.kibotu:AndroidResourceExtensions:{latest-version}' 23 | } 24 | 25 | ``` 26 | 27 | ## Jitpack 28 | 29 | ```groovy 30 | allprojects { 31 | repositories { 32 | ... 33 | maven { url 'https://jitpack.io' } 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation 'com.github.kibotu:AndroidResourceExtensions:{latest-version}' 39 | } 40 | ``` 41 | 42 | ### Features: 43 | 44 | ##### Values 45 | 46 | - resBoolean 47 | - resInt 48 | - resLong 49 | - resString 50 | - resString(args) 51 | - localizedString(locale) 52 | - localizedResources(locale) 53 | - quantityString 54 | - quantityString(args) 55 | - resColorLong 56 | - resColor 57 | - resDimension 58 | - html 59 | - html 60 | - csv 61 | - resXml 62 | - resFraction 63 | 64 | ##### Arrays 65 | 66 | - resIntArray 67 | - resStringArray 68 | - resTextArray 69 | - resColorArray 70 | - resColorIntArray 71 | - resDrawableArray 72 | - resDrawableIdArray 73 | 74 | ##### Ids 75 | 76 | - resId 77 | - resName 78 | - resTypeName 79 | - resPackageName 80 | - resStringId 81 | - resDrawableId 82 | - resDrawableId((Exception)->Unit) 83 | - resColorDrawable 84 | - resGradientDrawable 85 | 86 | ##### Objects 87 | 88 | - resDrawable 89 | - colorDrawable 90 | - resAnim 91 | - resAnimator 92 | - resFont 93 | - resRaw 94 | - resInterpolator 95 | - resLayoutAnimation 96 | - resTransition 97 | 98 | ##### Layout 99 | 100 | - resLayout 101 | - inflate 102 | 103 | ##### Screen 104 | 105 | - dp 106 | - px 107 | - sp 108 | - pt 109 | - inches 110 | - mm 111 | - screenWidthDp 112 | - screenHeightDp 113 | - screenWidthPixels 114 | - screenHeightPixels 115 | 116 | ##### Assets 117 | 118 | - bytesFromAssets // thread-safe 119 | - stringFromAssets 120 | 121 | ##### Misc 122 | 123 | - isRightToLeft 124 | - isTelephoneLink 125 | - isMailToLink 126 | 127 | 128 | ### ManifestPermissions 129 | 130 | - isGranted // checks if granted, doesn't trigger request 131 | 132 | 133 | ### How to use 134 | 135 | 136 | ```kotlin 137 | val my_integer: Int = R.integer.my_integer.resInt 138 | val my_long: Long = R.integer.my_long.resLong 139 | val my_string: String = R.string.my_string.resString 140 | val my_string_args: String = R.string.my_string_args.resString("ipsum") 141 | val my_string_args_float: String = R.string.my_string_args_float.resString(2f) 142 | val my_localized_string: String = R.string.my_localized_string.localizedString(Locale.GERMAN) 143 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 144 | val my_localized_resources: Resources = localizedResources(this, Locale.GERMAN) 145 | } 146 | val my_quantityString: String = R.plurals.my_quantityString.quantityString(2) 147 | val my_quantityString_args: String = R.plurals.my_quantityString_args.quantityString(2, "total") 148 | 149 | val my_boolean: Boolean = R.bool.my_boolean.resBoolean 150 | val my_color_long: Long = R.color.my_color_long.resColorLong 151 | val my_color: Int = R.color.my_color.resColor 152 | val my_dimension: Float = R.dimen.my_dimension.resDimension 153 | val my_string_html: Spanned = """Google""".html 154 | val my_html: Spanned = R.string.my_html.html 155 | val my_csv: List = R.string.my_csv.csv 156 | val my_xml: XmlResourceParser = R.xml.lorem_ipsum.resXml 157 | // 0.10f 158 | val my_fraction: Float = R.fraction.my_fraction.resFraction(2, 2) 159 | val my_int_array: IntArray = R.array.my_int_array.resIntArray 160 | val my_string_array: Array = R.array.my_string_array.resStringArray 161 | val my_character_array: Array = R.array.my_string_array.resTextArray 162 | /*ColorRes*/ 163 | val my_icons_array: List = R.array.my_colors.resColorArray 164 | /*ColorInt*/ 165 | val my_icons_array_color_int: List = R.array.my_colors.resColorIntArray 166 | /*@DrawableRes*/ 167 | val my_colors_array: List = R.array.my_icons.resDrawableIdArray 168 | /*@Drawable*/ 169 | val my_colors_array_drawable: List = R.array.my_icons.resDrawableArray 170 | @IdRes val my_id: Int = "my_id".resId 171 | val my_res_name: String = R.integer.my_res_name.resName 172 | val my_res_type_name: String = R.integer.my_res_type_name.resTypeName 173 | val my_res_package_name: String = R.integer.my_res_package_name.resPackageName 174 | @StringRes val my_res_string_id: Int = "my_res_string_id".resStringId { it.printStackTrace() } 175 | @DrawableRes val my_res_drawable_id: Int = "ic_share".resDrawableId 176 | @DrawableRes val my_res_drawable_id_with_error_handling: Int = "ic_share".resDrawableId { it.printStackTrace() } 177 | val my_drawable: Drawable = R.drawable.ic_share.resDrawable 178 | val my_anim: Animation = R.anim.grow.resAnim 179 | val my_animator: Animator = R.animator.flip_animation.resAnimator 180 | val my_font: Typeface = R.font.lato.resFont 181 | val my_raw: InputStream = R.raw.my_raw.resRaw 182 | val my_interpolator: Interpolator = android.R.interpolator.anticipate_overshoot.resInterpolator 183 | val my_res_layout_animation_controller: LayoutAnimationController = R.anim.layout_animation.resLayoutAnimation 184 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 185 | val my_transition: Transition = android.R.transition.explode.resTransition 186 | } 187 | val my_layout: XmlResourceParser = R.layout.activity_main.resLayout 188 | val my_inflated_layout: View = R.layout.activity_main.inflate(root) 189 | val my_dp: Float = 16f.dp 190 | val my_dp_int: Int = 16.dp 191 | val my_px: Float = 200f.px 192 | val my_px_int: Int = 200.px 193 | val my_sp: Float = 14f.sp 194 | val my_pt: Float = 14f.pt 195 | val my_inches: Float = 14f.inches 196 | val my_mm: Float = 14f.mm 197 | val my_screen_width_dp: Int = screenWidthDp 198 | val my_screen_height_dp: Int = screenHeightDp 199 | val my_screen_width_pixels: Int = screenWidthPixels 200 | val my_screen_height_pixels: Int = screenHeightPixels 201 | val my_bytes_from_assets: ByteArray? = "my_text.json".bytesFromAssets() 202 | val my_string_from_assets: String? = "my_text.json".stringFromAssets() 203 | val my_device_is_rtl: Boolean = isRightToLeft 204 | val my_string_is_a_telephone_link: Boolean = Uri.parse("""Google""").isTelephoneLink 205 | val my_string_is_a_mailto_link: Boolean = Uri.parse("""Google""").isMailToLink 206 | 207 | val locationPermission : Boolean = Manifest.permission.ACCESS_FINE_LOCATION.isGranted 208 | 209 | ``` 210 | 211 | ### Notes 212 | 213 | Follow me on Twitter: [@wolkenschauer](https://twitter.com/wolkenschauer) 214 | 215 | Let me know what you think: [jan.rabe@kibotu.net](mailto:jan.rabe@kibotu.net) 216 | 217 | Contributions welcome! 218 | 219 | ### License 220 | 221 |
222 | Copyright 2022 Jan Rabe
223 | 
224 | Licensed under the Apache License, Version 2.0 (the "License");
225 | you may not use this file except in compliance with the License.
226 | You may obtain a copy of the License at
227 | 
228 | http://www.apache.org/licenses/LICENSE-2.0
229 | 
230 | Unless required by applicable law or agreed to in writing, software
231 | distributed under the License is distributed on an "AS IS" BASIS,
232 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
233 | See the License for the specific language governing permissions and
234 | limitations under the License.
235 | 
236 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | namespace "net.kibotu.resourceextensions.demo" 6 | compileSdk compileSdkVer 7 | buildToolsVersion = buildToolsVer 8 | 9 | defaultConfig { 10 | applicationId "net.kibotu.resourceextensions.demo" 11 | minSdk minSdkVer 12 | targetSdk targetSdkVer 13 | versionName version 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | debug { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', '../proguard-debug.pro' 21 | } 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', '../proguard-release.pro' 25 | } 26 | } 27 | 28 | // region java compile options 29 | 30 | java { 31 | toolchain { 32 | languageVersion.set(JavaLanguageVersion.of(17)) 33 | } 34 | } 35 | 36 | compileOptions { 37 | sourceCompatibility JavaVersion.VERSION_17 38 | targetCompatibility JavaVersion.VERSION_17 39 | } 40 | 41 | // endregion 42 | 43 | // region kotlin compile options 44 | 45 | kotlinOptions { 46 | jvmTarget = "17" 47 | allWarningsAsErrors = false 48 | kotlinOptions.verbose = true 49 | freeCompilerArgs += [ 50 | "-Xjvm-default=all-compatibility" 51 | ] 52 | } 53 | 54 | // endregion 55 | } 56 | 57 | dependencies { 58 | coreLibraryDesugaring desugaring.jdk 59 | implementation libs.supportAppCompat 60 | implementation libs.coreKtx 61 | implementation libs.constraintLayout 62 | implementation libs.material 63 | 64 | implementation project(':AndroidResourceExtensions') 65 | implementation libs.applicationProvider 66 | } 67 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/assets/my_text.json: -------------------------------------------------------------------------------- 1 | { 2 | "lorem" : "ipsum" 3 | } -------------------------------------------------------------------------------- /app/src/main/java/net/kibotu/resourceextensions/demo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package net.kibotu.resourceextensions.demo 2 | 3 | import android.animation.Animator 4 | import android.content.res.Resources 5 | import android.content.res.XmlResourceParser 6 | import android.graphics.Typeface 7 | import android.graphics.drawable.Drawable 8 | import android.net.Uri 9 | import android.os.Build 10 | import android.os.Bundle 11 | import android.text.Spanned 12 | import android.transition.Transition 13 | import android.view.View 14 | import android.view.animation.Animation 15 | import android.view.animation.Interpolator 16 | import android.view.animation.LayoutAnimationController 17 | import androidx.annotation.DrawableRes 18 | import androidx.annotation.IdRes 19 | import androidx.annotation.StringRes 20 | import androidx.appcompat.app.AppCompatActivity 21 | import net.kibotu.resourceextension.* 22 | import java.io.InputStream 23 | import java.util.* 24 | 25 | class MainActivity : AppCompatActivity() { 26 | 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | setContentView(R.layout.activity_main) 30 | 31 | val my_integer: Int = R.integer.my_integer.resInt 32 | val my_long: Long = R.integer.my_long.resLong 33 | val my_string: String = R.string.my_string.resString 34 | val my_string_args: String = R.string.my_string_args.resString("ipsum") 35 | val my_string_args_float: String = R.string.my_string_args_float.resString(2f) 36 | val my_localized_string: String = R.string.my_localized_string.localizedString(Locale.GERMAN) 37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 38 | val my_localized_resources: Resources = localizedResources(this, Locale.GERMAN) 39 | } 40 | val my_quantityString: String = R.plurals.my_quantityString.quantityString(2) 41 | val my_quantityString_args: String = R.plurals.my_quantityString_args.quantityString(2, "total") 42 | 43 | val my_boolean: Boolean = R.bool.my_boolean.resBoolean 44 | val my_color_long: Long = R.color.my_color_long.resColorLong 45 | val my_color: Int = R.color.my_color.resColor 46 | val my_dimension: Float = R.dimen.my_dimension.resDimension 47 | val my_string_html: Spanned = """Google""".html 48 | val my_html: Spanned = R.string.my_html.html 49 | val my_csv: List = R.string.my_csv.csv 50 | val my_xml: XmlResourceParser = R.xml.lorem_ipsum.resXml 51 | // 0.10f 52 | val my_fraction: Float = R.fraction.my_fraction.resFraction(2, 2) 53 | val my_int_array: IntArray = R.array.my_int_array.resIntArray 54 | val my_string_array: Array = R.array.my_string_array.resStringArray 55 | val my_character_array: Array = R.array.my_string_array.resTextArray 56 | /*ColorRes*/ 57 | val my_icons_array: List = R.array.my_colors.resColorArray 58 | /*ColorInt*/ 59 | val my_icons_array_color_int: List = R.array.my_colors.resColorIntArray 60 | /*@DrawableRes*/ 61 | val my_colors_array: List = R.array.my_icons.resDrawableIdArray 62 | /*@Drawable*/ 63 | val my_colors_array_drawable: List = R.array.my_icons.resDrawableArray 64 | @IdRes val my_id: Int = "my_id".resId 65 | val my_res_name: String = R.integer.my_res_name.resName 66 | val my_res_type_name: String = R.integer.my_res_type_name.resTypeName 67 | val my_res_package_name: String = R.integer.my_res_package_name.resPackageName 68 | @StringRes val my_res_string_id: Int = "my_res_string_id".resStringId { it.printStackTrace() } 69 | @DrawableRes val my_res_drawable_id: Int = "ic_share".resDrawableId 70 | @DrawableRes val my_res_drawable_id_with_error_handling: Int = "ic_share".resDrawableId { it.printStackTrace() } 71 | val my_drawable: Drawable = R.drawable.ic_share.resDrawable 72 | val my_anim: Animation = R.anim.grow.resAnim 73 | val my_animator: Animator = R.animator.flip_animation.resAnimator 74 | val my_font: Typeface? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 75 | R.font.lato.resFont 76 | } else { 77 | TODO("VERSION.SDK_INT < O") 78 | } 79 | val my_raw: InputStream = R.raw.my_raw.resRaw 80 | val my_interpolator: Interpolator = android.R.interpolator.anticipate_overshoot.resInterpolator 81 | val my_res_layout_animation_controller: LayoutAnimationController = R.anim.layout_animation.resLayoutAnimation 82 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 83 | val my_transition: Transition = android.R.transition.explode.resTransition 84 | } 85 | val my_layout: XmlResourceParser = R.layout.activity_main.resLayout 86 | val my_inflated_layout: View = R.layout.activity_main.inflate(findViewById(R.id.root)) 87 | val my_dp: Float = 16f.dp 88 | val my_dp_int: Int = 16.dp 89 | val my_px: Float = 200f.px 90 | val my_px_int: Int = 200.px 91 | val my_sp: Float = 14f.sp 92 | val my_screen_width_dp: Int = screenWidthDp 93 | val my_screen_height_dp: Int = screenHeightDp 94 | val my_screen_width_pixels: Int = screenWidthPixels 95 | val my_screen_height_pixels: Int = screenHeightPixels 96 | val my_bytes_from_assets: ByteArray? = "my_text.json".bytesFromAssets() 97 | val my_string_from_assets: String? = "my_text.json".stringFromAssets() 98 | val my_device_is_rtl: Boolean = isRightToLeft 99 | val my_string_is_a_telephone_link: Boolean = Uri.parse("""Google""").isTelephoneLink 100 | val my_string_is_a_mailto_link: Boolean = Uri.parse("""Google""").isMailToLink 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/res/anim/grow.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/anim/layout_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/animator/flip_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 19 | 20 | 26 | 27 | 31 | 32 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/font/lato.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/font/lato.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/raw/my_raw.json: -------------------------------------------------------------------------------- 1 | { 2 | "lorem" : "ipsum" 3 | } -------------------------------------------------------------------------------- /app/src/main/res/values-de/localized.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | german 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidResourceExtensions 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12345 5 | 12345 6 | lorem ipsum 7 | lorem %s 8 | lorem %.2f 9 | default 10 | 11 | 12 | Minutes 13 | Minute 14 | Minutes 15 | Minutes 16 | Minutes 17 | Minutes 18 | 19 | 20 | 21 | %s Minutes 22 | %s Minute 23 | %s Minutes 24 | %s Minutes 25 | %s Minutes 26 | %s Minutes 27 | 28 | 29 | true 30 | #aaefefef 31 | #aae33fef 32 | 16dp 33 | lorem, ipsum, dolor 34 | Google]]> 35 | 5% 36 | 37 | 38 | 1 39 | 2 40 | 3 41 | 4 42 | 5 43 | 44 | 45 | 46 | aa 47 | bb 48 | cc 49 | ee 50 | ff 51 | 52 | 53 | 54 | a 55 | b 56 | c 57 | e 58 | f 59 | 60 | 61 | 62 | @android:drawable/ic_delete 63 | @android:drawable/ic_menu_share 64 | @android:drawable/ic_dialog_alert 65 | @android:drawable/ic_btn_speak_now 66 | @android:drawable/ic_notification_overlay 67 | 68 | 69 | 70 | @color/colorPrimary 71 | @color/colorAccent 72 | @color/colorPrimaryDark 73 | @color/my_color 74 | @color/my_color_long 75 | 76 | 77 | 12345 78 | 12345 79 | 12345 80 | 12345 81 | 12345 82 | 83 | -------------------------------------------------------------------------------- /app/src/main/res/xml/lorem_ipsum.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Brian Cantoni 5 | Generate random Lorem Ipsum text from lipsum.com. Parameters: amount=number of things to fetch; what: paras, words, bytes, or lists; start: set to "no" to not start all strings with Lorem Ipsum. 6 | http://www.lipsum.com/ 7 | select * from {table} where amount='5' and what='paras'; 8 | 9 | 10 | 28 | 29 |
-------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | 3 | apply from: "./dependencies.gradle" 4 | 5 | repositories { 6 | google() 7 | mavenCentral() 8 | gradlePluginPortal() 9 | maven { url 'https://jitpack.io' } 10 | } 11 | 12 | dependencies { 13 | classpath plugin.gradleBuildTools 14 | classpath plugin.kotlinGradle 15 | classpath plugin.mavenCentralPublish 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | mavenCentral() 23 | gradlePluginPortal() 24 | maven { url 'https://jitpack.io' } 25 | } 26 | } -------------------------------------------------------------------------------- /dependencies.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | // refresh gradle dependencies: ./gradlew build --refresh-dependencies 3 | minSdkVer = 21 4 | 5 | compileSdkVer = 35 6 | buildToolsVer = "35.0.0" 7 | targetSdkVer = 35 8 | 9 | // @see https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8 10 | kotlinVersion = "2.1.0" 11 | 12 | isJitpack = System.getenv("JITPACK") == "true" 13 | 14 | println "Compile Version: $compileSdkVer" 15 | println "Min SDK Version: $minSdkVer" 16 | println "Target SDK Version: $targetSdkVer" 17 | println "Kotlin: $kotlinVersion" 18 | println "Version Name: $version" 19 | } 20 | 21 | ext.plugin = [ 22 | mavenCentralPublish: "com.vanniktech:gradle-maven-publish-plugin:0.30.0", 23 | gradleBuildTools : "com.android.tools.build:gradle:8.7.3", 24 | kotlinGradle : "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion", 25 | ] 26 | 27 | ext.libs = [ 28 | supportAppCompat : "androidx.appcompat:appcompat:1.7.0", 29 | coreKtx : "androidx.core:core-ktx:1.7.0", 30 | applicationProvider: "net.kibotu:ApplicationProvider:2.1.2", 31 | constraintLayout : "androidx.constraintlayout:constraintlayout:2.1.4", 32 | material : "com.google.android.material:material:1.12.0", 33 | ] 34 | 35 | ext.desugaring = [ 36 | jdk: "com.android.tools:desugar_jdk_libs:2.1.3" 37 | ] 38 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # https://developer.android.com/build/optimize-your-build#experiment-with-the-jvm-parallel-garbage-collector 2 | org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dfile.encoding=UTF-8 3 | org.gradle.caching=true 4 | org.gradle.configureondemand=true 5 | org.gradle.daemon=true 6 | org.gradle.info=true 7 | org.gradle.offline=true 8 | org.gradle.profile=true 9 | org.gradle.parallel=true 10 | org.gradle.parallel.threads=12 11 | org.gradle.workers.max=12 12 | # https://docs.gradle.org/current/userguide/file_system_watching.html 13 | org.gradle.vfs.watch=true 14 | # https://docs.gradle.org/current/userguide/configuration_cache.html 15 | org.gradle.configuration-cache=true 16 | org.gradle.configuration-cache-problems=warn 17 | ## ================================================================================================= 18 | ## java 19 | ## ================================================================================================= 20 | compileJava.options.incremental=true 21 | compileJava.options.fork=true 22 | ## ================================================================================================= 23 | ## android 24 | ## ================================================================================================= 25 | # https://developer.android.com/topic/libraries/support-library/androidx-overview 26 | android.useAndroidX=true 27 | ## Determines whether to generate a BuildConfig class. 28 | android.defaults.buildfeatures.buildConfig=false 29 | ## Determines whether to support Data Binding. 30 | android.defaults.buildFeatures.dataBinding=false 31 | ## Determines whether to support View Binding. 32 | android.defaults.buildFeatures.viewBinding=false 33 | ## Determines whether to generate binder classes for your AIDL files. 34 | android.defaults.buildfeatures.resvalues=true 35 | ## Determines whether to support shader AOT compilation. 36 | android.defaults.buildfeatures.shaders=false 37 | # https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#r8-full-mode 38 | android.enableR8.fullMode=false 39 | ## since agp 8.0.0 changed default values must be reverted for desired Behaviour 40 | # https://developer.android.com/build/releases/gradle-plugin#default-changes 41 | android.nonFinalResIds=true 42 | android.nonTransitiveRClass=false 43 | ## ================================================================================================= 44 | ## kotlin 45 | ## ================================================================================================= 46 | kotlin.code.style=official 47 | kotlin.incremental=true 48 | kotlin.caching.enabled=true 49 | kotlin.incremental.js=true 50 | kotlinOptions.allWarningsAsErrors=true 51 | kotlinOptions.verbose=true 52 | kotlinOptions.freeCompilerArgs=["-Xjvm-default=all-compatibility"] 53 | 54 | # publishing 55 | GROUP=net.kibotu 56 | POM_ARTIFACT_ID=AndroidResourceExtensions 57 | 58 | POM_NAME=AndroidResourceExtensions 59 | POM_DESCRIPTION=Convenience extension methods for android's auto-generated /res folder *R.* class. Basically everything in your res/ and /assets folder can be accessed via an extension function. *Note: everything gets loaded with current activity context, if that is not available it uses application context.* 60 | POM_INCEPTION_YEAR=2024 61 | POM_URL=https://github.com/kibotu/AndroidResourceExtensions 62 | 63 | POM_LICENSE_NAME=The Apache Software License, Version 2.0 64 | POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt 65 | POM_LICENSE_DIST=repo 66 | 67 | POM_SCM_URL=https://github.com/kibotu/AndroidResourceExtensions 68 | POM_SCM_CONNECTION=scm:git:git://github.com/kibotu/AndroidResourceExtensions.git 69 | POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/kibotu/AndroidResourceExtensions.git 70 | 71 | POM_DEVELOPER_ID=kibotu 72 | POM_DEVELOPER_NAME=Jan Rabe 73 | POM_DEVELOPER_URL=https://github.com/kibotu/ 74 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kibotu/AndroidResourceExtensions/640539e70ac5c92d98a5951cec4ce0a86f3793b1/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-8.11.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s 90 | ' "$PWD" ) || exit 91 | 92 | # Use the maximum available, or set MAX_FD != -1 to use that value. 93 | MAX_FD=maximum 94 | 95 | warn () { 96 | echo "$*" 97 | } >&2 98 | 99 | die () { 100 | echo 101 | echo "$*" 102 | echo 103 | exit 1 104 | } >&2 105 | 106 | # OS specific support (must be 'true' or 'false'). 107 | cygwin=false 108 | msys=false 109 | darwin=false 110 | nonstop=false 111 | case "$( uname )" in #( 112 | CYGWIN* ) cygwin=true ;; #( 113 | Darwin* ) darwin=true ;; #( 114 | MSYS* | MINGW* ) msys=true ;; #( 115 | NONSTOP* ) nonstop=true ;; 116 | esac 117 | 118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 119 | 120 | 121 | # Determine the Java command to use to start the JVM. 122 | if [ -n "$JAVA_HOME" ] ; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD=$JAVA_HOME/jre/sh/java 126 | else 127 | JAVACMD=$JAVA_HOME/bin/java 128 | fi 129 | if [ ! -x "$JAVACMD" ] ; then 130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 131 | 132 | Please set the JAVA_HOME variable in your environment to match the 133 | location of your Java installation." 134 | fi 135 | else 136 | JAVACMD=java 137 | if ! command -v java >/dev/null 2>&1 138 | then 139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 140 | 141 | Please set the JAVA_HOME variable in your environment to match the 142 | location of your Java installation." 143 | fi 144 | fi 145 | 146 | # Increase the maximum file descriptors if we can. 147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 148 | case $MAX_FD in #( 149 | max*) 150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 151 | # shellcheck disable=SC2039,SC3045 152 | MAX_FD=$( ulimit -H -n ) || 153 | warn "Could not query maximum file descriptor limit" 154 | esac 155 | case $MAX_FD in #( 156 | '' | soft) :;; #( 157 | *) 158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 159 | # shellcheck disable=SC2039,SC3045 160 | ulimit -n "$MAX_FD" || 161 | warn "Could not set maximum file descriptor limit to $MAX_FD" 162 | esac 163 | fi 164 | 165 | # Collect all arguments for the java command, stacking in reverse order: 166 | # * args from the command line 167 | # * the main class name 168 | # * -classpath 169 | # * -D...appname settings 170 | # * --module-path (only if needed) 171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 172 | 173 | # For Cygwin or MSYS, switch paths to Windows format before running java 174 | if "$cygwin" || "$msys" ; then 175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 177 | 178 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 179 | 180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 181 | for arg do 182 | if 183 | case $arg in #( 184 | -*) false ;; # don't mess with options #( 185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 186 | [ -e "$t" ] ;; #( 187 | *) false ;; 188 | esac 189 | then 190 | arg=$( cygpath --path --ignore --mixed "$arg" ) 191 | fi 192 | # Roll the args list around exactly as many times as the number of 193 | # args, so each arg winds up back in the position where it started, but 194 | # possibly modified. 195 | # 196 | # NB: a `for` loop captures its iteration list before it begins, so 197 | # changing the positional parameters here affects neither the number of 198 | # iterations, nor the values presented in `arg`. 199 | shift # remove old arg 200 | set -- "$@" "$arg" # push replacement arg 201 | done 202 | fi 203 | 204 | 205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 207 | 208 | # Collect all arguments for the java command: 209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 210 | # and any embedded shellness will be escaped. 211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 212 | # treated as '${Hostname}' itself on the command line. 213 | 214 | set -- \ 215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 216 | -classpath "$CLASSPATH" \ 217 | org.gradle.wrapper.GradleWrapperMain \ 218 | "$@" 219 | 220 | # Stop when "xargs" is not available. 221 | if ! command -v xargs >/dev/null 2>&1 222 | then 223 | die "xargs is not available" 224 | fi 225 | 226 | # Use "xargs" to parse quoted args. 227 | # 228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 229 | # 230 | # In Bash we could simply go: 231 | # 232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 233 | # set -- "${ARGS[@]}" "$@" 234 | # 235 | # but POSIX shell has neither arrays nor command substitution, so instead we 236 | # post-process each arg (as a line of input to sed) to backslash-escape any 237 | # character that might be a shell metacharacter, then use eval to reverse 238 | # that process (while maintaining the separation between arguments), and wrap 239 | # the whole thing up as a single "set" statement. 240 | # 241 | # This will of course break if any of these variables contains a newline or 242 | # an unmatched quote. 243 | # 244 | 245 | eval "set -- $( 246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 247 | xargs -n1 | 248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 249 | tr '\n' ' ' 250 | )" '"$@"' 251 | 252 | exec "$JAVACMD" "$@" 253 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk17 3 | -------------------------------------------------------------------------------- /proguard-debug.pro: -------------------------------------------------------------------------------- 1 | -verbose 2 | -dontobfuscate 3 | #-dontshrink 4 | #-dontoptimize 5 | -------------------------------------------------------------------------------- /proguard-release.pro: -------------------------------------------------------------------------------- 1 | -verbose 2 | #-dontobfuscate 3 | #-dontshrink 4 | #-dontoptimize 5 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':AndroidResourceExtensions' 2 | --------------------------------------------------------------------------------