├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── build.gradle ├── keys.properties.example ├── libs │ ├── android-5.1.jar │ ├── dex-ir-1.12.jar │ ├── dex-reader-1.15.jar │ ├── dex-tools-0.0.9.15.jar │ ├── dex-translator-0.0.9.15.jar │ ├── dx-1.16.jar │ ├── jadx-core-0.9.0.jar │ └── smali-2.2.1.jar ├── mock-google-services.json ├── multidex-config.pro ├── proguard-rules.pro ├── src │ ├── androidTest │ │ ├── assets │ │ │ └── test-application.jar │ │ └── kotlin │ │ │ └── com │ │ │ └── njlabs │ │ │ └── showjava │ │ │ └── test │ │ │ ├── DecompilerTestBase.kt │ │ │ └── decompilers │ │ │ ├── apk │ │ │ ├── ApkViaCfr.kt │ │ │ ├── ApkViaFernFlower.kt │ │ │ └── ApkViaJadx.kt │ │ │ ├── dex │ │ │ ├── DexViaCfr.kt │ │ │ ├── DexViaFernFlower.kt │ │ │ └── DexViaJadx.kt │ │ │ └── jar │ │ │ ├── JarViaCfr.kt │ │ │ ├── JarViaFernFlower.kt │ │ │ └── JarViaJadx.kt │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── codeview │ │ │ │ ├── highlightjs │ │ │ │ │ ├── highlight.js │ │ │ │ │ └── styles │ │ │ │ │ │ ├── androidstudio.css │ │ │ │ │ │ └── github-gist.css │ │ │ │ ├── script.js │ │ │ │ └── styles.css │ │ │ ├── extra │ │ │ │ └── LICENSE │ │ │ ├── ignored.basic.list │ │ │ └── ignored.list │ │ ├── config │ │ │ └── logback.xml │ │ ├── ic_launcher_round-web.png │ │ ├── ic_logo_plain-web.png │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── njlabs │ │ │ │ └── showjava │ │ │ │ ├── Constants.kt │ │ │ │ ├── MainApplication.kt │ │ │ │ ├── activities │ │ │ │ ├── BaseActivity.kt │ │ │ │ ├── about │ │ │ │ │ └── AboutActivity.kt │ │ │ │ ├── apps │ │ │ │ │ ├── AppsActivity.kt │ │ │ │ │ ├── AppsHandler.kt │ │ │ │ │ └── adapters │ │ │ │ │ │ └── AppsListAdapter.kt │ │ │ │ ├── decompiler │ │ │ │ │ ├── DecompilerActivity.kt │ │ │ │ │ ├── DecompilerProcessActivity.kt │ │ │ │ │ └── LowMemoryActivity.kt │ │ │ │ ├── explorer │ │ │ │ │ ├── navigator │ │ │ │ │ │ ├── NavigatorActivity.kt │ │ │ │ │ │ ├── NavigatorHandler.kt │ │ │ │ │ │ └── adapters │ │ │ │ │ │ │ └── FilesListAdapter.kt │ │ │ │ │ └── viewer │ │ │ │ │ │ ├── CodeViewerActivity.kt │ │ │ │ │ │ └── ImageViewerActivity.kt │ │ │ │ ├── landing │ │ │ │ │ ├── LandingActivity.kt │ │ │ │ │ ├── LandingHandler.kt │ │ │ │ │ └── adapters │ │ │ │ │ │ └── HistoryListAdapter.kt │ │ │ │ ├── purchase │ │ │ │ │ └── PurchaseActivity.kt │ │ │ │ └── settings │ │ │ │ │ ├── SettingsActivity.kt │ │ │ │ │ └── SettingsHandler.kt │ │ │ │ ├── data │ │ │ │ ├── FileItem.kt │ │ │ │ ├── PackageInfo.kt │ │ │ │ └── SourceInfo.kt │ │ │ │ ├── decompilers │ │ │ │ ├── BaseDecompiler.kt │ │ │ │ ├── JarExtractionWorker.kt │ │ │ │ ├── JavaExtractionWorker.kt │ │ │ │ └── ResourcesExtractionWorker.kt │ │ │ │ ├── receivers │ │ │ │ └── DecompilerActionReceiver.kt │ │ │ │ ├── utils │ │ │ │ ├── Ads.kt │ │ │ │ ├── Identicon.kt │ │ │ │ ├── ProcessNotifier.kt │ │ │ │ ├── RequestQueue.kt │ │ │ │ ├── SingletonHolder.kt │ │ │ │ ├── UserPreferences.kt │ │ │ │ ├── ZipUtils.kt │ │ │ │ ├── ktx │ │ │ │ │ ├── Extensions.kt │ │ │ │ │ ├── PackageSourceTools.kt │ │ │ │ │ └── Tools.kt │ │ │ │ ├── logging │ │ │ │ │ └── ProductionTree.kt │ │ │ │ ├── rx │ │ │ │ │ └── ProcessStatus.kt │ │ │ │ ├── secure │ │ │ │ │ ├── PurchaseUtils.kt │ │ │ │ │ └── SecureUtils.kt │ │ │ │ ├── streams │ │ │ │ │ ├── Logger.kt │ │ │ │ │ └── ProgressStream.kt │ │ │ │ └── views │ │ │ │ │ └── CodeView.kt │ │ │ │ └── workers │ │ │ │ └── DecompilerWorker.kt │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ ├── ic_list_generic.png │ │ │ ├── ic_stat_code.png │ │ │ ├── ic_stat_error.png │ │ │ ├── ic_stat_stop.png │ │ │ └── sad_ram.png │ │ │ ├── drawable-mdpi │ │ │ ├── ic_list_generic.png │ │ │ ├── ic_stat_code.png │ │ │ ├── ic_stat_error.png │ │ │ ├── ic_stat_stop.png │ │ │ └── sad_ram.png │ │ │ ├── drawable-xhdpi │ │ │ ├── ic_list_generic.png │ │ │ ├── ic_stat_code.png │ │ │ ├── ic_stat_error.png │ │ │ ├── ic_stat_stop.png │ │ │ └── sad_ram.png │ │ │ ├── drawable-xxhdpi │ │ │ ├── ic_list_generic.png │ │ │ ├── ic_stat_code.png │ │ │ ├── ic_stat_error.png │ │ │ ├── ic_stat_stop.png │ │ │ └── sad_ram.png │ │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_stat_code.png │ │ │ ├── ic_stat_error.png │ │ │ ├── ic_stat_stop.png │ │ │ └── sad_ram.png │ │ │ ├── drawable │ │ │ ├── fab_label.xml │ │ │ ├── ic_apps_white.xml │ │ │ ├── ic_bug_report_black.xml │ │ │ ├── ic_code_black.xml │ │ │ ├── ic_code_white.xml │ │ │ ├── ic_delete_white.xml │ │ │ ├── ic_error_outline_black.xml │ │ │ ├── ic_gear_grey.xml │ │ │ ├── ic_info_black.xml │ │ │ ├── ic_invert_colors_white.xml │ │ │ ├── ic_sd_card_white.xml │ │ │ ├── ic_search_white.xml │ │ │ ├── ic_settings_black.xml │ │ │ ├── ic_share_white.xml │ │ │ ├── ic_stop_black.xml │ │ │ ├── ic_whatshot_black.xml │ │ │ ├── navbar_header.jpg │ │ │ ├── previous.png │ │ │ ├── showjava_logo.png │ │ │ ├── type_css.png │ │ │ ├── type_file.png │ │ │ ├── type_folder.png │ │ │ ├── type_html.png │ │ │ ├── type_jar.png │ │ │ ├── type_java.png │ │ │ ├── type_javascript.png │ │ │ ├── type_jpg.png │ │ │ ├── type_json.png │ │ │ ├── type_png.png │ │ │ ├── type_txt.png │ │ │ ├── type_xml.png │ │ │ └── type_zip.png │ │ │ ├── font │ │ │ ├── lato.xml │ │ │ ├── lato_bold.ttf │ │ │ ├── lato_light.ttf │ │ │ └── lato_regular.ttf │ │ │ ├── layout │ │ │ ├── action_layout_checkbox.xml │ │ │ ├── activity_about.xml │ │ │ ├── activity_apps.xml │ │ │ ├── activity_code_viewer.xml │ │ │ ├── activity_decompiler.xml │ │ │ ├── activity_decompiler_process.xml │ │ │ ├── activity_image_viewer.xml │ │ │ ├── activity_landing.xml │ │ │ ├── activity_low_memory.xml │ │ │ ├── activity_navigator.xml │ │ │ ├── activity_purchase.xml │ │ │ ├── activity_settings.xml │ │ │ ├── layout_admob.xml │ │ │ ├── layout_app_list_item.xml │ │ │ ├── layout_drawer_header.xml │ │ │ ├── layout_pick_decompiler_list_item.xml │ │ │ └── layout_toolbar.xml │ │ │ ├── menu │ │ │ ├── menu_app.xml │ │ │ ├── menu_fab.xml │ │ │ └── menu_main.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_logo_plain.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_logo_plain.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_logo_plain.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_logo_plain.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_logo_plain.png │ │ │ ├── transition │ │ │ └── default_window_fade.xml │ │ │ ├── values-sw360dp-v13 │ │ │ └── values-preference.xml │ │ │ ├── values-v21 │ │ │ └── styles.xml │ │ │ ├── values │ │ │ ├── array.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ ├── file_provider_paths.xml │ │ │ ├── preferences.xml │ │ │ └── searchable.xml │ └── test │ │ └── kotlin │ │ └── com │ │ └── njlabs │ │ └── showjava │ │ └── ExampleUnitTest.kt └── test-proguard-rules.pro ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /apl 2 | /captures 3 | *.apk 4 | *.ap_ 5 | /releases 6 | /local.properties 7 | /app/keys.properties 8 | *.dex 9 | *.class 10 | bin/ 11 | gen/ 12 | /app/extra.gradle 13 | Thumbs.db 14 | .DS_Store 15 | .classpath 16 | .project 17 | .idea 18 | .gradle 19 | build 20 | *.iml 21 | google-services.json 22 | /app/standard/ 23 | tmp 24 | dependencies.txt 25 | test.sh -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: oraclejdk8 4 | 5 | sudo: false 6 | 7 | env: 8 | global: 9 | - MALLOC_ARENA_MAX=1 10 | # matrix: 11 | # - API_LEVEL=25 SYS_IMAGE_TAG=google_apis ANDROID_ABI=arm64-v8a 12 | # - API_LEVEL=24 SYS_IMAGE_TAG=google_apis ANDROID_ABI=arm64-v8a 13 | # - API_LEVEL=21 SYS_IMAGE_TAG=google_apis ANDROID_ABI=armeabi-v7a 14 | # - API_LEVEL=19 SYS_IMAGE_TAG=google_apis ANDROID_ABI=armeabi-v7a 15 | # - API_LEVEL=17 SYS_IMAGE_TAG=google_apis ANDROID_ABI=armeabi-v7a 16 | 17 | android: 18 | components: 19 | - tools 20 | - android-28 21 | # - android-$API_LEVEL 22 | - build-tools-28.0.3 23 | - platform-tools 24 | - extra 25 | # - sys-img-$ANDROID_ABI-$SYS_IMAGE_TAG-$API_LEVEL 26 | 27 | before_cache: 28 | - rm -rf $HOME/.gradle/caches/modules-2/modules-2.lock 29 | - rm -rf $HOME/.gradle/caches/*/plugin-resolution/ 30 | 31 | cache: 32 | directories: 33 | - $HOME/.gradle/caches/ 34 | - $HOME/.gradle/wrapper/ 35 | - $HOME/.android/build-cache 36 | 37 | #install: 38 | # - ulimit -s 1082768 39 | # - touch app/keys.properties 40 | # - echo no | android create avd --force -n test -t android-$API_LEVEL --abi $ANDROID_ABI --tag $SYS_IMAGE_TAG 41 | # - emulator -avd test -no-skin -no-window & 42 | # - android-wait-for-emulator 43 | # - adb shell input keyevent 82 & 44 | 45 | before_script: 46 | - cp -f app/mock-google-services.json app/google-services.json 47 | - cat app/keys.properties.example | envsubst > app/keys.properties 48 | - yes | sdkmanager "platforms;android-28" 49 | - yes | sdkmanager "build-tools;28.0.3" 50 | 51 | script: 52 | # - ./gradlew connectedAndroidTest --stacktrace -w 53 | - ./gradlew assembleRelease --stacktrace -w 54 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to ShowJava 2 | 3 | 1. Fork the repository. ([niranjan94/show-java](https://www.github.com/niranjan94/show-java)) 4 | 2. Clone the repository locally by using the command: ```git clone git@github.com:username/show-java``` 5 | 6 | > Connect your local to the original ‘upstream’ repository by adding it as a remote. Pull in changes from ‘upstream’ often so that you stay up to date so that when you submit your pull request, merge conflicts will be less likely. See more detailed instructions [here](https://help.github.com/articles/syncing-a-fork). 7 | 8 | 3. Create a branch for your edits/bugfixes/feature additions 9 | 4. Do your magic 10 | 5. Test whatever you made in Android versions 4.1.x , 4.4.x, 5.x, 6.x, 7.x etc (You get the idea :wink: ) 11 | 6. Once you're confident in your code, send a pull request to the `development` branch of the upstream repository with a proper descriptions explaining what you did and why. Be clear and consise. 12 | 7. Wait for one of the project maintainers to review your pull request. 13 | 8. We may merge it into the `development` branch if it's good. 14 | 15 | > Also have a look at the [GitHub Flow](https://guides.github.com/introduction/flow/), to understand better how all this works. 16 | 17 | ## Reporting a Bug ([over here](https://github.com/niranjan94/show-java/issues/new)) 18 | 19 | 1. Check [existing issues](https://github.com/niranjan94/show-java/issues) for your issue. Duplicating an issue is slower for both parties so search through open and closed issues to see if what you’re running into has been addressed already. 20 | 2. Be clear about what your problem is: what was the expected outcome, what happened instead? Detail how someone else can recreate the problem. 21 | 3. Include system details like Android version, total RAM, etc. 22 | 4. If possible, include the link to the app that you were trying to decompile 23 | 5. Paste stacktrace (if possible) in your issue or in a Gist. If pasting them in the issue, wrap it in three backticks: ``` so that it renders nicely. 24 | 6. Submit it and wait for one of the project maintainers to review it. (Please be patient) 25 | 26 | ## Requesting a Feature/Enhancement ([over here](https://github.com/niranjan94/show-java/issues/new)) 27 | 28 | 1. Check [existing issues](https://github.com/niranjan94/show-java/issues) for your issue. Duplicating an issue is slower for both parties so search through open and closed issues to see if what you’re running into has been addressed already. 29 | 2. Give a clear and a consise description about the feature/enhancement that you'd love to see in ShowJava 30 | 3. Submit it and wait for one of the project maintainers to review it. (Please be patient) -------------------------------------------------------------------------------- /app/keys.properties.example: -------------------------------------------------------------------------------- 1 | deviceId=YourDeviceId 2 | admobPublisherId=pub-3940256099942544 3 | adUnitId=YourAdUnitId 4 | admobAppId=ca-app-pub-3940256099942544~3347511713 5 | IapProductId=pro_app 6 | googlePlayLicenseKey=xyzzy 7 | backendUrl=https://postb.in/iiolsQAd 8 | purchaseVerifierPath=check/buy 9 | privacyPolicyUrl=https://example.com/privacy-policy/ 10 | minifyEnabled=true 11 | shrinkResources=true 12 | crashlyticsApiKey=$CRASHLYTICS_API_KEY -------------------------------------------------------------------------------- /app/libs/android-5.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/android-5.1.jar -------------------------------------------------------------------------------- /app/libs/dex-ir-1.12.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/dex-ir-1.12.jar -------------------------------------------------------------------------------- /app/libs/dex-reader-1.15.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/dex-reader-1.15.jar -------------------------------------------------------------------------------- /app/libs/dex-tools-0.0.9.15.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/dex-tools-0.0.9.15.jar -------------------------------------------------------------------------------- /app/libs/dex-translator-0.0.9.15.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/dex-translator-0.0.9.15.jar -------------------------------------------------------------------------------- /app/libs/dx-1.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/dx-1.16.jar -------------------------------------------------------------------------------- /app/libs/jadx-core-0.9.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/jadx-core-0.9.0.jar -------------------------------------------------------------------------------- /app/libs/smali-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/libs/smali-2.2.1.jar -------------------------------------------------------------------------------- /app/multidex-config.pro: -------------------------------------------------------------------------------- 1 | -keep class com.njlabs.MainApplication 2 | -keep class com.njlabs.MainApplication { *; } 3 | -keep class com.njlabs.showjava.utils.logging.** { *; } 4 | -keep class com.njlabs.showjava.test.** { *; } 5 | -keep class androidx.test.** { *; } 6 | -keep class androidx.multidex.** { *; } 7 | -keep class kotlin.** { *; } 8 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | 7 | -libraryjars libs/android-5.1.jar 8 | -libraryjars libs/dex-ir-1.12.jar 9 | -libraryjars libs/dex-reader-1.15.jar 10 | -libraryjars libs/dex-tools-0.0.9.15.jar 11 | -libraryjars libs/dex-translator-0.0.9.15.jar 12 | -libraryjars libs/dx-1.16.jar 13 | -libraryjars libs/jadx-core-0.9.0.jar 14 | -libraryjars libs/smali-2.2.1.jar 15 | 16 | -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*,!code/allocation/variable 17 | -allowaccessmodification 18 | 19 | -keep public class com.android.vending.billing.IInAppBillingService 20 | -keep class com.android.vending.billing.** 21 | -keep public class * extends android.view.View { 22 | public (android.content.Context); 23 | public (android.content.Context, android.util.AttributeSet); 24 | public (android.content.Context, android.util.AttributeSet, int); 25 | } 26 | -keepclasseswithmembers class * { 27 | public (android.content.Context, android.util.AttributeSet); 28 | } 29 | -keepclasseswithmembers class * { 30 | public (android.content.Context, android.util.AttributeSet, int); 31 | } 32 | -keepclassmembers class * extends android.content.Context { 33 | public void *(android.view.View); 34 | public void *(android.view.MenuItem); 35 | } 36 | 37 | -keep class android.support.v4.app.** { *; } 38 | -keep interface android.support.v4.app.** { *; } 39 | 40 | -keep class android.support.** { *; } 41 | -keep interface android.support.** { *; } 42 | 43 | 44 | -keepattributes *Annotation* 45 | -keepattributes Signature 46 | -keepattributes InnerClasses 47 | -keepattributes InnerClasses,EnclosingMethod 48 | 49 | -keep class com.googlecode.** 50 | -keep class com.android.** 51 | -keep class com.crashlytics.android.** 52 | -keep class org.objectweb.asm.** 53 | -keep class io.fabric.sdk.android.** 54 | -keep class com.crashlytics.android.** 55 | -keep class com.google.android.** 56 | -keep class ch.qos.logback.** 57 | -keep class com.android.dex.** { *; } 58 | -keep class xyz.codezero.android.dex.** { *; } 59 | -keep class kotlin.** { *; } 60 | -keep class com.njlabs.showjava.MainApplication { *; } 61 | -keep class com.njlabs.showjava.decompilers.** { *; } 62 | -keep class jadx.core.clsp.** { *; } 63 | 64 | -keepattributes SourceFile,LineNumberTable 65 | 66 | -keep public class * extends java.lang.Exception 67 | 68 | -dontwarn com.google.** 69 | -dontwarn com.android.** 70 | -dontwarn antlr.debug.** 71 | -dontwarn org.antlr.** 72 | -dontwarn com.njlabs.showjava.** 73 | -dontwarn rx.internal.** 74 | -dontwarn com.googlecode.dex2jar.** 75 | -dontwarn android.test.** 76 | -dontwarn p.rn.** 77 | -dontwarn junit.runner.** 78 | -dontwarn net.dongliu.** 79 | -dontwarn com.** 80 | -dontwarn android.** 81 | -dontwarn org.** 82 | -dontwarn net.** 83 | -dontwarn uk.** 84 | -dontwarn io.** 85 | -dontwarn jadx.** 86 | -dontwarn java.** 87 | -dontwarn org.jetbrains.java.decompiler.** 88 | -dontwarn com.crashlytics.** 89 | -dontwarn com.google.android.** 90 | -dontwarn ch.qos.logback.** -------------------------------------------------------------------------------- /app/src/androidTest/assets/test-application.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/androidTest/assets/test-application.jar -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/apk/ApkViaCfr.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.apk 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class ApkViaCfr: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.APK 29 | override val decompiler: String = "cfr" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/apk/ApkViaFernFlower.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.apk 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class ApkViaFernFlower: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.APK 29 | override val decompiler: String = "fernflower" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/apk/ApkViaJadx.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.apk 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class ApkViaJadx: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.APK 29 | override val decompiler: String = "jadx" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/dex/DexViaCfr.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.dex 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class DexViaCfr: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.DEX 29 | override val decompiler: String = "cfr" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/dex/DexViaFernFlower.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.dex 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class DexViaFernFlower: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.DEX 29 | override val decompiler: String = "fernflower" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/dex/DexViaJadx.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.dex 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class DexViaJadx: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.DEX 29 | override val decompiler: String = "jadx" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/jar/JarViaCfr.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.jar 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class JarViaCfr: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.JAR 29 | override val decompiler: String = "cfr" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/jar/JarViaFernFlower.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.jar 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class JarViaFernFlower: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.JAR 29 | override val decompiler: String = "fernflower" 30 | } -------------------------------------------------------------------------------- /app/src/androidTest/kotlin/com/njlabs/showjava/test/decompilers/jar/JarViaJadx.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.test.decompilers.jar 20 | 21 | import androidx.test.ext.junit.runners.AndroidJUnit4 22 | import com.njlabs.showjava.test.DecompilerTestBase 23 | import com.njlabs.showjava.data.PackageInfo 24 | import org.junit.runner.RunWith 25 | 26 | @RunWith(AndroidJUnit4::class) 27 | class JarViaJadx: DecompilerTestBase() { 28 | override val type: PackageInfo.Type = PackageInfo.Type.JAR 29 | override val decompiler: String = "jadx" 30 | } -------------------------------------------------------------------------------- /app/src/main/assets/codeview/highlightjs/styles/androidstudio.css: -------------------------------------------------------------------------------- 1 | /* 2 | Date: 24 Fev 2015 3 | Author: Pedro Oliveira 4 | */ 5 | 6 | .hljs { 7 | color: #a9b7c6; 8 | background: #282b2e; 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | } 13 | 14 | .hljs-number, 15 | .hljs-literal, 16 | .hljs-symbol, 17 | .hljs-bullet { 18 | color: #6897BB; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-deletion { 24 | color: #cc7832; 25 | } 26 | 27 | .hljs-variable, 28 | .hljs-template-variable, 29 | .hljs-link { 30 | color: #629755; 31 | } 32 | 33 | .hljs-comment, 34 | .hljs-quote { 35 | color: #808080; 36 | } 37 | 38 | .hljs-meta { 39 | color: #bbb529; 40 | } 41 | 42 | .hljs-string, 43 | .hljs-attribute, 44 | .hljs-addition { 45 | color: #6A8759; 46 | } 47 | 48 | .hljs-section, 49 | .hljs-title, 50 | .hljs-type { 51 | color: #ffc66d; 52 | } 53 | 54 | .hljs-name, 55 | .hljs-selector-id, 56 | .hljs-selector-class { 57 | color: #e8bf6a; 58 | } 59 | 60 | .hljs-emphasis { 61 | font-style: italic; 62 | } 63 | 64 | .hljs-strong { 65 | font-weight: bold; 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/assets/codeview/highlightjs/styles/github-gist.css: -------------------------------------------------------------------------------- 1 | /** 2 | * GitHub Gist Theme 3 | * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | background: white; 9 | padding: 0.5em; 10 | color: #333333; 11 | overflow-x: auto; 12 | } 13 | 14 | .hljs-comment, 15 | .hljs-meta { 16 | color: #969896; 17 | } 18 | 19 | .hljs-string, 20 | .hljs-variable, 21 | .hljs-template-variable, 22 | .hljs-strong, 23 | .hljs-emphasis, 24 | .hljs-quote { 25 | color: #df5000; 26 | } 27 | 28 | .hljs-keyword, 29 | .hljs-selector-tag, 30 | .hljs-type { 31 | color: #a71d5d; 32 | } 33 | 34 | .hljs-literal, 35 | .hljs-symbol, 36 | .hljs-bullet, 37 | .hljs-attribute { 38 | color: #0086b3; 39 | } 40 | 41 | .hljs-section, 42 | .hljs-name { 43 | color: #63a35c; 44 | } 45 | 46 | .hljs-tag { 47 | color: #333333; 48 | } 49 | 50 | .hljs-title, 51 | .hljs-attr, 52 | .hljs-selector-id, 53 | .hljs-selector-class, 54 | .hljs-selector-attr, 55 | .hljs-selector-pseudo { 56 | color: #795da3; 57 | } 58 | 59 | .hljs-addition { 60 | color: #55a532; 61 | background-color: #eaffea; 62 | } 63 | 64 | .hljs-deletion { 65 | color: #bd2c00; 66 | background-color: #ffecec; 67 | } 68 | 69 | .hljs-link { 70 | text-decoration: underline; 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/assets/codeview/script.js: -------------------------------------------------------------------------------- 1 | var lines; 2 | 3 | function highlightCode() { 4 | try { 5 | android.onStartCodeHighlight(); 6 | } catch (ignored) { } 7 | var codeHolder = document.getElementById('code-holder'); 8 | hljs.highlightBlock(codeHolder); 9 | try { 10 | android.onFinishCodeHighlight(); 11 | lines = document.querySelectorAll('td.ln'); 12 | } catch (ignored) { } 13 | } 14 | 15 | 16 | function updateStyleAndClasses(styleUri, bodyClass) { 17 | document.getElementById('stylesheet').setAttribute('href', styleUri); 18 | document.getElementById('body').setAttribute('class', bodyClass); 19 | } 20 | 21 | function showHideLineNumber(isShown) { 22 | for (var i = 0; i < lines.length; i++) { 23 | lines[i].style.display = isShown ? '' : 'none'; 24 | } 25 | } 26 | 27 | function changeFontSize(size) { 28 | document.body.style.fontSize = size + 'px'; 29 | } 30 | 31 | function fillLineNumbers() { 32 | for (var i = 0; i < lines.length; i++) { 33 | lines[i].innerHTML = lines[i].getAttribute('line'); 34 | } 35 | } 36 | 37 | function highlightLineNumber(number) { 38 | var x = document.querySelectorAll('.highlighted-line'); 39 | if(x && x.length === 1) { 40 | x[0].classList.remove('highlighted-line'); 41 | } 42 | if (number > 0) { 43 | var x = document.querySelectorAll("td.line[line='" + number + "']"); 44 | if(x && x.length === 1) { 45 | x[0].classList.add('highlighted-line') 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/assets/codeview/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | line-height: 1.2; 4 | } 5 | 6 | body.dark { 7 | background: #212121 !important; 8 | } 9 | 10 | body.light { 11 | background: white !important; 12 | } 13 | 14 | .hljs { 15 | } 16 | 17 | pre { 18 | margin: 0; 19 | position: relative; 20 | } 21 | 22 | table, td, tr { 23 | margin: 0; 24 | padding: 0; 25 | } 26 | 27 | code > span { 28 | display: none; 29 | } 30 | 31 | td.ln { 32 | text-align: right; 33 | padding-right: 2px; 34 | } 35 | 36 | td.line:hover span { 37 | background: #661d76; 38 | color: #fff; 39 | } 40 | 41 | td.line:hover { 42 | background: #661d76; 43 | color: #fff; 44 | border-radius: 2px; 45 | } 46 | 47 | td.highlighted-line { 48 | background: #ffda11; 49 | color: #000; 50 | border-radius: 2px; 51 | } 52 | 53 | td.highlighted-line span { 54 | background: #ffda11; 55 | color: #000; 56 | } 57 | 58 | body.wrapped td.line { 59 | word-wrap: break-word; 60 | white-space: pre-wrap; 61 | word-break: break-all; 62 | } -------------------------------------------------------------------------------- /app/src/main/assets/ignored.basic.list: -------------------------------------------------------------------------------- 1 | com.google.apps 2 | android 3 | com.android.support 4 | com.android 5 | com.google.android.gms 6 | com.google.common 7 | com.google.auto 8 | com.google.ads 9 | com.google.android 10 | com.google.android.vending 11 | javax 12 | junit 13 | kotlin 14 | androidx 15 | sun.misc 16 | dalvik.system 17 | org.junit 18 | java 19 | org.intellij.lang.annotations 20 | org.jetbrains.annotations 21 | rx 22 | io.reactivex 23 | dagger 24 | io.realm 25 | com.facebook.react 26 | com.android.volley 27 | com.facebook.fresco 28 | com.facebook.drawee 29 | com.facebook.rebound 30 | com.google.protobuf 31 | com.google.gson 32 | -------------------------------------------------------------------------------- /app/src/main/assets/ignored.list: -------------------------------------------------------------------------------- 1 | com.bumptech.glide 2 | org.androidannotations 3 | de.greenrobot.event 4 | roboguice 5 | com.squareup.okhttp 6 | okhttp3 7 | com.square.picasso 8 | com.squareup.picasso 9 | com.square.tape 10 | com.squareup.tape 11 | com.nineoldandroids 12 | bolts 13 | com.mikepenz.iconics 14 | com.mikepenz.google_material 15 | retrofit 16 | org.parceler 17 | butterknife 18 | com.crashlytics 19 | io.fabric.sdk 20 | com.androidquery 21 | com.parse 22 | com.actionbarsherlock 23 | org.apache 24 | org.acra 25 | org.joda 26 | org.antlr 27 | org.achartengine 28 | com.bugsense 29 | org.andengine 30 | com.inmobi 31 | com.google.zxing 32 | com.dacer.androidcharts 33 | com.astuetz 34 | com.viewpagerindicator 35 | de.greenrobot.dao 36 | com.mopub 37 | com.millennialmedia 38 | com.amazon.inapp 39 | com.flurry.sdk 40 | org.spongycastle 41 | com.google.firebase 42 | org.jsoup 43 | com.fasterxml.jackson 44 | org.codehaus.jackson 45 | org.greenrobot.eventbus 46 | pub.devrel.easypermissions 47 | org.slf4j 48 | cz.msebera.android.httpclient 49 | net.sourceforge.javaflacencoder 50 | vavi.sound 51 | okio 52 | org.objectweb.asm 53 | com.appsflyer 54 | com.mobikwik.sdk 55 | com.clevertap.android.sdk 56 | com.mixpanel 57 | com.google.vr.sdk -------------------------------------------------------------------------------- /app/src/main/config/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | [ignored] %msg%n 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher_round-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/ic_launcher_round-web.png -------------------------------------------------------------------------------- /app/src/main/ic_logo_plain-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/ic_logo_plain-web.png -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/Constants.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava 20 | 21 | /** 22 | * Constants used throughout the application 23 | */ 24 | object Constants { 25 | 26 | const val STORAGE_PERMISSION_REQUEST = 1009 27 | 28 | interface EVENTS { 29 | companion object { 30 | const val CLEAR_SOURCE_HISTORY = "clear_source_history" 31 | const val CHANGE_FONT = "change_font" 32 | const val TOGGLE_DARK_MODE = "toggle_dark_mode" 33 | const val SELECT_DECOMPILER = "select_decompiler" 34 | const val DECOMPILE_APP = "decompile_app" 35 | const val REPORT_APP_LOW_MEMORY = "report_app_low_memory" 36 | } 37 | } 38 | 39 | /** 40 | * Workers related constants 41 | */ 42 | interface WORKER { 43 | 44 | companion object { 45 | const val STATUS_TYPE = "com.njlabs.showjava.worker.STATUS_TYPE" 46 | const val STATUS_TITLE = "com.njlabs.showjava.worker.STATUS_TITLE" 47 | const val STATUS_MESSAGE = "com.njlabs.showjava.worker.STATUS_MESSAGE" 48 | 49 | const val PROGRESS_NOTIFICATION_CHANNEL = "com.njlabs.showjava.worker.notification.progress" 50 | const val COMPLETION_NOTIFICATION_CHANNEL = "com.njlabs.showjava.worker.notification.completion" 51 | const val PROGRESS_NOTIFICATION_ID = 1094 52 | const val COMPLETED_NOTIFICATION_ID = 1095 53 | } 54 | 55 | /** 56 | * Actions used for interacting with workers 57 | */ 58 | interface ACTION { 59 | companion object { 60 | // Action to broadcast status to receivers 61 | const val BROADCAST = "com.njlabs.showjava.worker.action.BROADCAST" 62 | 63 | // Action to instruct the receiver to stop the worker 64 | const val STOP = "com.njlabs.showjava.worker.action.STOP" 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/MainApplication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava 20 | 21 | import android.app.NotificationManager 22 | import android.content.Context 23 | import android.os.Build 24 | import androidx.annotation.RequiresApi 25 | import androidx.appcompat.app.AppCompatDelegate 26 | import androidx.multidex.MultiDexApplication 27 | import androidx.preference.PreferenceManager 28 | import androidx.work.WorkManager 29 | import com.njlabs.showjava.utils.Ads 30 | import com.njlabs.showjava.utils.UserPreferences 31 | import com.njlabs.showjava.utils.logging.ProductionTree 32 | import io.reactivex.Observable 33 | import io.reactivex.disposables.CompositeDisposable 34 | import io.reactivex.schedulers.Schedulers 35 | import timber.log.Timber 36 | import com.crashlytics.android.Crashlytics 37 | import com.google.firebase.iid.FirebaseInstanceId 38 | import io.fabric.sdk.android.Fabric 39 | 40 | 41 | class MainApplication : MultiDexApplication() { 42 | 43 | val disposables = CompositeDisposable() 44 | lateinit var instanceId: String 45 | 46 | override fun onCreate() { 47 | super.onCreate() 48 | instanceId = FirebaseInstanceId.getInstance().id 49 | 50 | PreferenceManager.setDefaultValues( 51 | applicationContext, 52 | UserPreferences.NAME, 53 | Context.MODE_PRIVATE, 54 | R.xml.preferences, 55 | false 56 | ) 57 | 58 | val preferences = 59 | UserPreferences( 60 | applicationContext.getSharedPreferences( 61 | UserPreferences.NAME, 62 | Context.MODE_PRIVATE 63 | ) 64 | ) 65 | 66 | AppCompatDelegate.setDefaultNightMode( 67 | if (preferences.darkMode) 68 | AppCompatDelegate.MODE_NIGHT_YES 69 | else 70 | AppCompatDelegate.MODE_NIGHT_NO 71 | ) 72 | 73 | Ads(this).init() 74 | Fabric.with(this, Crashlytics()) 75 | Crashlytics.setUserIdentifier(instanceId) 76 | 77 | if (BuildConfig.DEBUG) { 78 | Timber.plant(Timber.DebugTree()) 79 | } else { 80 | Timber.plant(ProductionTree()) 81 | } 82 | 83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 84 | disposables.add( 85 | cleanStaleNotifications() 86 | .subscribeOn(Schedulers.io()) 87 | .observeOn(Schedulers.io()) 88 | .onErrorReturn {} 89 | .subscribe() 90 | ) 91 | } 92 | } 93 | 94 | /** 95 | * Clean any stale notifications not linked to any decompiler process 96 | */ 97 | @RequiresApi(Build.VERSION_CODES.M) 98 | fun cleanStaleNotifications(): Observable { 99 | return Observable.fromCallable { 100 | val manager = applicationContext 101 | .getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 102 | val workManager = WorkManager.getInstance() 103 | manager.activeNotifications.forEach { notification -> 104 | val status = workManager.getWorkInfosForUniqueWorkLiveData(notification.tag) 105 | .value?.any { it.state.isFinished } 106 | if (status == null || status == true) { 107 | manager.cancel(notification.tag, notification.id) 108 | } 109 | } 110 | } 111 | } 112 | 113 | override fun onTerminate() { 114 | super.onTerminate() 115 | disposables.clear() 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/about/AboutActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.about 20 | 21 | import android.content.Intent 22 | import android.os.Bundle 23 | import com.google.android.gms.oss.licenses.OssLicensesMenuActivity 24 | import com.njlabs.showjava.BuildConfig 25 | import com.njlabs.showjava.R 26 | import com.njlabs.showjava.activities.BaseActivity 27 | import kotlinx.android.synthetic.main.activity_about.* 28 | 29 | /** 30 | * Show information about the app, its version & licenses to all open source libraries used 31 | */ 32 | class AboutActivity : BaseActivity() { 33 | override fun init(savedInstanceState: Bundle?) { 34 | setupLayout(R.layout.activity_about) 35 | if (BuildConfig.GIT_SHA.isNotEmpty()) { 36 | version.setText(R.string.appVersionExtendedWithHash) 37 | } 38 | 39 | appInstanceId.text = getString(R.string.instanceId, mainApplication.instanceId) 40 | 41 | viewOpenSourceLicenses.setOnClickListener { 42 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) 43 | startActivity(Intent(context, OssLicensesMenuActivity::class.java)) 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/apps/AppsHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.apps 20 | 21 | import android.content.Context 22 | import com.njlabs.showjava.R 23 | import com.njlabs.showjava.data.PackageInfo 24 | import com.njlabs.showjava.utils.ktx.isSystemPackage 25 | import com.njlabs.showjava.utils.rx.ProcessStatus 26 | import io.reactivex.Observable 27 | import io.reactivex.ObservableEmitter 28 | 29 | class AppsHandler(private var context: Context) { 30 | 31 | /** 32 | * Load all installed applications. 33 | * 34 | * @return [Observable] which can be used to track the loading progress and completion state. 35 | */ 36 | fun loadApps(withSystemApps: Boolean): Observable>> { 37 | return Observable.create { emitter: ObservableEmitter>> -> 38 | val installedApps = ArrayList() 39 | var packages = context.packageManager.getInstalledPackages(0) 40 | packages = packages.filter { pack -> 41 | withSystemApps || !isSystemPackage(pack) 42 | } 43 | packages.forEachIndexed { index, pack -> 44 | val packageInfo = PackageInfo.fromApkPackageInfo(context, pack) 45 | packageInfo.icon = pack.applicationInfo.loadIcon(context.packageManager) 46 | packageInfo.isSystemPackage = isSystemPackage(pack) 47 | installedApps.add(packageInfo) 48 | val currentCount = index + 1 49 | emitter.onNext( 50 | ProcessStatus( 51 | (currentCount.toFloat() / packages.size.toFloat()) * 100f, 52 | context.getString(R.string.loadingApp, packageInfo.label), 53 | context.getString(R.string.loadingStatistic, currentCount, packages.size) 54 | ) 55 | ) 56 | } 57 | installedApps.sortBy { 58 | it.label.toLowerCase() 59 | } 60 | emitter.onNext(ProcessStatus(installedApps)) 61 | emitter.onComplete() 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/apps/adapters/AppsListAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.apps.adapters 20 | 21 | import android.content.Context 22 | import android.text.SpannableString 23 | import android.text.TextUtils 24 | import android.view.LayoutInflater 25 | import android.view.View 26 | import android.view.ViewGroup 27 | import androidx.core.content.ContextCompat 28 | import androidx.core.content.res.ResourcesCompat 29 | import cn.nekocode.badge.BadgeDrawable 30 | import com.njlabs.showjava.R 31 | import com.njlabs.showjava.data.PackageInfo 32 | import kotlinx.android.synthetic.main.layout_app_list_item.view.* 33 | 34 | 35 | fun getSystemBadge(context: Context): BadgeDrawable { 36 | return BadgeDrawable.Builder() 37 | .type(BadgeDrawable.TYPE_ONLY_ONE_TEXT) 38 | .badgeColor(ContextCompat.getColor(context, R.color.grey_400)) 39 | .typeFace(ResourcesCompat.getFont(context, R.font.lato)) 40 | .text1("system") 41 | .build() 42 | } 43 | 44 | /** 45 | * Adapter for populating and managing the Apps list 46 | */ 47 | class AppsListAdapter( 48 | private var apps: List, 49 | private val itemClick: (PackageInfo, View) -> Unit 50 | ) : androidx.recyclerview.widget.RecyclerView.Adapter() { 51 | 52 | private lateinit var systemBadgeInstance: BadgeDrawable 53 | 54 | inner class ViewHolder(private val view: View, private val itemClick: (PackageInfo, View) -> Unit) : 55 | androidx.recyclerview.widget.RecyclerView.ViewHolder(view) { 56 | 57 | private val systemBadge: BadgeDrawable 58 | get() { 59 | if (!::systemBadgeInstance.isInitialized) { 60 | systemBadgeInstance = getSystemBadge(view.context) 61 | } 62 | return systemBadgeInstance 63 | } 64 | 65 | fun bindPackageInfo(packageInfo: PackageInfo) { 66 | with(packageInfo) { 67 | itemView.itemLabel.text = if (packageInfo.isSystemPackage) 68 | SpannableString( 69 | TextUtils.concat( 70 | packageInfo.label, 71 | " ", " ", 72 | systemBadge.toSpannable() 73 | ) 74 | ) 75 | else 76 | packageInfo.label 77 | 78 | itemView.itemSecondaryLabel.text = packageInfo.version 79 | itemView.itemIcon.setImageDrawable(packageInfo.icon) 80 | itemView.itemCard.cardElevation = 1F 81 | itemView.itemCard.setOnClickListener { itemClick(this, itemView) } 82 | } 83 | } 84 | } 85 | 86 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 87 | val view = LayoutInflater.from(parent.context) 88 | .inflate(R.layout.layout_app_list_item, parent, false) 89 | return ViewHolder(view, itemClick) 90 | } 91 | 92 | override fun onBindViewHolder(holder: AppsListAdapter.ViewHolder, position: Int) { 93 | holder.bindPackageInfo(apps[position]) 94 | } 95 | 96 | override fun getItemCount(): Int { 97 | return apps.size 98 | } 99 | 100 | fun updateList(apps: List) { 101 | this.apps = apps 102 | notifyDataSetChanged() 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/decompiler/LowMemoryActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.decompiler 20 | 21 | import android.os.Bundle 22 | import android.widget.Toast 23 | import com.njlabs.showjava.Constants 24 | import com.njlabs.showjava.R 25 | import com.njlabs.showjava.activities.BaseActivity 26 | import com.njlabs.showjava.data.PackageInfo 27 | import com.njlabs.showjava.utils.ktx.toBundle 28 | import io.reactivex.android.schedulers.AndroidSchedulers 29 | import io.reactivex.schedulers.Schedulers 30 | import kotlinx.android.synthetic.main.activity_low_memory.* 31 | import timber.log.Timber 32 | 33 | /** 34 | * If an app's decompilation was stopped due to low memory, explain what happened to the user 35 | * And also provide user a way to report the app that failed to decompile. This can then 36 | * be investigated later on to see what can be done to reduce the memory usage. 37 | */ 38 | class LowMemoryActivity : BaseActivity() { 39 | 40 | override fun init(savedInstanceState: Bundle?) { 41 | setupLayout(R.layout.activity_low_memory) 42 | val packageInfo = intent.getParcelableExtra("packageInfo") 43 | val decompiler = intent.getStringExtra("decompiler") 44 | 45 | reportButton.setOnClickListener { 46 | 47 | firebaseAnalytics.logEvent(Constants.EVENTS.REPORT_APP_LOW_MEMORY, mapOf( 48 | "shouldIgnoreLibs" to userPreferences.ignoreLibraries, 49 | "maxAttempts" to userPreferences.maxAttempts, 50 | "chunkSize" to userPreferences.chunkSize, 51 | "memoryThreshold" to userPreferences.memoryThreshold, 52 | "label" to packageInfo.label, 53 | "name" to packageInfo.name, 54 | "type" to packageInfo.type.name, 55 | "decompiler" to decompiler 56 | ).toBundle()) 57 | 58 | Toast.makeText(context, R.string.appReportThanks, Toast.LENGTH_LONG).show() 59 | } 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/explorer/navigator/NavigatorHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.explorer.navigator 20 | 21 | import android.content.Context 22 | import com.crashlytics.android.Crashlytics 23 | import com.njlabs.showjava.data.FileItem 24 | import com.njlabs.showjava.utils.ZipUtils 25 | import io.reactivex.Observable 26 | import org.apache.commons.io.FileUtils 27 | import java.io.File 28 | import java.io.IOException 29 | import java.text.DateFormat 30 | import java.util.Date 31 | import kotlin.collections.ArrayList 32 | import kotlin.collections.forEach 33 | import kotlin.collections.sortBy 34 | 35 | class NavigatorHandler(private var context: Context) { 36 | 37 | /** 38 | * Load all files in the given directory 39 | */ 40 | fun loadFiles(currentDirectory: File): Observable> { 41 | return Observable.fromCallable { 42 | val directories = ArrayList() 43 | val files = ArrayList() 44 | val items = currentDirectory.listFiles() 45 | if (items.isNullOrEmpty()) { 46 | return@fromCallable directories 47 | } 48 | items.forEach { file -> 49 | val lastModDate = DateFormat.getDateTimeInstance() 50 | .format( 51 | Date( 52 | file.lastModified() 53 | ) 54 | ) 55 | if (file.isDirectory) { 56 | val children = file.listFiles() 57 | val noOfChildren = children?.size ?: 0 58 | val fileSize = "$noOfChildren ${if (noOfChildren == 1) "item" else "items"}" 59 | directories.add(FileItem(file, fileSize, lastModDate)) 60 | } else { 61 | val fileSize = FileUtils.byteCountToDisplaySize(file.length()) 62 | files.add(FileItem(file, fileSize, lastModDate)) 63 | } 64 | } 65 | directories.sortBy { it.name?.toLowerCase() } 66 | files.sortBy { it.name?.toLowerCase() } 67 | directories.addAll(files) 68 | directories 69 | } 70 | } 71 | 72 | /** 73 | * Package an entire directory containing the source code into a .zip archive. 74 | */ 75 | fun archiveDirectory(sourceDirectory: File, packageName: String): Observable { 76 | return Observable.fromCallable { 77 | ZipUtils.zipDir(sourceDirectory, packageName) 78 | } 79 | } 80 | 81 | /** 82 | * Delete the source directory 83 | */ 84 | fun deleteDirectory(sourceDirectory: File): Observable { 85 | return Observable.fromCallable { 86 | try { 87 | if (sourceDirectory.exists()) { 88 | FileUtils.deleteDirectory(sourceDirectory) 89 | } 90 | } catch (e: IOException) { 91 | Crashlytics.logException(e) 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/explorer/navigator/adapters/FilesListAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.explorer.navigator.adapters 20 | 21 | import android.view.LayoutInflater 22 | import android.view.View 23 | import android.view.ViewGroup 24 | import com.njlabs.showjava.R 25 | import com.njlabs.showjava.data.FileItem 26 | import kotlinx.android.synthetic.main.layout_app_list_item.view.* 27 | 28 | /** 29 | * List adapter for the code navigator 30 | */ 31 | class FilesListAdapter( 32 | private var fileItems: List, 33 | private val itemClick: (FileItem) -> Unit 34 | ) : androidx.recyclerview.widget.RecyclerView.Adapter() { 35 | 36 | class ViewHolder(view: View, private val itemClick: (FileItem) -> Unit) : 37 | androidx.recyclerview.widget.RecyclerView.ViewHolder(view) { 38 | fun bindSourceInfo(fileItem: FileItem) { 39 | with(fileItem) { 40 | itemView.itemLabel.text = fileItem.name 41 | itemView.itemSecondaryLabel.text = fileItem.fileSize 42 | itemView.itemIcon.setImageResource(fileItem.iconResource) 43 | itemView.itemCard.cardElevation = 1F 44 | itemView.itemCard.setOnClickListener { itemClick(this) } 45 | } 46 | } 47 | } 48 | 49 | fun updateData(fileItems: List?) { 50 | if (fileItems != null) { 51 | this.fileItems = fileItems 52 | notifyDataSetChanged() 53 | } 54 | } 55 | 56 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 57 | val view = LayoutInflater.from(parent.context) 58 | .inflate(R.layout.layout_app_list_item, parent, false) 59 | return ViewHolder(view, itemClick) 60 | } 61 | 62 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 63 | holder.bindSourceInfo(fileItems[position]) 64 | } 65 | 66 | override fun getItemCount(): Int { 67 | return fileItems.size 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/explorer/viewer/ImageViewerActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.explorer.viewer 20 | 21 | import android.graphics.Color 22 | import android.os.Bundle 23 | import android.os.Environment 24 | import android.view.Menu 25 | import android.view.MenuItem 26 | import com.davemorrissey.labs.subscaleview.ImageSource 27 | import com.davemorrissey.labs.subscaleview.ImageViewState 28 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView 29 | import com.njlabs.showjava.R 30 | import com.njlabs.showjava.activities.BaseActivity 31 | import kotlinx.android.synthetic.main.activity_image_viewer.* 32 | import org.apache.commons.io.FilenameUtils 33 | 34 | 35 | class ImageViewerActivity : BaseActivity() { 36 | private var isBlack: Boolean = true 37 | private val bundleState = "ImageViewState" 38 | 39 | override fun init(savedInstanceState: Bundle?) { 40 | setupLayout(R.layout.activity_image_viewer) 41 | window.decorView.setBackgroundColor(Color.BLACK) 42 | toolbar.popupTheme = R.style.AppTheme_DarkPopupOverlay 43 | 44 | val extras = intent.extras 45 | extras?.let { 46 | 47 | var imageViewState: ImageViewState? = null 48 | if (savedInstanceState != null && savedInstanceState.containsKey(bundleState)) { 49 | imageViewState = savedInstanceState.getSerializable(bundleState) as ImageViewState 50 | } 51 | 52 | val filePath = it.getString("filePath") 53 | val packageName = it.getString("name") 54 | val fileName = FilenameUtils.getName(filePath) 55 | supportActionBar?.title = fileName 56 | val subtitle = FilenameUtils 57 | .getFullPath(filePath) 58 | .replace( 59 | "${Environment.getExternalStorageDirectory()}/show-java/sources/$packageName/", 60 | "" 61 | ) 62 | 63 | if (fileName.trim().equals("icon.png", true)) { 64 | setSubtitle(packageName) 65 | } else { 66 | setSubtitle(subtitle) 67 | } 68 | 69 | imageView.setImage(ImageSource.uri(filePath!!), imageViewState) 70 | imageView.orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF 71 | imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_CENTER) 72 | imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM) 73 | imageView.setMinimumDpi(100) 74 | imageView.setMaximumDpi(600) 75 | } 76 | 77 | } 78 | 79 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 80 | menuInflater.inflate(R.menu.menu_main, menu) 81 | menu.findItem(R.id.invert_colors).isVisible = true 82 | return true 83 | } 84 | 85 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 86 | when (item.itemId) { 87 | R.id.invert_colors -> { 88 | if (isBlack) { 89 | window.decorView.setBackgroundColor(Color.WHITE) 90 | } else { 91 | window.decorView.setBackgroundColor(Color.BLACK) 92 | } 93 | isBlack = !isBlack 94 | return true 95 | } 96 | } 97 | return super.onOptionsItemSelected(item) 98 | } 99 | 100 | public override fun onSaveInstanceState(outState: Bundle) { 101 | super.onSaveInstanceState(outState) 102 | val state = imageView.state 103 | if (state != null) { 104 | outState.putSerializable(bundleState, imageView.state) 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/landing/LandingHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.landing 20 | 21 | import android.content.Context 22 | import androidx.work.WorkManager 23 | import com.njlabs.showjava.data.SourceInfo 24 | import com.njlabs.showjava.utils.ktx.appStorage 25 | import io.reactivex.Observable 26 | import timber.log.Timber 27 | import java.io.File 28 | import java.io.IOException 29 | 30 | class LandingHandler(private var context: Context) { 31 | 32 | 33 | private fun isDecompilerRunning(): Boolean { 34 | return WorkManager.getInstance().getWorkInfosByTagLiveData("decompiler").value?.any { 35 | !it.state.isFinished 36 | } ?: false 37 | } 38 | 39 | fun loadHistory(): Observable> { 40 | return Observable.fromCallable { 41 | val historyItems = ArrayList() 42 | appStorage.mkdirs() 43 | val nomedia = File(appStorage, ".nomedia") 44 | if (!nomedia.exists() || !nomedia.isFile) { 45 | try { 46 | nomedia.createNewFile() 47 | } catch (e: IOException) { 48 | Timber.e(e) 49 | } 50 | } 51 | val sourcesDir = appStorage.resolve("sources") 52 | if (sourcesDir.exists()) { 53 | val files = sourcesDir.listFiles() 54 | if (files != null && files.isNotEmpty()) 55 | files.forEach { file -> 56 | if (SourceInfo.exists(file)) { 57 | SourceInfo.from(file).let { 58 | historyItems.add(it) 59 | } 60 | } else { 61 | /* // Not deleting directories. 62 | if (!isDecompilerRunning()) { 63 | try { 64 | if (file.exists()) { 65 | if (file.isDirectory) { 66 | FileUtils.deleteDirectory(file) 67 | } else { 68 | file.delete() 69 | } 70 | } 71 | 72 | } catch (e: Exception) { 73 | Timber.d(e) 74 | } 75 | if (file.exists() && !file.isDirectory) { 76 | file.delete() 77 | } 78 | } 79 | */ 80 | } 81 | } 82 | } 83 | historyItems 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/landing/adapters/HistoryListAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.landing.adapters 20 | 21 | import android.graphics.BitmapFactory 22 | import android.graphics.drawable.BitmapDrawable 23 | import android.os.Environment 24 | import android.view.LayoutInflater 25 | import android.view.View 26 | import android.view.ViewGroup 27 | import com.njlabs.showjava.R 28 | import com.njlabs.showjava.data.SourceInfo 29 | import kotlinx.android.synthetic.main.layout_app_list_item.view.* 30 | import java.io.File 31 | 32 | class HistoryListAdapter( 33 | private var historyItems: List, 34 | private val itemClick: (SourceInfo) -> Unit 35 | ) : androidx.recyclerview.widget.RecyclerView.Adapter() { 36 | 37 | class ViewHolder(view: View, private val itemClick: (SourceInfo) -> Unit) : 38 | androidx.recyclerview.widget.RecyclerView.ViewHolder(view) { 39 | 40 | fun bindSourceInfo(sourceInfo: SourceInfo) { 41 | with(sourceInfo) { 42 | itemView.itemLabel.text = sourceInfo.packageLabel 43 | itemView.itemSecondaryLabel.text = sourceInfo.packageName 44 | val iconPath = 45 | "${Environment.getExternalStorageDirectory()}/show-java/sources/${sourceInfo.packageName}/icon.png" 46 | if (File(iconPath).exists()) { 47 | val iconBitmap = BitmapFactory.decodeFile(iconPath) 48 | itemView.itemIcon.setImageDrawable( 49 | BitmapDrawable( 50 | itemView.context.resources, 51 | iconBitmap 52 | ) 53 | ) 54 | } else { 55 | itemView.itemIcon.setImageResource(R.drawable.ic_list_generic) 56 | } 57 | itemView.itemCard.cardElevation = 1F 58 | itemView.itemCard.setOnClickListener { itemClick(this) } 59 | } 60 | } 61 | } 62 | 63 | fun updateData(historyItems: List) { 64 | this.historyItems = historyItems 65 | notifyDataSetChanged() 66 | } 67 | 68 | override fun onCreateViewHolder( 69 | parent: ViewGroup, 70 | viewType: Int 71 | ): ViewHolder { 72 | val view = LayoutInflater.from(parent.context) 73 | .inflate(R.layout.layout_app_list_item, parent, false) 74 | return ViewHolder(view, itemClick) 75 | } 76 | 77 | override fun onBindViewHolder(holder: HistoryListAdapter.ViewHolder, position: Int) { 78 | holder.bindSourceInfo(historyItems[position]) 79 | } 80 | 81 | override fun getItemCount(): Int { 82 | return historyItems.size 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/purchase/PurchaseActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.purchase 20 | 21 | import android.content.Intent 22 | import android.os.Bundle 23 | import android.view.View 24 | import android.widget.Toast 25 | import com.google.firebase.analytics.FirebaseAnalytics 26 | import com.njlabs.showjava.R 27 | import com.njlabs.showjava.activities.BaseActivity 28 | import com.njlabs.showjava.utils.secure.PurchaseUtils 29 | import kotlinx.android.synthetic.main.activity_purchase.* 30 | import org.solovyev.android.checkout.* 31 | import timber.log.Timber 32 | 33 | 34 | class PurchaseActivity : BaseActivity() { 35 | 36 | private lateinit var purchaseUtils: PurchaseUtils 37 | 38 | private fun isLoading(loading: Boolean) { 39 | buttonProgressBar.visibility = if (!loading) View.GONE else View.VISIBLE 40 | buyButton.visibility = if (loading) View.GONE else View.VISIBLE 41 | } 42 | 43 | override fun init(savedInstanceState: Bundle?) { 44 | setupLayout(R.layout.activity_purchase, getString(R.string.appNameGetPro)) 45 | Timber.d("[pa] init") 46 | 47 | secureUtils.isSafeExtended( 48 | { // allow 49 | runOnUiThread { 50 | isLoading(false) 51 | purchaseUtils = PurchaseUtils(this, secureUtils) { 52 | isLoading(it) 53 | } 54 | purchaseUtils.doOnComplete { 55 | finish() 56 | } 57 | purchaseUtils.initializeCheckout(true) 58 | buyButton.setOnClickListener { 59 | isLoading(true) 60 | makePurchase() 61 | } 62 | } 63 | }, 64 | { err, app ->// Do not allow 65 | runOnUiThread { 66 | isLoading(false) 67 | buyButton.visibility = View.GONE 68 | if (app != null) { 69 | Toast.makeText( 70 | context, 71 | getString(R.string.deviceVerificationFailedPirateApp, "${app.name} (${app.packageName})"), 72 | Toast.LENGTH_LONG 73 | ).show() 74 | } else { 75 | Toast.makeText( 76 | context, 77 | getString(R.string.deviceVerificationFailed, err.name), 78 | Toast.LENGTH_SHORT 79 | ).show() 80 | } 81 | } 82 | }, 83 | { // On Error 84 | runOnUiThread { 85 | isLoading(false) 86 | buyButton.visibility = View.GONE 87 | Toast.makeText(context, R.string.purchaseInitError, Toast.LENGTH_SHORT).show() 88 | } 89 | } 90 | ) 91 | 92 | Timber.d("[pa] initComplete") 93 | 94 | } 95 | 96 | private fun makePurchase() { 97 | firebaseAnalytics.logEvent(FirebaseAnalytics.Event.BEGIN_CHECKOUT, null) 98 | purchaseUtils.checkout.whenReady(object : Checkout.EmptyListener() { 99 | override fun onReady(requests: BillingRequests) { 100 | firebaseAnalytics.logEvent(FirebaseAnalytics.Event.CHECKOUT_PROGRESS, null) 101 | requests.purchase( 102 | ProductTypes.IN_APP, 103 | secureUtils.iapProductId, 104 | null, 105 | purchaseUtils.checkout.purchaseFlow 106 | ) 107 | } 108 | }) 109 | } 110 | 111 | override fun onDestroy() { 112 | if (::purchaseUtils.isInitialized) { 113 | purchaseUtils.onDestroy() 114 | } 115 | super.onDestroy() 116 | } 117 | 118 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 119 | super.onActivityResult(requestCode, resultCode, data) 120 | if (::purchaseUtils.isInitialized) { 121 | purchaseUtils.checkout.onActivityResult(requestCode, resultCode, data) 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/activities/settings/SettingsHandler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.activities.settings 20 | 21 | import android.content.Context 22 | import com.njlabs.showjava.utils.ktx.appStorage 23 | import io.reactivex.Observable 24 | 25 | class SettingsHandler(private var context: Context) { 26 | 27 | /** 28 | * Delete all decompiled sources recursively 29 | */ 30 | fun deleteHistory(): Observable { 31 | return Observable.fromCallable { 32 | appStorage.resolve("sources") 33 | .deleteRecursively() 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/data/FileItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.data 20 | 21 | import android.os.Parcel 22 | import android.os.Parcelable 23 | import com.njlabs.showjava.R 24 | import org.apache.commons.io.FilenameUtils 25 | import java.io.File 26 | 27 | /** 28 | * Each file/folder item displayed in [com.njlabs.showjava.activities.explorer.navigator.NavigatorActivity] 29 | */ 30 | class FileItem() : Parcelable { 31 | 32 | var file: File = File("/") 33 | var fileSize: String = "" 34 | var metaInfo: String? = "" 35 | 36 | val name: String? 37 | get() = if (metaInfo == "parent") ".." else file.name 38 | 39 | /** 40 | * Returns the appropriate icon resource based on the file extension via reflection 41 | */ 42 | val iconResource: Int 43 | get() { 44 | if (metaInfo == "parent") { 45 | return R.drawable.previous 46 | } 47 | if (file.isDirectory) { 48 | return R.drawable.type_folder 49 | } 50 | var extension = FilenameUtils.getExtension(file.name) ?: return R.drawable.type_file 51 | extension = if (extension === "jpeg") "jpg" else extension 52 | return try { 53 | val res = R.drawable::class.java 54 | val drawableField = res.getField("type_$extension") 55 | drawableField.getInt(null) 56 | } catch (e: Exception) { 57 | R.drawable.type_file 58 | } 59 | } 60 | 61 | 62 | constructor(parcel: Parcel) : this() { 63 | file = File(parcel.readString()) 64 | fileSize = parcel.readString() as String 65 | metaInfo = parcel.readString() as String 66 | } 67 | 68 | constructor(file: File, fileSize: String, metaInfo: String) : this() { 69 | this.file = file 70 | this.fileSize = fileSize 71 | this.metaInfo = metaInfo 72 | } 73 | 74 | override fun writeToParcel(parcel: Parcel, flags: Int) { 75 | parcel.writeString(file.canonicalPath) 76 | parcel.writeString(fileSize) 77 | parcel.writeString(metaInfo) 78 | } 79 | 80 | override fun describeContents(): Int { 81 | return 0 82 | } 83 | 84 | companion object CREATOR : Parcelable.Creator { 85 | override fun createFromParcel(parcel: Parcel): FileItem { 86 | return FileItem(parcel) 87 | } 88 | 89 | override fun newArray(size: Int): Array { 90 | return arrayOfNulls(size) 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/receivers/DecompilerActionReceiver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.receivers 20 | 21 | import android.content.BroadcastReceiver 22 | import android.content.Context 23 | import android.content.Intent 24 | import com.njlabs.showjava.Constants 25 | import com.njlabs.showjava.workers.DecompilerWorker 26 | import timber.log.Timber 27 | 28 | /** 29 | * [DecompilerActionReceiver] is used to receive the cancel request from the notification action, 30 | * and cancel the decompilation process. 31 | */ 32 | class DecompilerActionReceiver : BroadcastReceiver() { 33 | 34 | override fun onReceive(context: Context?, intent: Intent?) { 35 | when (intent?.action) { 36 | Constants.WORKER.ACTION.STOP -> { 37 | val id = intent.getStringExtra("id") 38 | Timber.d("[cancel-request] ID: $id") 39 | context?.let { 40 | DecompilerWorker.cancel(it, id) 41 | } 42 | } 43 | else -> { 44 | Timber.i("Received an unknown action.") 45 | } 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/Ads.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils 20 | 21 | import android.annotation.SuppressLint 22 | import android.app.Activity 23 | import android.content.Context 24 | import android.content.Intent 25 | import android.content.SharedPreferences 26 | import com.google.ads.consent.* 27 | import com.google.android.gms.ads.MobileAds 28 | import com.njlabs.showjava.R 29 | import com.njlabs.showjava.activities.purchase.PurchaseActivity 30 | import timber.log.Timber 31 | import java.net.URL 32 | 33 | /** 34 | * Initialize the ads library. Also, takes care of showing a consent screen for users within EU 35 | * and persisting the consent. 36 | */ 37 | class Ads(val context: Context) { 38 | private val consentInformation: ConsentInformation = ConsentInformation.getInstance(context) 39 | private lateinit var consentForm: ConsentForm 40 | 41 | fun getPreferences(): SharedPreferences { 42 | return context.getSharedPreferences(UserPreferences.NAME, Context.MODE_PRIVATE) 43 | } 44 | 45 | @SuppressLint("ApplySharedPref") 46 | fun init() { 47 | MobileAds.initialize(context, context.getString(R.string.admobAppId)) 48 | val publisherIds = arrayOf(context.getString(R.string.admobPublisherId)) 49 | consentInformation.requestConsentInfoUpdate( 50 | publisherIds, 51 | object : ConsentInfoUpdateListener { 52 | override fun onConsentInfoUpdated(consentStatus: ConsentStatus) { 53 | getPreferences().edit() 54 | .putInt("consentStatus", consentStatus.ordinal) 55 | .commit() 56 | } 57 | override fun onFailedToUpdateConsentInfo(errorDescription: String) { 58 | getPreferences().edit() 59 | .putInt("consentStatus", ConsentStatus.UNKNOWN.ordinal) 60 | .commit() 61 | } 62 | }) 63 | } 64 | 65 | /** 66 | * Load the consent screen and prepare to display. 67 | */ 68 | fun loadConsentScreen(): ConsentForm? { 69 | consentForm = ConsentForm.Builder(context, URL(context.getString(R.string.privacyPolicyUrl))) 70 | .withListener(object : ConsentFormListener() { 71 | override fun onConsentFormLoaded() { 72 | if (context is Activity && !context.isFinishing) { 73 | consentForm.show() 74 | } 75 | } 76 | 77 | override fun onConsentFormOpened() { 78 | Timber.d("[consent-screen] onConsentFormOpened") 79 | } 80 | 81 | override fun onConsentFormClosed(consentStatus: ConsentStatus?, userPrefersAdFree: Boolean?) { 82 | consentStatus?.let { 83 | ConsentInformation.getInstance(context).consentStatus = it 84 | getPreferences().edit().putInt("consentStatus", consentStatus.ordinal).apply() 85 | } 86 | if (userPrefersAdFree != null && userPrefersAdFree) { 87 | context.startActivity(Intent(context, PurchaseActivity::class.java)) 88 | } 89 | } 90 | 91 | override fun onConsentFormError(errorDescription: String?) { 92 | Timber.d("[consent-screen] onConsentFormError: $errorDescription") 93 | } 94 | }) 95 | .withPersonalizedAdsOption() 96 | .withNonPersonalizedAdsOption() 97 | .withAdFreeOption() 98 | .build() 99 | consentForm.load() 100 | return consentForm 101 | } 102 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/RequestQueue.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils 20 | 21 | import android.content.Context 22 | import com.android.volley.Request 23 | import com.android.volley.RequestQueue as VolleyRequestQueue 24 | import com.android.volley.toolbox.Volley 25 | 26 | /** 27 | * A singleton request queue to use with Volley for all network requests. 28 | */ 29 | class RequestQueue constructor(context: Context) { 30 | companion object { 31 | @Volatile 32 | private var INSTANCE: RequestQueue? = null 33 | fun getInstance(context: Context) = 34 | INSTANCE ?: synchronized(this) { 35 | INSTANCE ?: RequestQueue(context).also { 36 | INSTANCE = it 37 | } 38 | } 39 | } 40 | private val requestQueue: VolleyRequestQueue by lazy { 41 | // applicationContext is key, it keeps you from leaking the 42 | // Activity or BroadcastReceiver if someone passes one in. 43 | Volley.newRequestQueue(context.applicationContext) 44 | } 45 | fun addToRequestQueue(req: Request) { 46 | requestQueue.add(req) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/SingletonHolder.kt: -------------------------------------------------------------------------------- 1 | package com.njlabs.showjava.utils 2 | 3 | /* 4 | * Code borrowed from https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e 5 | * Copyright (C) 2018 Christophe Beyls 6 | */ 7 | open class SingletonHolder(creator: (A) -> T) { 8 | private var creator: ((A) -> T)? = creator 9 | @Volatile private var instance: T? = null 10 | 11 | fun getInstance(arg: A): T { 12 | val i = instance 13 | if (i != null) { 14 | return i 15 | } 16 | return synchronized(this) { 17 | val i2 = instance 18 | if (i2 != null) { 19 | i2 20 | } else { 21 | val created = creator!!(arg) 22 | instance = created 23 | creator = null 24 | created 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/UserPreferences.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils 20 | 21 | import android.content.SharedPreferences 22 | import com.google.ads.consent.ConsentStatus 23 | 24 | /** 25 | * A thin-wrapper around [SharedPreferences] to expose preferences as getters. 26 | */ 27 | class UserPreferences(private val prefs: SharedPreferences) { 28 | 29 | companion object { 30 | const val NAME = "user_preferences" 31 | } 32 | 33 | interface DEFAULTS { 34 | companion object { 35 | const val CUSTOM_FONT = true 36 | const val DARK_MODE = false 37 | const val SHOW_MEMORY_USAGE = true 38 | const val SHOW_SYSTEM_APPS = false 39 | const val MEMORY_THRESHOLD = 80 40 | const val IGNORE_LIBRARIES = true 41 | const val KEEP_INTERMEDIATE_FILES = false 42 | const val CHUNK_SIZE = 500 43 | const val MAX_ATTEMPTS = 2 44 | } 45 | } 46 | 47 | val ignoreLibraries: Boolean 48 | get() = prefs.getBoolean("ignoreLibraries", DEFAULTS.IGNORE_LIBRARIES) 49 | 50 | val keepIntermediateFiles: Boolean 51 | get() = prefs.getBoolean("keepIntermediateFiles", DEFAULTS.KEEP_INTERMEDIATE_FILES) 52 | 53 | val customFont: Boolean 54 | get() = prefs.getBoolean("customFont", DEFAULTS.CUSTOM_FONT) 55 | 56 | val darkMode: Boolean 57 | get() = prefs.getBoolean("darkMode", DEFAULTS.DARK_MODE) 58 | 59 | val showMemoryUsage: Boolean 60 | get() = prefs.getBoolean("showMemoryUsage", DEFAULTS.SHOW_MEMORY_USAGE) 61 | 62 | val showSystemApps: Boolean 63 | get() = prefs.getBoolean("showSystemApps", DEFAULTS.SHOW_SYSTEM_APPS) 64 | 65 | val chunkSize: Int 66 | get() = try { 67 | prefs.getString("chunkSize", DEFAULTS.CHUNK_SIZE.toString())?.trim()?.toInt() 68 | ?: DEFAULTS.CHUNK_SIZE 69 | } catch (ignored: Exception) { 70 | DEFAULTS.CHUNK_SIZE 71 | } 72 | 73 | val maxAttempts: Int 74 | get() = try { 75 | prefs.getString("maxAttempts", DEFAULTS.MAX_ATTEMPTS.toString())?.trim()?.toInt() 76 | ?: DEFAULTS.MAX_ATTEMPTS 77 | } catch (ignored: Exception) { 78 | DEFAULTS.MAX_ATTEMPTS 79 | } 80 | 81 | val memoryThreshold: Int 82 | get() = try { 83 | prefs.getString( 84 | "memoryThreshold", 85 | DEFAULTS.MEMORY_THRESHOLD.toString() 86 | )?.trim()?.toInt() 87 | ?: DEFAULTS.MEMORY_THRESHOLD 88 | } catch (ignored: Exception) { 89 | DEFAULTS.MEMORY_THRESHOLD 90 | } 91 | 92 | val consentStatus: Int 93 | get() = prefs.getInt("consentStatus", ConsentStatus.UNKNOWN.ordinal) 94 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/ZipUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils 20 | 21 | 22 | import com.njlabs.showjava.utils.ktx.appStorage 23 | import timber.log.Timber 24 | import java.io.* 25 | import java.util.zip.ZipEntry 26 | import java.util.zip.ZipInputStream 27 | import java.util.zip.ZipOutputStream 28 | 29 | /** 30 | * [ZipUtils] to extract and compress directories 31 | */ 32 | object ZipUtils { 33 | 34 | fun zipDir(dir: File, packageId: String): File { 35 | val zipIntoDir = appStorage.resolve("archives") 36 | if (!zipIntoDir.exists() || !zipIntoDir.isDirectory) { 37 | zipIntoDir.mkdirs() 38 | } 39 | val zipFile = File(zipIntoDir, "$packageId.zip") 40 | if (zipFile.exists()) { 41 | zipFile.delete() 42 | } 43 | try { 44 | val zip: ZipOutputStream 45 | val fileWriter = FileOutputStream(zipFile) 46 | zip = ZipOutputStream(fileWriter) 47 | addFolderToZip("", dir.toString(), zip) 48 | zip.flush() 49 | zip.close() 50 | } catch (e: Exception) { 51 | Timber.e(e) 52 | } 53 | 54 | return zipFile 55 | } 56 | 57 | @Throws(Exception::class) 58 | private fun addFileToZip(path: String, srcFile: String, zip: ZipOutputStream) { 59 | val folder = File(srcFile) 60 | if (folder.isDirectory) { 61 | addFolderToZip(path, srcFile, zip) 62 | } else { 63 | val buffer = ByteArray(1024) 64 | val fileInputStream = FileInputStream(srcFile) 65 | zip.putNextEntry(ZipEntry(path + "/" + folder.name)) 66 | 67 | while (true) { 68 | val len = fileInputStream.read(buffer) 69 | if (len <= 0) { 70 | break 71 | } 72 | zip.write(buffer, 0, len) 73 | } 74 | } 75 | } 76 | 77 | @Throws(Exception::class) 78 | private fun addFolderToZip(path: String, srcFolder: String, zip: ZipOutputStream) { 79 | val folder = File(srcFolder) 80 | for (fileName in folder.list()) { 81 | if (path == "") { 82 | addFileToZip(folder.name, "$srcFolder/$fileName", zip) 83 | } else { 84 | addFileToZip(path + "/" + folder.name, "$srcFolder/$fileName", zip) 85 | } 86 | } 87 | } 88 | 89 | @Throws(IOException::class) 90 | @JvmOverloads 91 | fun unzip(zipFile: File, targetDirectory: File, printStream: PrintStream = System.out) { 92 | val zipInputStream = ZipInputStream(BufferedInputStream(FileInputStream(zipFile))) 93 | zipInputStream.use { zis -> 94 | val buffer = ByteArray(8192) 95 | while (true) { 96 | val zipEntry = zis.nextEntry ?: break 97 | val file = File(targetDirectory, zipEntry.name) 98 | printStream.println(zipEntry.name) 99 | val dir = if (zipEntry.isDirectory) file else file.parentFile 100 | if (!dir.isDirectory && !dir.mkdirs()) { 101 | throw FileNotFoundException("Failed to ensure directory: " + dir.canonicalPath) 102 | } 103 | 104 | if (zipEntry.isDirectory) { 105 | continue 106 | } 107 | 108 | val fileOutputStream = FileOutputStream(file) 109 | fileOutputStream.use { out -> 110 | while (true) { 111 | val count = zis.read(buffer) 112 | if (count <= 0) { 113 | break 114 | } 115 | out.write(buffer, 0, count) 116 | } 117 | } 118 | val time = zipEntry.time 119 | if (time > 0) { 120 | file.setLastModified(time) 121 | } 122 | } 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/ktx/Extensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.ktx 20 | 21 | import android.graphics.Bitmap 22 | import android.graphics.Paint 23 | import android.graphics.Canvas 24 | import android.graphics.Rect 25 | import android.graphics.PorterDuff 26 | import android.graphics.PorterDuffXfermode 27 | import android.os.Build 28 | import android.os.Bundle 29 | import android.os.IBinder 30 | import android.os.Parcelable 31 | import java.io.File 32 | import java.io.InputStream 33 | import java.io.Serializable 34 | 35 | /** 36 | * Convert an [InputStream] to a file given a path as a [String] 37 | */ 38 | fun InputStream.toFile(path: String) { 39 | toFile(File(path)) 40 | } 41 | 42 | /** 43 | * Convert an [InputStream] to a file given the destination [File] 44 | */ 45 | fun InputStream.toFile(file: File) { 46 | file.outputStream().use { this.copyTo(it) } 47 | } 48 | 49 | /** 50 | * Convert a [Map] to a bundle by iterating through the map entries 51 | */ 52 | fun Map.toBundle(bundle: Bundle = Bundle()): Bundle = bundle.apply { 53 | forEach { 54 | val k = it.key 55 | val v = it.value 56 | when (v) { 57 | is IBinder -> { 58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 59 | putBinder(k, v) 60 | } 61 | } 62 | is Bundle -> putBundle(k, v) 63 | is Byte -> putByte(k, v) 64 | is ByteArray -> putByteArray(k, v) 65 | is String -> putString(k, v) 66 | is Char -> putChar(k, v) 67 | is CharArray -> putCharArray(k, v) 68 | is CharSequence -> putCharSequence(k, v) 69 | is Float -> putFloat(k, v) 70 | is FloatArray -> putFloatArray(k, v) 71 | is Parcelable -> putParcelable(k, v) 72 | is Serializable -> putSerializable(k, v) 73 | is Short -> putShort(k, v) 74 | is ShortArray -> putShortArray(k, v) 75 | is Boolean -> putBoolean(k, v) 76 | is Int -> putInt(k, v) 77 | is IntArray -> putIntArray(k, v) 78 | } 79 | } 80 | } 81 | 82 | /** 83 | * Get a circular [Bitmap] from the original 84 | * 85 | * Borrowed from: https://stackoverflow.com/a/46613094/1562480 (Yuriy Seredyuk) 86 | */ 87 | fun Bitmap.getCircularBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap { 88 | // circle configuration 89 | val circlePaint = Paint().apply { isAntiAlias = true } 90 | val circleRadius = Math.max(width, height) / 2f 91 | 92 | // output bitmap 93 | val outputBitmapPaint = Paint(circlePaint).apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) } 94 | val outputBounds = Rect(0, 0, width, height) 95 | val output = Bitmap.createBitmap(width, height, config) 96 | 97 | return Canvas(output).run { 98 | drawCircle(circleRadius, circleRadius, circleRadius, circlePaint) 99 | drawBitmap(this@getCircularBitmap, outputBounds, outputBounds, outputBitmapPaint) 100 | output 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/ktx/PackageSourceTools.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.ktx 20 | 21 | import android.content.pm.ApplicationInfo 22 | import android.content.pm.PackageInfo 23 | import android.os.Environment 24 | import java.io.File 25 | 26 | /** 27 | * Path to the priamry storage directory on the user's internal memory 28 | */ 29 | val appStorage: File = File(Environment.getExternalStorageDirectory(), "show-java") 30 | 31 | /** 32 | * Check if the given packageInfo points to a system application 33 | */ 34 | fun isSystemPackage(pkgInfo: PackageInfo): Boolean { 35 | return pkgInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0 36 | } 37 | 38 | /** 39 | * Get the source directory for a given package name 40 | */ 41 | fun sourceDir(packageName: String): File { 42 | return appStorage.resolve("sources/$packageName") 43 | } 44 | 45 | /** 46 | * Convert an arbitrary file name into a generated package name that we can use 47 | */ 48 | fun jarPackageName(jarFileName: String): String { 49 | val slug = toSlug(jarFileName) 50 | return "$slug-${hashString("SHA-1", slug).slice(0..7)}".toLowerCase() 51 | } -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/ktx/Tools.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.ktx 20 | 21 | import android.content.Context 22 | import android.content.pm.PackageInfo 23 | import android.net.ConnectivityManager 24 | import android.os.Build 25 | import java.security.MessageDigest 26 | import java.text.Normalizer 27 | import java.text.SimpleDateFormat 28 | import java.util.* 29 | import java.util.regex.Pattern 30 | 31 | private val NON_LATIN = Pattern.compile("[^\\w-]") 32 | private val WHITESPACE = Pattern.compile("[\\s]") 33 | 34 | /** 35 | * Convert a [packageName] in dot.notation to a class reference (Eg. Lclass/reference) 36 | */ 37 | fun toClassName(packageName: String): String { 38 | return "L" + packageName.trim().replace(".", "/") 39 | } 40 | 41 | /** 42 | * Convert the [input] to a slug. 43 | */ 44 | fun toSlug(input: String): String { 45 | val noWhiteSpace = WHITESPACE.matcher(input).replaceAll("-") 46 | val normalized = Normalizer.normalize(noWhiteSpace, Normalizer.Form.NFD) 47 | val slug = NON_LATIN.matcher(normalized).replaceAll("") 48 | return slug.toLowerCase(Locale.ENGLISH) 49 | } 50 | 51 | /** 52 | * Hash the given [input] string using the specified [algorithm] 53 | */ 54 | fun hashString(algorithm: String, input: String): String { 55 | val hexChars = "0123456789ABCDEF" 56 | val bytes = MessageDigest 57 | .getInstance(algorithm) 58 | .digest(input.toByteArray()) 59 | val result = StringBuilder(bytes.size * 2) 60 | bytes.forEach { 61 | val i = it.toInt() 62 | result.append(hexChars[i shr 4 and 0x0f]) 63 | result.append(hexChars[i and 0x0f]) 64 | } 65 | return result.toString() 66 | } 67 | 68 | /** 69 | * Check if the device is connected to a network. 70 | */ 71 | fun checkDataConnection(context: Context): Boolean { 72 | val connectivityMgr = 73 | context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 74 | return (connectivityMgr.activeNetworkInfo != null && 75 | connectivityMgr.activeNetworkInfo.isAvailable && 76 | connectivityMgr.activeNetworkInfo.isConnected) 77 | } 78 | 79 | /** 80 | * Get the current date as ISO 8601 [String] 81 | */ 82 | fun getDate(): String { 83 | val date = Date(System.currentTimeMillis()) 84 | val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) 85 | formatter.timeZone = TimeZone.getTimeZone("UTC") 86 | return formatter.format(date) 87 | } 88 | 89 | /** 90 | * Request JVM to run the garbage collector. 91 | * Don't think this would do much good. But okay. 92 | */ 93 | fun cleanMemory() { 94 | Runtime.getRuntime().gc() 95 | Thread.sleep(500) 96 | } 97 | 98 | /** 99 | * Get either version name or version code form [packageInfo]. 100 | */ 101 | fun getVersion(packageInfo: PackageInfo): String { 102 | return if (packageInfo.versionName != null) 103 | packageInfo.versionName 104 | else 105 | getVersionCode(packageInfo).toString() 106 | } 107 | 108 | /** 109 | * Get version code from [packageInfo] using the correct method depending on Android version. 110 | */ 111 | fun getVersionCode(packageInfo: PackageInfo): Number { 112 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) 113 | packageInfo.longVersionCode 114 | else 115 | packageInfo.versionCode 116 | } 117 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/logging/ProductionTree.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.logging 20 | 21 | import android.util.Log 22 | import com.crashlytics.android.Crashlytics 23 | import timber.log.Timber 24 | 25 | /** 26 | * Logs all exceptions and anything with priority higher than [Log.WARN] to [Crashlytics] and ignores 27 | * the rest. 28 | */ 29 | class ProductionTree : Timber.Tree() { 30 | override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { 31 | if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) { 32 | return 33 | } 34 | 35 | if (t !== null && t !is OutOfMemoryError && t !is StackOverflowError && t !is NoClassDefFoundError) { 36 | if (message.isNotEmpty()) { 37 | Crashlytics.log("[$tag] $message") 38 | } 39 | Crashlytics.logException(t) 40 | return 41 | } 42 | 43 | if (priority > Log.WARN) { 44 | Crashlytics.logException(Throwable("[$tag] $message")) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/rx/ProcessStatus.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.rx 20 | 21 | class ProcessStatus { 22 | 23 | val status: String? 24 | val secondaryStatus: String? 25 | val progress: Float 26 | val result: T? 27 | 28 | constructor(progress: Float, status: String, secondaryStatus: String) { 29 | this.progress = progress 30 | this.result = null 31 | this.status = status 32 | this.secondaryStatus = secondaryStatus 33 | } 34 | 35 | constructor(progress: Float, status: String) { 36 | this.progress = progress 37 | this.result = null 38 | this.status = status 39 | this.secondaryStatus = "" 40 | } 41 | 42 | constructor(result: T) { 43 | this.progress = 1f 44 | this.status = "" 45 | this.secondaryStatus = "" 46 | this.result = result 47 | } 48 | 49 | val isDone: Boolean 50 | get() = result != null 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/streams/Logger.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.streams 20 | 21 | import jadx.api.JadxArgs 22 | import jadx.core.dex.nodes.ClassNode 23 | import java.io.File 24 | 25 | 26 | object Logger { 27 | 28 | /** 29 | * This method will be invoked by a JaDX method that is used to save classes. 30 | */ 31 | @Suppress("UNUSED_PARAMETER") 32 | @JvmStatic 33 | fun logJadxClassWrite(dir: File, args: JadxArgs, cls: ClassNode) { 34 | println("Decompiling " + cls.fullName) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/kotlin/com/njlabs/showjava/utils/streams/ProgressStream.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava.utils.streams 20 | 21 | import androidx.annotation.NonNull 22 | import com.njlabs.showjava.decompilers.BaseDecompiler 23 | import timber.log.Timber 24 | import java.io.OutputStream 25 | import java.nio.charset.Charset 26 | import java.util.Arrays 27 | 28 | 29 | /** 30 | * A custom output stream that strips unnecessary stuff from raw input stream 31 | */ 32 | class ProgressStream(val decompiler: BaseDecompiler) : OutputStream() { 33 | 34 | private val validProgressRegex = Regex("^[^.][a-zA-Z/\$;\\s0-9.]+\$") 35 | 36 | private fun shouldIgnore(string: String): Boolean { 37 | if (string.startsWith("[ignored]")) { 38 | return true 39 | } 40 | for (part in arrayOf( 41 | "TRYBLOCK", "stack info", "Produces", "ASTORE", "targets", 42 | "WARN jadx", "thread-1", "ERROR jadx", "JadxRuntimeException", 43 | "java.lang")) { 44 | if (string.contains(part, true)) { 45 | return true 46 | } 47 | } 48 | 49 | return !validProgressRegex.matches(string) 50 | } 51 | 52 | override fun write(@NonNull data: ByteArray, offset: Int, length: Int) { 53 | var str = String( 54 | Arrays.copyOfRange(data, offset, length), 55 | Charset.forName("UTF-8") 56 | ) 57 | .replace("\n", "") 58 | .replace("\r", "") 59 | .replace("INFO:".toRegex(RegexOption.IGNORE_CASE), "") 60 | .replace("ERROR:".toRegex(RegexOption.IGNORE_CASE), "") 61 | .replace("WARN:".toRegex(RegexOption.IGNORE_CASE), "") 62 | .replace("\n\r", "") 63 | .replace("... done", "") 64 | .replace("at", "") 65 | .replace("Processing ".toRegex(RegexOption.IGNORE_CASE), "") 66 | .replace("Decompiling ".toRegex(RegexOption.IGNORE_CASE), "") 67 | .replace("Extracting ".toRegex(RegexOption.IGNORE_CASE), "") 68 | .trim() 69 | 70 | if (shouldIgnore(str)) { 71 | return 72 | } 73 | 74 | if (str.startsWith("[stdout]")) { 75 | str = str.removePrefix("[stdout] ") 76 | } 77 | 78 | if (str.isNotEmpty()) { 79 | Timber.d("[stdout] %s", str) 80 | decompiler.sendStatus(str) 81 | } 82 | } 83 | 84 | override fun write(byte: Int) { 85 | // Just a stub. We aren't implementing this. 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_list_generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-hdpi/ic_list_generic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_stat_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-hdpi/ic_stat_code.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_stat_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-hdpi/ic_stat_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_stat_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-hdpi/ic_stat_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/sad_ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-hdpi/sad_ram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_list_generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-mdpi/ic_list_generic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_stat_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-mdpi/ic_stat_code.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_stat_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-mdpi/ic_stat_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_stat_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-mdpi/ic_stat_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/sad_ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-mdpi/sad_ram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_list_generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xhdpi/ic_list_generic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_stat_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xhdpi/ic_stat_code.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_stat_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xhdpi/ic_stat_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_stat_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xhdpi/ic_stat_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/sad_ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xhdpi/sad_ram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_list_generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxhdpi/ic_list_generic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_stat_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxhdpi/ic_stat_code.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_stat_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxhdpi/ic_stat_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_stat_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxhdpi/ic_stat_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sad_ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxhdpi/sad_ram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_stat_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxxhdpi/ic_stat_code.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_stat_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxxhdpi/ic_stat_error.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_stat_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxxhdpi/ic_stat_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/sad_ram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable-xxxhdpi/sad_ram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_label.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_apps_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bug_report_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_code_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_code_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_white.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error_outline_black.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_gear_grey.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_invert_colors_white.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sd_card_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_black.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share_white.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_stop_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_whatshot_black.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/navbar_header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/navbar_header.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/previous.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/showjava_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/showjava_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_css.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_file.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_folder.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_html.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_jar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_jar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_java.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_javascript.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_jpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_jpg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_json.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_png.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_txt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_txt.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_xml.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/type_zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/drawable/type_zip.png -------------------------------------------------------------------------------- /app/src/main/res/font/lato.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 24 | 28 | 29 | 33 | 37 | 38 | 42 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/font/lato_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/font/lato_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/lato_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/font/lato_light.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/lato_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/font/lato_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/action_layout_checkbox.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 13 | 22 | 23 | 30 | 31 | 38 | 39 | 46 | 47 | 55 | 56 | 66 | 67 | 68 | 69 | 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_apps.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 29 | 30 | 33 | 34 | 42 | 43 | 53 | 54 | 58 | 59 | 71 | 72 | 73 | 74 | 85 | 86 | 93 | 94 | 101 | 102 | 103 | 110 | 111 | 112 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_code_viewer.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 24 | 25 | 28 | 29 | 36 | 37 | 38 | 45 | 46 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_image_viewer.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 24 | 25 | 28 | 29 | 35 | 36 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_low_memory.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 29 | 30 | 39 | 40 | 41 | 46 | 47 | 54 | 55 | 65 | 66 | 78 | 79 | 85 | 86 | 87 | 88 | 91 | 92 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 33 | 34 | 37 | 38 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_purchase.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 24 | 25 | 28 | 29 | 38 | 39 | 40 | 48 | 49 | 55 | 56 | 63 | 64 | 71 | 72 | 79 | 80 | 88 | 89 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 27 | 28 | 30 | 31 | 39 | 40 | 48 | 49 | 50 | 51 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_admob.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_app_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 37 | 38 | 43 | 44 | 51 | 52 | 59 | 60 | 68 | 69 | 76 | 77 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_drawer_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 29 | 30 | 40 | 41 | 54 | 55 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_pick_decompiler_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 25 | 26 | 37 | 44 | 45 | 53 | 54 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_app.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 22 | 29 | 30 | 35 | 36 | 41 | 42 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_fab.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 22 | 27 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 23 | 24 | 26 | 27 | 35 | 36 | 44 | 45 | 46 | 48 | 49 | 57 | 66 | 67 | 76 | 77 | 86 | 87 | 88 | 90 | 96 | 97 | 103 | 104 | 110 | 111 | 112 | 113 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_logo_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-hdpi/ic_logo_plain.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_logo_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-mdpi/ic_logo_plain.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_logo_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xhdpi/ic_logo_plain.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_logo_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxhdpi/ic_logo_plain.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_logo_plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/app/src/main/res/mipmap-xxxhdpi/ic_logo_plain.png -------------------------------------------------------------------------------- /app/src/main/res/transition/default_window_fade.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/values-sw360dp-v13/values-preference.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | false 23 | 0dp 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 29 | 30 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | @drawable/fab_label 23 | @drawable/fab_label 24 | @drawable/fab_label 25 | @drawable/fab_label 26 | @drawable/fab_label 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | #3F51B5 22 | #303F9F 23 | #D32F2F 24 | 25 | @color/white 26 | 27 | #000000 28 | #212121 29 | #616161 30 | #BDBDBD 31 | 32 | #4CAF50 33 | #FFC107 34 | #FF9800 35 | #F44336 36 | 37 | #ffffff 38 | #22d32f2f 39 | #282b2e 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 16dp 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | 32 | 33 | 37 | 38 | 40 | 41 | 47 | 48 | 51 | 52 | 61 | 62 | 64 | 65 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/res/xml/file_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/xml/searchable.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/test/kotlin/com/njlabs/showjava/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package com.njlabs.showjava 20 | 21 | import org.junit.Assert.assertEquals 22 | import org.junit.Test 23 | 24 | /** 25 | * Example local unit test, which will execute on the development machine (host). 26 | 27 | * @see [Testing documentation](http://d.android.com/tools/testing) 28 | */ 29 | class ExampleUnitTest { 30 | @Test 31 | @Throws(Exception::class) 32 | fun additionIsCorrect() { 33 | assertEquals(4, (2 + 2).toLong()) 34 | } 35 | } -------------------------------------------------------------------------------- /app/test-proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Proguard rules that are applied to your test apk/code. 2 | -ignorewarnings 3 | 4 | -keepattributes *Annotation* 5 | 6 | -dontnote junit.framework.** 7 | -dontnote junit.runner.** 8 | 9 | -keep class androidx.test.** 10 | -keep class androidx.test.** { *; } 11 | -keep class com.njlabs.showjava.** { *; } 12 | -keep class com.android.dex.** { *; } 13 | 14 | -dontwarn androidx.test.** 15 | -dontwarn androidx.** 16 | -dontwarn android.support.test.** 17 | -dontwarn org.junit.** 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 20 | 21 | buildscript { 22 | 23 | ext.kotlin_version = '1.3.31' 24 | 25 | repositories { 26 | google() 27 | jcenter() 28 | maven { url "https://maven.fabric.io/public" } 29 | } 30 | dependencies { 31 | classpath 'com.android.tools.build:gradle:3.5.0-beta04' 32 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 33 | classpath "com.google.gms:google-services:4.2.0" 34 | classpath "io.fabric.tools:gradle:1.27.1" 35 | classpath "com.bryansharp:hibeaver:1.2.7" 36 | classpath "io.michaelrocks:paranoid-gradle-plugin:0.2.4" 37 | classpath "com.google.android.gms:oss-licenses-plugin:0.9.5" 38 | classpath "ru.tinkoff.gradle:jarjar:1.1.0" 39 | } 40 | } 41 | 42 | plugins { 43 | id "com.github.ben-manes.versions" version "0.21.0" 44 | } 45 | 46 | 47 | allprojects { 48 | repositories { 49 | google() 50 | jcenter() 51 | maven { url "https://jitpack.io" } 52 | maven { url "https://maven.google.com/" } 53 | } 54 | } 55 | 56 | tasks.register("clean", Delete) { 57 | delete rootProject.buildDir 58 | } 59 | 60 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # AndroidX & Jetpack config - https://developer.android.com/jetpack/androidx/migrate 11 | android.enableJetifier=true 12 | android.useAndroidX=true 13 | 14 | # Specifies the JVM arguments used for the daemon process. 15 | # The setting is particularly useful for tweaking memory settings. 16 | org.gradle.jvmargs=-Xmx4608M 17 | 18 | # android.enableR8 = true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niranjan94/show-java/f2f71dcd0955f21c8a9538322137a7961d33e792/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 22 16:57:42 IST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Show Java - A java/apk decompiler for android 3 | * Copyright (c) 2018 Niranjan Rajendran 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | include ":app" 20 | --------------------------------------------------------------------------------