├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.yml └── workflows │ ├── commit_ci.yml │ └── pull_request_ci.yml ├── .gitignore ├── .idea ├── AndroidProjectSystem.xml ├── icon.png ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinc.xml ├── ktlint-plugin.xml ├── ktlint.xml ├── migrations.xml ├── runConfigurations.xml └── vcs.xml ├── .secret ├── .gitignore └── universal.p12 ├── LICENSE ├── README-ja-JP.md ├── README-zh-CN.md ├── README.md ├── build.gradle.kts ├── demo-app ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── fankes │ │ └── apperrorstracking │ │ └── demo_app │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── demo_app.cpp │ ├── java │ │ └── com │ │ │ └── fankes │ │ │ └── apperrorsdemo │ │ │ ├── application │ │ │ └── DemoApplication.kt │ │ │ ├── native │ │ │ └── Channel.kt │ │ │ ├── ui │ │ │ └── activity │ │ │ │ ├── MainActivity.kt │ │ │ │ └── base │ │ │ │ └── BaseActivity.kt │ │ │ └── utils │ │ │ └── factory │ │ │ └── FunctionFactory.kt │ └── res │ │ ├── drawable-night │ │ └── bg_permotion_round.xml │ │ ├── drawable │ │ ├── bg_button_round.xml │ │ ├── bg_permotion_round.xml │ │ ├── ic_back.xml │ │ └── ic_launcher_foreground.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── activity_multi_process.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-night │ │ ├── color.xml │ │ └── themes.xml │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ ├── values-zh-rHK │ │ └── strings.xml │ │ ├── values-zh-rMO │ │ └── strings.xml │ │ ├── values-zh-rTW │ │ └── strings.xml │ │ ├── values │ │ ├── color.xml │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ └── locales_config.xml │ └── test │ └── java │ └── com │ └── fankes │ └── apperrorstracking │ └── demo_app │ └── ExampleUnitTest.kt ├── gradle.properties ├── gradle ├── sweet-dependency │ └── sweet-dependency-config.yaml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img-src └── icon.png ├── module-app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── fankes │ │ └── apperrorstracking │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── fankes │ │ │ └── apperrorstracking │ │ │ ├── application │ │ │ └── AppErrorsApplication.kt │ │ │ ├── bean │ │ │ ├── AppErrorsDisplayBean.kt │ │ │ ├── AppErrorsInfoBean.kt │ │ │ ├── AppFiltersBean.kt │ │ │ ├── AppInfoBean.kt │ │ │ ├── MutedErrorsAppBean.kt │ │ │ └── enum │ │ │ │ └── AppFiltersType.kt │ │ │ ├── const │ │ │ └── ConstFactory.kt │ │ │ ├── data │ │ │ ├── AppErrorsConfigData.kt │ │ │ ├── AppErrorsRecordData.kt │ │ │ ├── ConfigData.kt │ │ │ ├── enum │ │ │ │ └── AppErrorsConfigType.kt │ │ │ └── factory │ │ │ │ └── CompoundButtonFactory.kt │ │ │ ├── hook │ │ │ ├── HookEntry.kt │ │ │ └── entity │ │ │ │ └── FrameworkHooker.kt │ │ │ ├── locale │ │ │ └── LocaleFactory.kt │ │ │ ├── service │ │ │ └── QuickStartTileService.kt │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── base │ │ │ │ │ └── BaseActivity.kt │ │ │ │ ├── debug │ │ │ │ │ └── LoggerActivity.kt │ │ │ │ ├── errors │ │ │ │ │ ├── AppErrorsDetailActivity.kt │ │ │ │ │ ├── AppErrorsDisplayActivity.kt │ │ │ │ │ ├── AppErrorsMutedActivity.kt │ │ │ │ │ └── AppErrorsRecordActivity.kt │ │ │ │ └── main │ │ │ │ │ ├── ConfigureActivity.kt │ │ │ │ │ └── MainActivity.kt │ │ │ └── widget │ │ │ │ ├── ItemLinearLayout.kt │ │ │ │ └── MaterialSwitch.kt │ │ │ ├── utils │ │ │ ├── factory │ │ │ │ ├── BaseAdapterFactory.kt │ │ │ │ ├── DialogBuilderFactory.kt │ │ │ │ ├── FunctionFactory.kt │ │ │ │ ├── GsonFormatFactory.kt │ │ │ │ └── ThreadPoolFactory.kt │ │ │ └── tool │ │ │ │ ├── AppAnalyticsTool.kt │ │ │ │ ├── FrameworkTool.kt │ │ │ │ ├── GithubReleaseTool.kt │ │ │ │ ├── StackTraceShareHelper.kt │ │ │ │ └── ZipFileTool.kt │ │ │ └── wrapper │ │ │ └── BuildConfigWrapper.kt │ └── res │ │ ├── drawable-night │ │ ├── bg_dark_round.xml │ │ ├── bg_permotion_ripple.xml │ │ └── bg_permotion_round.xml │ │ ├── drawable │ │ ├── bg_black_round.xml │ │ ├── bg_blue_round.xml │ │ ├── bg_button_round.xml │ │ ├── bg_dark_round.xml │ │ ├── bg_green_round.xml │ │ ├── bg_logger_d_round.xml │ │ ├── bg_logger_e_round.xml │ │ ├── bg_logger_i_round.xml │ │ ├── bg_logger_w_round.xml │ │ ├── bg_orange_round.xml │ │ ├── bg_permotion_ripple.xml │ │ ├── bg_permotion_round.xml │ │ ├── bg_red_round.xml │ │ ├── bg_stack_round.xml │ │ ├── bg_yellow_round.xml │ │ ├── ic_android.xml │ │ ├── ic_appcenter.xml │ │ ├── ic_back.xml │ │ ├── ic_baseline_bug_report.xml │ │ ├── ic_baseline_close.xml │ │ ├── ic_baseline_eject.xml │ │ ├── ic_baseline_info.xml │ │ ├── ic_baseline_refresh.xml │ │ ├── ic_batch.xml │ │ ├── ic_clear.xml │ │ ├── ic_copy.xml │ │ ├── ic_cpp.xml │ │ ├── ic_debug.xml │ │ ├── ic_exception.xml │ │ ├── ic_export.xml │ │ ├── ic_filter.xml │ │ ├── ic_function.xml │ │ ├── ic_github.xml │ │ ├── ic_global.xml │ │ ├── ic_home.xml │ │ ├── ic_java.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_notify.xml │ │ ├── ic_preference.xml │ │ ├── ic_print.xml │ │ ├── ic_refresh.xml │ │ ├── ic_restart.xml │ │ ├── ic_share.xml │ │ ├── ic_statistics.xml │ │ ├── ic_success.xml │ │ ├── ic_theme.xml │ │ └── ic_warn.xml │ │ ├── layout │ │ ├── activitiy_logger.xml │ │ ├── activity_app_errors_detail.xml │ │ ├── activity_app_errors_display.xml │ │ ├── activity_app_errors_muted.xml │ │ ├── activity_app_errors_record.xml │ │ ├── activity_config.xml │ │ ├── activity_main.xml │ │ ├── adapter_app_errors_muted.xml │ │ ├── adapter_app_errors_record.xml │ │ ├── adapter_app_info.xml │ │ ├── adapter_logger.xml │ │ ├── dia_app_config.xml │ │ ├── dia_app_errors_display.xml │ │ ├── dia_app_errors_statistics.xml │ │ ├── dia_apps_filter.xml │ │ ├── dia_logger_filter.xml │ │ └── dia_stack_trace_share.xml │ │ ├── menu │ │ ├── menu_list_detail_action.xml │ │ └── menu_logger_action.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── bg_payment_code.jpg │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_yukihookapi.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-night │ │ ├── color.xml │ │ └── themes.xml │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ ├── values-zh-rHK │ │ └── strings.xml │ │ ├── values-zh-rMO │ │ └── strings.xml │ │ ├── values-zh-rTW │ │ └── strings.xml │ │ ├── values │ │ ├── array.xml │ │ ├── color.xml │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── file_paths.xml │ │ └── locales_config.xml │ └── test │ └── java │ └── com │ └── fankes │ └── apperrorstracking │ └── ExampleUnitTest.kt └── settings.gradle.kts /.editorconfig: -------------------------------------------------------------------------------- 1 | # noinspection EditorConfigKeyCorrectness 2 | [{*.kt,*.kts}] 3 | ktlint_standard_annotation = disabled 4 | ktlint_standard_filename = disabled 5 | ktlint_standard_wrapping = disabled 6 | ktlint_standard_import-ordering = enabled 7 | ktlint_standard_max-line-length = disabled 8 | ktlint_standard_multiline-if-else = disabled 9 | ktlint_standard_argument-list-wrapping = disabled 10 | ktlint_standard_parameter-list-wrapping = disabled 11 | ktlint_standard_trailing-comma-on-declaration-site = disabled 12 | ktlint_function_signature_body_expression_wrapping = multiline 13 | ktlint_standard_string-template-indent = disabled 14 | ktlint_standard_function-signature = disabled 15 | ktlint_standard_trailing-comma-on-call-site = disabled 16 | ktlint_standard_multiline-expression-wrapping = disabled 17 | ktlint_standard_no-empty-first-line-in-class-body = disabled 18 | ktlint_standard_if-else-wrapping = disabled 19 | ktlint_standard_if-else-bracing = disabled 20 | ktlint_standard_statement-wrapping = disabled 21 | ktlint_standard_blank-line-before-declaration = disabled 22 | ktlint_standard_no-empty-file = disabled 23 | ktlint_standard_property-naming = disabled 24 | ktlint_standard_function-naming = disabled 25 | ktlint_standard_chain-method-continuation = disabled 26 | ktlint_standard_class-signature = disabled 27 | ktlint_standard_condition-wrapping = disabled 28 | ktlint_standard_class-signature = disabled 29 | ij_continuation_indent_size = 2 30 | indent_size = 4 31 | indent_style = space 32 | insert_final_newline = false 33 | max_line_length = 150 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Issues and Bugs Report / 问题与 BUG 反馈 2 | description: 问题反馈必须使用此模板进行提交 / Issues and bugs report must be submitted using this template 3 | labels: [ bug ] 4 | title: "[Issues and Bugs Report] (Briefly describe the cause of the problem)" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ### Please fill in the specific reason and steps to reproduce the problem below. 10 | 11 | In the event of an exception, crash functional problem, you must submit a problem log, if not, your issues will be closed directly. 12 | 13 | ### 请在下方填写问题发生的具体原因和复现步骤。 14 | 15 | 发生异常、崩溃、闪退或功能性问题,必须提交问题 Log (日志),没有 Log 的 issues 将直接被关闭。 16 | - type: input 17 | attributes: 18 | label: Module App version / 模块版本 19 | description: | 20 | Please fill in the complete version of the Module App currently in use, for example: **1.0** 21 | 请填写当前使用的模块完整版本号,例如:**1.0** 22 | validations: 23 | required: true 24 | - type: input 25 | attributes: 26 | label: Device model and system in used / 正在使用的设备型号以及使用的系统 27 | description: | 28 | Fill in the current device model and system here, the system such as (MIUI, ColorOS, OxygenOS, PE/Native) 29 | 这里填写当前使用的设备型号以及使用的系统,系统例如 (MIUI、ColorOS、OxygenOS、PE/原生) 30 | validations: 31 | required: true 32 | - type: dropdown 33 | attributes: 34 | label: Android version / Android 版本 35 | options: 36 | - 14 37 | - 13 38 | - 12L/12.1 39 | - 12 40 | - 11 41 | - 10 42 | - 9 43 | - 8.1 44 | - 8.0.0 45 | - 7.1.2 46 | - 7.1.1 47 | - 7.0 48 | validations: 49 | required: true 50 | - type: input 51 | attributes: 52 | label: Xposed Framework name and version / Xposed 框架名称与版本号 53 | description: | 54 | Please fill in the currently used Xposed Framework, for example: **LSPosed 1.8.4 (version code)** 55 | 请填写当前使用的 Xposed 框架,例如:**LSPosed 1.8.4 (次版本号)** 56 | validations: 57 | required: true 58 | - type: input 59 | attributes: 60 | label: Xposed Modules with the same scope / 与当前同作用域的 Xposed 模块 61 | description: | 62 | The scope of this module is the System Framework (Android System). 63 | To ensure that the problem is not caused by conflicts with other modules, please be sure to fill in the relevant modules that you are currently activating at the same time. 64 | If not, please fill in "none" directly below. 65 | 此模块的作用域为系统框架 (Android 系统),为确保非其它模块冲突造成的问题,请一定要填写当前你同时激活的相关模块。 66 | 若没有,请直接在下方填写“无”。 67 | validations: 68 | required: true 69 | - type: textarea 70 | attributes: 71 | label: Describe in detail why the problem occurred / 详细描述问题发生的具体原因 72 | description: 请在下方详细描述问题发生的具体场景、复现步骤和经过,以便我们能够按照你所描述的步骤复现这个问题。 73 | validations: 74 | required: true 75 | - type: textarea 76 | attributes: 77 | label: Provide module problem logs or necessary logs / 提供模块问题 Log 或必要 Log 78 | description: | 79 | If you are using LSPosed, you can view and filter the logs containing `AppErrorsTracking` in the log management. 80 | LSPosed 可在日志管理中查看并筛选包含 `AppErrorsTracking` 的日志。 81 | value: | 82 |
Click to expand / 展开查看

 83 | 
 84 |         (Paste problem log here / 此处粘贴问题 Log)
 85 | 
 86 |         
87 | 88 | 89 | validations: 90 | required: true 91 | - type: checkboxes 92 | attributes: 93 | label: Confirm the contents you submitted / 确认一下你提交的信息 94 | description: | 95 | In order to ensure the quality of issues and avoid wasting unnecessary time, issues that do not check the options below will be closed directly. 96 | Please make sure you have **checked the option below** before submitting. 97 | 为了确保 issues 的质量和避免浪费不必要的时间,未勾选下方选项的 issues 将直接被关闭。 98 | 请一定确保你已经**勾选下方的选项**后再提交。 99 | options: 100 | - label: I certify that the above contents is correct / 我确保上述信息准确无误 101 | required: false 102 | -------------------------------------------------------------------------------- /.github/workflows/commit_ci.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Build on Commit 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ master ] 7 | paths-ignore: 8 | - '**.md' 9 | - '**.txt' 10 | - '.github/**' 11 | - '!.github/workflows/**' 12 | 13 | jobs: 14 | build: 15 | name: Build CI 16 | if: ${{ success() }} 17 | runs-on: ubuntu-latest 18 | env: 19 | MODULE_APK_OUTPUT_PATH: 'module-app/build/outputs/apk' 20 | DEMO_APK_OUTPUT_PATH: 'demo-app/build/outputs/apk' 21 | APP_CENTER_SECRET: ${{ secrets.APP_CENTER_SECRET }} 22 | TG_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} 23 | TG_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} 24 | COMMIT_MESSAGE: |+ 25 | New push to GitHub\! 26 | ``` 27 | ${{ github.event.head_commit.message }} 28 | ```by `${{ github.event.head_commit.author.name }}` 29 | See commit detail [here](${{ github.event.head_commit.url }}) 30 | COMMIT_URL: ${{ github.event.head_commit.url }} 31 | steps: 32 | - uses: actions/checkout@v4 33 | - name: Prepare GitHub Env 34 | run: | 35 | GITHUB_SHA=${{ github.sha }} 36 | GITHUB_CI_COMMIT_ID=${GITHUB_SHA:0:7} 37 | echo "GITHUB_CI_COMMIT_ID=$GITHUB_CI_COMMIT_ID" >> $GITHUB_ENV 38 | - name: Setup cmake 39 | uses: jwlawson/actions-setup-cmake@v1 40 | with: 41 | cmake-version: '3.22.1' 42 | - name: Prepare Java 17 43 | uses: actions/setup-java@v4 44 | with: 45 | java-version: 17 46 | java-package: jdk 47 | distribution: 'temurin' 48 | cache: 'gradle' 49 | - name: Cache Gradle Dependencies 50 | uses: actions/cache@v3 51 | with: 52 | path: | 53 | ~/.gradle/caches 54 | ~/.gradle/wrapper 55 | !~/.gradle/caches/build-cache-* 56 | key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }} 57 | restore-keys: | 58 | gradle-deps 59 | - name: Cache Gradle Build 60 | uses: actions/cache@v3 61 | with: 62 | path: | 63 | ~/.gradle/caches/build-cache-* 64 | key: gradle-builds-core-${{ github.sha }} 65 | restore-keys: | 66 | gradle-builds 67 | - name: Build with Gradle 68 | run: | 69 | ./gradlew :module-app:assembleDebug 70 | ./gradlew :module-app:assembleRelease 71 | ./gradlew :demo-app:assembleDebug 72 | ./gradlew :demo-app:assembleRelease 73 | echo "MODULE_DEBUG_APK_PATH=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV 74 | echo "MODULE_RELEASE_APK_PATH=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV 75 | echo "DEMO_DEBUG_APK_PATH=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV 76 | echo "DEMO_RELEASE_APK_PATH=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV 77 | - name: Upload Artifacts (Module-Debug) 78 | uses: actions/upload-artifact@v4 79 | with: 80 | path: ${{ env.MODULE_DEBUG_APK_PATH }} 81 | name: AppErrorsTracking-module-debug-${{ github.event.head_commit.id }} 82 | - name: Upload Artifacts (Module-Release) 83 | uses: actions/upload-artifact@v4 84 | with: 85 | path: ${{ env.MODULE_RELEASE_APK_PATH }} 86 | name: AppErrorsTracking-module-release-${{ github.event.head_commit.id }} 87 | - name: Upload Artifacts (Demo-Debug) 88 | uses: actions/upload-artifact@v4 89 | with: 90 | path: ${{ env.DEMO_DEBUG_APK_PATH }} 91 | name: AppErrorsTracking-demo-debug-${{ github.event.head_commit.id }} 92 | - name: Upload Artifacts (Demo-Release) 93 | uses: actions/upload-artifact@v4 94 | with: 95 | path: ${{ env.DEMO_RELEASE_APK_PATH }} 96 | name: AppErrorsTracking-demo-release-${{ github.event.head_commit.id }} 97 | - name: Post Artifacts to Telegram 98 | run: | 99 | export module_debug=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/debug -name "*.apk") 100 | export module_release=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/release -name "*.apk") 101 | export demo_debug=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/debug -name "*.apk") 102 | export demo_release=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/release -name "*.apk") 103 | ESCAPED=`python3 -c 'import json,os,urllib.parse; msg = json.dumps(os.environ["COMMIT_MESSAGE"]); print(urllib.parse.quote(msg if len(msg) <= 1024 else json.dumps(os.environ["COMMIT_URL"])))'` 104 | curl -v "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMediaGroup?chat_id=${TG_CHAT_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fmodule_debug%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fmodule_release%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fdemo_debug%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fdemo_release%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22:${ESCAPED}%7D%5D" \ 105 | -F module_debug="@$module_debug" \ 106 | -F module_release="@$module_release" \ 107 | -F demo_debug="@$demo_debug" \ 108 | -F demo_release="@$demo_release" -------------------------------------------------------------------------------- /.github/workflows/pull_request_ci.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Checker 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | paths-ignore: 7 | - '**.md' 8 | - '**.txt' 9 | - '.github/**' 10 | - '!.github/workflows/**' 11 | 12 | jobs: 13 | build: 14 | name: Pull Request Check 15 | if: ${{ success() }} 16 | runs-on: ubuntu-latest 17 | env: 18 | MODULE_APK_OUTPUT_PATH: 'module-app/build/outputs/apk' 19 | DEMO_APK_OUTPUT_PATH: 'demo-app/build/outputs/apk' 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Prepare GitHub Env 23 | run: | 24 | GITHUB_SHA=${{ github.sha }} 25 | GITHUB_CI_COMMIT_ID=${GITHUB_SHA:0:7} 26 | echo "GITHUB_CI_COMMIT_ID=$GITHUB_CI_COMMIT_ID" >> $GITHUB_ENV 27 | - name: Setup cmake 28 | uses: jwlawson/actions-setup-cmake@v1 29 | with: 30 | cmake-version: '3.22.1' 31 | - name: Prepare Java 17 32 | uses: actions/setup-java@v4 33 | with: 34 | java-version: 17 35 | java-package: jdk 36 | distribution: 'temurin' 37 | cache: 'gradle' 38 | - name: Cache Gradle Dependencies 39 | uses: actions/cache@v3 40 | with: 41 | path: | 42 | ~/.gradle/caches 43 | ~/.gradle/wrapper 44 | !~/.gradle/caches/build-cache-* 45 | key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }} 46 | restore-keys: | 47 | gradle-deps 48 | - name: Cache Gradle Build 49 | uses: actions/cache@v3 50 | with: 51 | path: | 52 | ~/.gradle/caches/build-cache-* 53 | key: gradle-builds-core-${{ github.sha }} 54 | restore-keys: | 55 | gradle-builds 56 | - name: Build with Gradle 57 | run: | 58 | ./gradlew :module-app:assembleDebug 59 | ./gradlew :module-app:assembleRelease 60 | ./gradlew :demo-app:assembleDebug 61 | ./gradlew :demo-app:assembleRelease 62 | echo "MODULE_DEBUG_APK_PATH=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV 63 | echo "MODULE_RELEASE_APK_PATH=$(find ${{ env.MODULE_APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV 64 | echo "DEMO_DEBUG_APK_PATH=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV 65 | echo "DEMO_RELEASE_APK_PATH=$(find ${{ env.DEMO_APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV 66 | - name: Upload Artifacts (Module-Debug) 67 | uses: actions/upload-artifact@v4 68 | with: 69 | path: ${{ env.MODULE_DEBUG_APK_PATH }} 70 | name: AppErrorsTracking-module-debug-${{ github.event.head_commit.id }} 71 | - name: Upload Artifacts (Module-Release) 72 | uses: actions/upload-artifact@v4 73 | with: 74 | path: ${{ env.MODULE_RELEASE_APK_PATH }} 75 | name: AppErrorsTracking-module-release-${{ github.event.head_commit.id }} 76 | - name: Upload Artifacts (Demo-Debug) 77 | uses: actions/upload-artifact@v4 78 | with: 79 | path: ${{ env.DEMO_DEBUG_APK_PATH }} 80 | name: AppErrorsTracking-demo-debug-${{ github.event.head_commit.id }} 81 | - name: Upload Artifacts (Demo-Release) 82 | uses: actions/upload-artifact@v4 83 | with: 84 | path: ${{ env.DEMO_RELEASE_APK_PATH }} 85 | name: AppErrorsTracking-demo-release-${{ github.event.head_commit.id }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Fully .gtignore for IntelliJ, Android Studio and Gradle based Java projects 2 | ## References: 3 | ## - https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 4 | ## - https://github.com/android/platform-samples/blob/main/.gitignore 5 | 6 | # User-specific stuff 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/**/usage.statistics.xml 10 | .idea/**/dictionaries 11 | .idea/**/shelf 12 | 13 | # AWS User-specific 14 | .idea/**/aws.xml 15 | 16 | # Generated files 17 | .idea/**/contentModel.xml 18 | 19 | # Sensitive or high-churn files 20 | .idea/**/dataSources/ 21 | .idea/**/dataSources.ids 22 | .idea/**/dataSources.local.xml 23 | .idea/**/sqlDataSources.xml 24 | .idea/**/dynamic.xml 25 | .idea/**/uiDesigner.xml 26 | .idea/**/dbnavigator.xml 27 | 28 | # Gradle 29 | .idea/**/gradle.xml 30 | .idea/**/libraries 31 | 32 | # Gradle and Maven with auto-import 33 | .idea/.name 34 | .idea/artifacts 35 | .idea/compiler.xml 36 | .idea/jarRepositories.xml 37 | .idea/modules.xml 38 | .idea/*.iml 39 | .idea/modules 40 | .idea/caches 41 | .idea/material_theme** 42 | .idea/other.xml 43 | *.iml 44 | *.ipr 45 | 46 | # Kotlin 47 | .kotlin 48 | 49 | # Misc 50 | .idea/misc.xml 51 | 52 | # CMake 53 | cmake-build-*/ 54 | 55 | # Mongo Explorer plugin 56 | .idea/**/mongoSettings.xml 57 | 58 | # File-based project format 59 | *.iws 60 | 61 | # IntelliJ 62 | out/ 63 | 64 | # mpeltonen/sbt-idea plugin 65 | .idea_modules/ 66 | 67 | # JIRA plugin 68 | atlassian-ide-plugin.xml 69 | 70 | # Cursive Clojure plugin 71 | .idea/replstate.xml 72 | 73 | # SonarLint plugin 74 | .idea/sonarlint/ 75 | 76 | # Crashlytics plugin (for Android Studio and IntelliJ) 77 | com_crashlytics_export_strings.xml 78 | crashlytics.properties 79 | crashlytics-build.properties 80 | fabric.properties 81 | 82 | # Editor-based Rest Client 83 | .idea/httpRequests 84 | 85 | # Android studio 3.1+ serialized cache file 86 | .idea/caches/build_file_checksums.ser 87 | 88 | # Android studio 3.1+ additional 89 | .idea/deployment*.xml 90 | .idea/assetWizardSettings.xml 91 | .idea/androidTestResultsUserPreferences.xml 92 | 93 | # Android projects 94 | **/local.properties 95 | /captures 96 | .externalNativeBuild 97 | .cxx 98 | 99 | # Gradle projects 100 | .gradle 101 | build/ 102 | 103 | # Mkdocs temporary serving folder 104 | docs-gen 105 | site 106 | *.bak 107 | .idea/appInsightsSettings.xml 108 | 109 | # Mac OS 110 | .DS_Store -------------------------------------------------------------------------------- /.idea/AndroidProjectSystem.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/.idea/icon.png -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/ktlint-plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MANUAL 5 | false 6 | 7 | -------------------------------------------------------------------------------- /.idea/ktlint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.secret/.gitignore: -------------------------------------------------------------------------------- 1 | /secret.properties -------------------------------------------------------------------------------- /.secret/universal.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/.secret/universal.p12 -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | autowire(libs.plugins.android.application) apply false 3 | autowire(libs.plugins.kotlin.android) apply false 4 | autowire(libs.plugins.kotlin.ksp) apply false 5 | } -------------------------------------------------------------------------------- /demo-app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | autowire(libs.plugins.android.application) 3 | autowire(libs.plugins.kotlin.android) 4 | } 5 | 6 | android { 7 | namespace = property.project.demo.app.packageName 8 | compileSdk = property.project.android.compileSdk 9 | ndkVersion = property.project.android.ndk.version 10 | 11 | signingConfigs { 12 | create("universal") { 13 | keyAlias = property.project.demo.app.signing.keyAlias 14 | keyPassword = property.project.demo.app.signing.keyPassword 15 | storeFile = rootProject.file(property.project.demo.app.signing.storeFilePath) 16 | storePassword = property.project.demo.app.signing.storePassword 17 | enableV1Signing = true 18 | enableV2Signing = true 19 | } 20 | } 21 | defaultConfig { 22 | applicationId = property.project.demo.app.packageName 23 | minSdk = property.project.android.minSdk 24 | targetSdk = property.project.android.targetSdk 25 | versionName = property.project.demo.app.versionName 26 | versionCode = property.project.demo.app.versionCode 27 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 28 | } 29 | buildTypes { 30 | all { signingConfig = signingConfigs.getByName("universal") } 31 | release { 32 | isMinifyEnabled = false 33 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") 34 | } 35 | } 36 | externalNativeBuild { 37 | cmake { 38 | path("src/main/cpp/CMakeLists.txt") 39 | version = property.project.android.cmake.version 40 | } 41 | } 42 | compileOptions { 43 | sourceCompatibility = JavaVersion.VERSION_17 44 | targetCompatibility = JavaVersion.VERSION_17 45 | } 46 | kotlinOptions { 47 | jvmTarget = "17" 48 | freeCompilerArgs = listOf( 49 | "-Xno-param-assertions", 50 | "-Xno-call-assertions", 51 | "-Xno-receiver-assertions" 52 | ) 53 | } 54 | buildFeatures { 55 | buildConfig = true 56 | viewBinding = true 57 | } 58 | lint { checkReleaseBuilds = false } 59 | androidResources.additionalParameters += listOf("--allow-reserved-package-id", "--package-id", "0x37") 60 | } 61 | 62 | androidComponents { 63 | onVariants(selector().all()) { 64 | it.outputs.forEach { output -> 65 | val currentType = it.buildType 66 | 67 | // Workaround for GitHub Actions. 68 | // Why? I don't know, but it works. 69 | // Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 70 | // public inline fun CharSequence.isNotBlank(): Boolean defined in kotlin.text. 71 | @Suppress("UNNECESSARY_SAFE_CALL", "RemoveRedundantCallsOfConversionMethods") 72 | val currentSuffix = property.github.ci.commit.id?.let { suffix -> 73 | // Workaround for GitHub Actions. 74 | // Strongly transfer type to [String]. 75 | val sSuffix = suffix.toString() 76 | if (sSuffix.isNotBlank()) "-$sSuffix" else "" 77 | } 78 | val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})" 79 | if (output is com.android.build.api.variant.impl.VariantOutputImpl) 80 | output.outputFileName.set("${property.project.name}-demo-v$currentVersion-$currentType.apk") 81 | } 82 | } 83 | } 84 | 85 | dependencies { 86 | implementation(com.fankes.projectpromote.project.promote) 87 | implementation(com.highcapable.yukireflection.api) 88 | implementation(androidx.core.core.ktx) 89 | implementation(androidx.appcompat.appcompat) 90 | implementation(com.google.android.material.material) 91 | testImplementation(junit.junit) 92 | androidTestImplementation(androidx.test.ext.junit) 93 | androidTestImplementation(androidx.test.espresso.espresso.core) 94 | } -------------------------------------------------------------------------------- /demo-app/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/consumer-rules.pro -------------------------------------------------------------------------------- /demo-app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /demo-app/src/androidTest/java/com/fankes/apperrorstracking/demo_app/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.fankes.apperrorstracking.demo_app 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.fankes.apperrorstracking.demo_app.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /demo-app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 11 | 12 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | -------------------------------------------------------------------------------- /demo-app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.22.1) 7 | 8 | # Declares and names the project. 9 | 10 | project("demo_app") 11 | 12 | # Creates and names a library, sets it as either STATIC 13 | # or SHARED, and provides the relative paths to its source code. 14 | # You can define multiple libraries, and CMake builds them for you. 15 | # Gradle automatically packages shared libraries with your APK. 16 | 17 | add_library( # Sets the name of the library. 18 | demo_app 19 | 20 | # Sets the library as a shared library. 21 | SHARED 22 | 23 | # Provides a relative path to your source file(s). 24 | demo_app.cpp) 25 | 26 | # Searches for a specified prebuilt library and stores the path as a 27 | # variable. Because CMake includes system libraries in the search path by 28 | # default, you only need to specify the name of the public NDK library 29 | # you want to add. CMake verifies that the library exists before 30 | # completing its build. 31 | 32 | find_library( # Sets the name of the path variable. 33 | log-lib 34 | 35 | # Specifies the name of the NDK library that 36 | # you want CMake to locate. 37 | log) 38 | 39 | # Specifies libraries CMake should link to your target library. You 40 | # can link multiple libraries, such as libraries you define in this 41 | # build script, prebuilt third-party libraries, or system libraries. 42 | 43 | target_link_libraries( # Specifies the target library. 44 | demo_app 45 | 46 | # Links the target library to the log library 47 | # included in the NDK. 48 | ${log-lib}) -------------------------------------------------------------------------------- /demo-app/src/main/cpp/demo_app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C" JNIEXPORT void JNICALL 5 | Java_com_fankes_apperrorsdemo_native_Channel_throwNativeException(JNIEnv *env, jobject) { 6 | throw std::exception(); 7 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/com/fankes/apperrorsdemo/application/DemoApplication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | package com.fankes.apperrorsdemo.application 23 | 24 | import android.app.Application 25 | import androidx.appcompat.app.AppCompatDelegate 26 | 27 | class DemoApplication : Application() { 28 | 29 | override fun onCreate() { 30 | super.onCreate() 31 | /** 跟随系统夜间模式 */ 32 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 33 | } 34 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/com/fankes/apperrorsdemo/native/Channel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | package com.fankes.apperrorsdemo.native 23 | 24 | object Channel { 25 | 26 | init { 27 | System.loadLibrary("demo_app") 28 | } 29 | 30 | fun throwRuntimeException() { 31 | throw RuntimeException("Exception test") 32 | } 33 | 34 | fun throwIllegalStateException() { 35 | throw IllegalStateException("Exception test") 36 | } 37 | 38 | fun throwNullPointerException() { 39 | throw NullPointerException("Exception test") 40 | } 41 | 42 | fun throwException() { 43 | throw Exception() 44 | } 45 | 46 | external fun throwNativeException() 47 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/com/fankes/apperrorsdemo/ui/activity/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | @file:Suppress("SetTextI18n") 23 | 24 | package com.fankes.apperrorsdemo.ui.activity 25 | 26 | import android.content.Intent 27 | import android.os.SystemClock 28 | import com.fankes.apperrorsdemo.R 29 | import com.fankes.apperrorsdemo.databinding.ActivityMainBinding 30 | import com.fankes.apperrorsdemo.databinding.ActivityMultiProcessBinding 31 | import com.fankes.apperrorsdemo.generated.DemoAppProperties 32 | import com.fankes.apperrorsdemo.native.Channel 33 | import com.fankes.apperrorsdemo.ui.activity.base.BaseActivity 34 | 35 | class MainActivity : BaseActivity() { 36 | 37 | override fun onCreate() { 38 | DemoAppProperties.GITHUB_CI_COMMIT_ID.takeIf(String::isNotBlank)?.also { 39 | binding.titleText.text = "${getString(R.string.app_name)} ($it)" 40 | }; binding.titleBackIcon.setOnClickListener { finish() } 41 | binding.throwRuntimeButton.setOnClickListener { Channel.throwRuntimeException() } 42 | binding.throwIllegalStateButton.setOnClickListener { Channel.throwIllegalStateException() } 43 | binding.throwNullPointerButton.setOnClickListener { Channel.throwNullPointerException() } 44 | binding.throwExceptionButton.setOnClickListener { Channel.throwException() } 45 | binding.throwNativeErrorButton.setOnClickListener { Channel.throwNativeException() } 46 | binding.throwMultiProcessErrorButton.setOnClickListener { startActivity(Intent(this, MultiProcessActivity::class.java)) } 47 | } 48 | 49 | class MultiProcessActivity : BaseActivity() { 50 | 51 | override fun onCreate() { 52 | Thread { 53 | SystemClock.sleep(600) 54 | error("Throw in multi-process") 55 | }.start() 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/com/fankes/apperrorsdemo/ui/activity/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | @file:Suppress("DEPRECATION") 23 | 24 | package com.fankes.apperrorsdemo.ui.activity.base 25 | 26 | import android.os.Build 27 | import android.os.Bundle 28 | import androidx.appcompat.app.AppCompatActivity 29 | import androidx.core.content.res.ResourcesCompat 30 | import androidx.core.view.WindowCompat 31 | import androidx.viewbinding.ViewBinding 32 | import com.fankes.apperrorsdemo.R 33 | import com.fankes.apperrorsdemo.utils.factory.isNotSystemInDarkMode 34 | import com.highcapable.yukireflection.factory.current 35 | import com.highcapable.yukireflection.factory.method 36 | import com.highcapable.yukireflection.type.android.LayoutInflaterClass 37 | 38 | abstract class BaseActivity : AppCompatActivity() { 39 | 40 | /** 获取绑定布局对象 */ 41 | lateinit var binding: VB 42 | 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | binding = current().generic()?.argument()?.method { 46 | name = "inflate" 47 | param(LayoutInflaterClass) 48 | }?.get()?.invoke(layoutInflater) ?: error("binding failed") 49 | if (Build.VERSION.SDK_INT >= 35) binding.root.fitsSystemWindows = true 50 | setContentView(binding.root) 51 | /** 隐藏系统的标题栏 */ 52 | supportActionBar?.hide() 53 | /** 初始化沉浸状态栏 */ 54 | WindowCompat.getInsetsController(window, window.decorView).apply { 55 | isAppearanceLightStatusBars = isNotSystemInDarkMode 56 | isAppearanceLightNavigationBars = isNotSystemInDarkMode 57 | } 58 | ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also { 59 | window?.statusBarColor = it 60 | window?.navigationBarColor = it 61 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) window?.navigationBarDividerColor = it 62 | } 63 | /** 装载子类 */ 64 | onCreate() 65 | } 66 | 67 | /** 回调 [onCreate] 方法 */ 68 | abstract fun onCreate() 69 | } -------------------------------------------------------------------------------- /demo-app/src/main/java/com/fankes/apperrorsdemo/utils/factory/FunctionFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | package com.fankes.apperrorsdemo.utils.factory 23 | 24 | import android.content.Context 25 | import android.content.res.Configuration 26 | 27 | /** 28 | * 系统深色模式是否开启 29 | * @return [Boolean] 是否开启 30 | */ 31 | val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES 32 | 33 | /** 34 | * 系统深色模式是否没开启 35 | * @return [Boolean] 是否开启 36 | */ 37 | inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable-night/bg_permotion_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/bg_button_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/bg_permotion_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /demo-app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /demo-app/src/main/res/layout/activity_multi_process.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/demo-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo-app/src/main/res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | AppErrorsDemo 4 | 戻る 5 | 一般的なシナリオにおけるビジネス例外のロジックを提供します。\nXposed モジュールを有効化後に例外を取得できるかどうかをテストする事ができます。\nXposed モジュールの有効性を検証するため、現在のアプリには手動で例外を処理するロジックコードはありません。 6 | RuntimeException をスロー 7 | IllegalStateException をスロー 8 | NullPointerException をスロー 9 | Exception をスロー 10 | ネイティブエラーをスロー 11 | マルチプロセスの例外をスロー 12 | プロセスを強制停止中 13 | 14 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-night/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF2D2D2D 4 | #FFCFCFCF 5 | #FFD3D3D3 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 异常示例 4 | 返回 5 | 这里提供了常见场景下的业务异常逻辑,激活 Xposed 模块后,可在此测试异常是否能够被捕获,为了验证 Xposed 模块生效情况,当前 APP 无任何手动处理异常的逻辑代码。 6 | 抛出 RuntimeException 7 | 抛出 IllegalStateException 8 | 抛出 NullPointerException 9 | 抛出 Exception 10 | 抛出原生层异常 11 | 抛出多进程异常 12 | 正在自杀 13 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-zh-rHK/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 異常示例 4 | 回退 5 | 這裡提供了常見場景下的業務異常邏輯,激活 Xposed 模組後,可在此測試異常是否能夠被捕獲,為了驗證 Xposed 模組生效情況,當前 APP 無任何手動處理異常的邏輯編碼。 6 | 抛出 RuntimeException 7 | 抛出 IllegalStateException 8 | 抛出 NullPointerException 9 | 抛出 Exception 10 | 拋出原生層異常 11 | 拋出多進程異常 12 | 自殺中 13 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-zh-rMO/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 異常示例 4 | 回退 5 | 這裡提供了常見場景下的業務異常邏輯,激活 Xposed 模組後,可在此測試異常是否能夠被捕獲,為了驗證 Xposed 模組生效情況,當前 APP 無任何手動處理異常的邏輯編碼。 6 | 抛出 RuntimeException 7 | 抛出 IllegalStateException 8 | 抛出 NullPointerException 9 | 抛出 Exception 10 | 拋出原生層異常 11 | 拋出多進程異常 12 | 自殺中 13 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values-zh-rTW/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 異常示例 4 | 回退 5 | 這裡提供了常見場景下的業務異常邏輯,激活 Xposed 模組後,可在此測試異常是否能夠被捕獲,為了驗證 Xposed 模組生效情況,當前 APP 無任何手動處理異常的邏輯編碼。 6 | 抛出 RuntimeException 7 | 抛出 IllegalStateException 8 | 抛出 NullPointerException 9 | 抛出 Exception 10 | 拋出原生層異常 11 | 拋出多進程異常 12 | 自殺中 13 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | #FF777777 5 | #FF323B42 6 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #656565 4 | #FF000000 5 | #FFFFFFFF 6 | #00000000 7 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF6200 4 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AppErrorsDemo 3 | Back 4 | The business exception logic in common scenarios is provided here.\nAfter activating the Xposed Module, you can test whether the exception can be caught here.\nIn order to verify the effectiveness of the Xposed Module, the current App does not have any logic code for manually handling exceptions. 5 | Throw RuntimeException 6 | Throw IllegalStateException 7 | Throw NullPointerException 8 | Throw Exception 9 | Throw Native Error 10 | Throw Multi-Process Exception 11 | Suicide in progress 12 | -------------------------------------------------------------------------------- /demo-app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | -------------------------------------------------------------------------------- /demo-app/src/main/res/xml/locales_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demo-app/src/test/java/com/fankes/apperrorstracking/demo_app/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.fankes.apperrorstracking.demo_app 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Compiler Configuration 2 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 3 | android.useAndroidX=true 4 | android.nonTransitiveRClass=true 5 | kotlin.code.style=official 6 | kotlin.incremental.useClasspathSnapshot=true 7 | # Project Configuration 8 | project.name=AppErrorsTracking 9 | project.android.compileSdk=35 10 | project.android.minSdk=24 11 | project.android.targetSdk=35 12 | project.android.ndk.version="24.0.8215888" 13 | project.android.cmake.version="3.22.1" 14 | project.module-app.packageName=com.fankes.apperrorstracking 15 | project.module-app.versionName="1.3" 16 | project.module-app.versionCode=6 17 | project.module-app.signing.keyAlias=public 18 | project.module-app.signing.keyPassword="123456" 19 | project.module-app.signing.storePassword="123456" 20 | project.module-app.signing.storeFilePath=.secret/universal.p12 21 | project.demo-app.packageName=com.fankes.apperrorsdemo 22 | project.demo-app.versionName="${project.module-app.versionName}" 23 | project.demo-app.versionCode=${project.module-app.versionCode} 24 | project.demo-app.signing.keyAlias="${project.module-app.signing.keyAlias}" 25 | project.demo-app.signing.keyPassword="${project.module-app.signing.keyPassword}" 26 | project.demo-app.signing.storePassword="${project.module-app.signing.storePassword}" 27 | project.demo-app.signing.storeFilePath="${project.module-app.signing.storeFilePath}" -------------------------------------------------------------------------------- /gradle/sweet-dependency/sweet-dependency-config.yaml: -------------------------------------------------------------------------------- 1 | preferences: 2 | autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES 3 | repositories-mode: FAIL_ON_PROJECT_REPOS 4 | 5 | repositories: 6 | gradle-plugin-portal: 7 | scope: PLUGINS 8 | google: 9 | maven-central: 10 | jit-pack: 11 | sonatype-oss-releases: 12 | rovo89-xposed-api: 13 | scope: LIBRARIES 14 | url: https://api.xposed.info/ 15 | content: 16 | include: 17 | group: 18 | de.robv.android.xposed 19 | fankes-maven-releases: 20 | url: https://raw.githubusercontent.com/fankes/maven-repository/main/repository/releases 21 | 22 | plugins: 23 | com.android.application: 24 | alias: android-application 25 | version: 8.9.0 26 | org.jetbrains.kotlin.android: 27 | alias: kotlin-android 28 | version: 2.1.10 29 | com.highcapable.flexilocale: 30 | alias: flexi-locale 31 | version: 1.0.1 32 | com.google.devtools.ksp: 33 | alias: kotlin-ksp 34 | version: 2.1.10-1.0.31 35 | 36 | libraries: 37 | com.fankes.projectpromote: 38 | project-promote: 39 | version: 1.0.0 40 | repositories: 41 | fankes-maven-releases 42 | de.robv.android.xposed: 43 | api: 44 | version: 82 45 | repositories: 46 | rovo89-xposed-api 47 | com.highcapable.yukihookapi: 48 | api: 49 | version: 1.2.1 50 | ksp-xposed: 51 | version-ref: ::api 52 | com.highcapable.yukireflection: 53 | api: 54 | version: 1.0.3 55 | com.microsoft.appcenter: 56 | appcenter-analytics: 57 | version: 5.0.6 58 | appcenter-crashes: 59 | version-ref: ::appcenter-analytics 60 | com.github.topjohnwu.libsu: 61 | core: 62 | version: 5.2.2 63 | auto-update: false 64 | com.github.duanhong169: 65 | drawabletoolbox: 66 | version: 1.0.7 67 | com.google.code.gson: 68 | gson: 69 | version: 2.12.1 70 | com.squareup.okhttp3: 71 | okhttp: 72 | version: 5.0.0-alpha.14 73 | androidx.core: 74 | core-ktx: 75 | version: 1.15.0 76 | androidx.appcompat: 77 | appcompat: 78 | version: 1.7.0 79 | com.google.android.material: 80 | material: 81 | version: 1.12.0 82 | androidx.constraintlayout: 83 | constraintlayout: 84 | version: 2.2.1 85 | androidx.test.ext: 86 | junit: 87 | version: 1.2.1 88 | androidx.test.espresso: 89 | espresso-core: 90 | version: 3.6.1 91 | junit: 92 | junit: 93 | version: 4.13.2 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 3 | distributionPath=wrapper/dists 4 | zipStorePath=wrapper/dists 5 | zipStoreBase=GRADLE_USER_HOME -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /img-src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/img-src/icon.png -------------------------------------------------------------------------------- /module-app/.gitignore: -------------------------------------------------------------------------------- 1 | /src/main/assets/xposed_init 2 | /src/main/resources/META-INF/yukihookapi_init -------------------------------------------------------------------------------- /module-app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | autowire(libs.plugins.android.application) 3 | autowire(libs.plugins.kotlin.android) 4 | autowire(libs.plugins.kotlin.ksp) 5 | autowire(libs.plugins.flexi.locale) 6 | } 7 | 8 | android { 9 | namespace = property.project.module.app.packageName 10 | compileSdk = property.project.android.compileSdk 11 | 12 | signingConfigs { 13 | create("universal") { 14 | keyAlias = property.project.module.app.signing.keyAlias 15 | keyPassword = property.project.module.app.signing.keyPassword 16 | storeFile = rootProject.file(property.project.module.app.signing.storeFilePath) 17 | storePassword = property.project.module.app.signing.storePassword 18 | enableV1Signing = true 19 | enableV2Signing = true 20 | } 21 | } 22 | defaultConfig { 23 | applicationId = property.project.module.app.packageName 24 | minSdk = property.project.android.minSdk 25 | targetSdk = property.project.android.targetSdk 26 | versionName = property.project.module.app.versionName 27 | versionCode = property.project.module.app.versionCode 28 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 29 | } 30 | buildTypes { 31 | all { signingConfig = signingConfigs.getByName("universal") } 32 | release { 33 | isMinifyEnabled = true 34 | isShrinkResources = true 35 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") 36 | } 37 | } 38 | compileOptions { 39 | sourceCompatibility = JavaVersion.VERSION_17 40 | targetCompatibility = JavaVersion.VERSION_17 41 | } 42 | kotlinOptions { 43 | jvmTarget = "17" 44 | freeCompilerArgs = listOf( 45 | "-Xno-param-assertions", 46 | "-Xno-call-assertions", 47 | "-Xno-receiver-assertions" 48 | ) 49 | } 50 | buildFeatures { 51 | buildConfig = true 52 | viewBinding = true 53 | } 54 | lint { checkReleaseBuilds = false } 55 | androidResources.additionalParameters += listOf("--allow-reserved-package-id", "--package-id", "0x37") 56 | } 57 | 58 | androidComponents { 59 | onVariants(selector().all()) { 60 | it.outputs.forEach { output -> 61 | val currentType = it.buildType 62 | 63 | // Workaround for GitHub Actions. 64 | // Why? I don't know, but it works. 65 | // Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 66 | // public inline fun CharSequence.isNotBlank(): Boolean defined in kotlin.text. 67 | @Suppress("UNNECESSARY_SAFE_CALL", "RemoveRedundantCallsOfConversionMethods") 68 | val currentSuffix = property.github.ci.commit.id?.let { suffix -> 69 | // Workaround for GitHub Actions. 70 | // Strongly transfer type to [String]. 71 | val sSuffix = suffix.toString() 72 | if (sSuffix.isNotBlank()) "-$sSuffix" else "" 73 | } 74 | val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})" 75 | if (output is com.android.build.api.variant.impl.VariantOutputImpl) 76 | output.outputFileName.set("${property.project.name}-module-v$currentVersion-$currentType.apk") 77 | } 78 | } 79 | } 80 | 81 | dependencies { 82 | compileOnly(de.robv.android.xposed.api) 83 | implementation(com.highcapable.yukihookapi.api) 84 | ksp(com.highcapable.yukihookapi.ksp.xposed) 85 | implementation(com.fankes.projectpromote.project.promote) 86 | implementation(com.microsoft.appcenter.appcenter.analytics) 87 | implementation(com.microsoft.appcenter.appcenter.crashes) 88 | implementation(com.github.topjohnwu.libsu.core) 89 | implementation(com.github.duanhong169.drawabletoolbox) 90 | implementation(com.google.code.gson.gson) 91 | implementation(com.squareup.okhttp3.okhttp) 92 | implementation(androidx.core.core.ktx) 93 | implementation(androidx.appcompat.appcompat) 94 | implementation(com.google.android.material.material) 95 | implementation(androidx.constraintlayout.constraintlayout) 96 | testImplementation(junit.junit) 97 | androidTestImplementation(androidx.test.ext.junit) 98 | androidTestImplementation(androidx.test.espresso.espresso.core) 99 | } -------------------------------------------------------------------------------- /module-app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -ignorewarnings 24 | -optimizationpasses 10 25 | -dontusemixedcaseclassnames 26 | -dontoptimize 27 | -verbose 28 | -overloadaggressively 29 | -allowaccessmodification 30 | -adaptclassstrings 31 | -adaptresourcefilenames 32 | -adaptresourcefilecontents 33 | 34 | -renamesourcefileattribute P 35 | -keepattributes SourceFile,Signature,LineNumberTable 36 | 37 | ## ---------------Begin: proguard configuration for Gson ---------- 38 | # Gson uses generic type information stored in a class file when working with fields. Proguard 39 | # removes such information by default, so configure it to keep all of it. 40 | 41 | # Explicitly preserve all serialization members. The Serializable interface 42 | # is only a marker interface, so it wouldn't save them. 43 | -keepclassmembers class * implements java.io.Serializable { 44 | static final long serialVersionUID; 45 | private static final java.io.ObjectStreamField[] serialPersistentFields; 46 | private void writeObject(java.io.ObjectOutputStream); 47 | private void readObject(java.io.ObjectInputStream); 48 | java.lang.Object writeReplace(); 49 | java.lang.Object readResolve(); 50 | } 51 | 52 | # Gson specific classes 53 | -dontwarn sun.misc.** 54 | -keep class com.google.gson.stream.** { *; } 55 | 56 | # Prevent R8 from leaving Data object members always null 57 | -keepclassmembers,allowobfuscation class * { 58 | @com.google.gson.annotations.SerializedName ; 59 | } 60 | 61 | # Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher. 62 | -keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken 63 | -keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken 64 | 65 | ## ---------------End: proguard configuration for Gson ---------- 66 | 67 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics { 68 | public static *** throwUninitializedProperty(...); 69 | public static *** throwUninitializedPropertyAccessException(...); 70 | } 71 | 72 | -keep class * extends android.app.Activity 73 | -keep class * implements androidx.viewbinding.ViewBinding { 74 | (); 75 | *** inflate(android.view.LayoutInflater); 76 | } -------------------------------------------------------------------------------- /module-app/src/androidTest/java/com/fankes/apperrorstracking/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.fankes.apperrorstracking 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.fankes.apperrorstracking", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /module-app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 16 | 19 | 20 | 30 | 31 | 34 | 37 | 40 | 43 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 77 | 78 | 82 | 83 | 87 | 88 | 92 | 93 | 102 | 103 | 108 | 109 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 126 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /module-app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/application/AppErrorsApplication.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/10. 21 | */ 22 | package com.fankes.apperrorstracking.application 23 | 24 | import androidx.appcompat.app.AppCompatDelegate 25 | import com.fankes.apperrorstracking.data.ConfigData 26 | import com.fankes.apperrorstracking.generated.locale.ModuleAppLocale 27 | import com.fankes.apperrorstracking.locale.locale 28 | import com.fankes.apperrorstracking.utils.tool.AppAnalyticsTool 29 | import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication 30 | 31 | class AppErrorsApplication : ModuleApplication() { 32 | 33 | override fun onCreate() { 34 | super.onCreate() 35 | /** 绑定 I18n */ 36 | locale = ModuleAppLocale.attach(this) 37 | /** 跟随系统夜间模式 */ 38 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 39 | /** 装载存储控制类 */ 40 | ConfigData.init(this) 41 | /** 装载 App Center */ 42 | AppAnalyticsTool.init(this) 43 | } 44 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/bean/AppErrorsDisplayBean.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/1. 21 | */ 22 | package com.fankes.apperrorstracking.bean 23 | 24 | import java.io.Serializable 25 | 26 | /** 27 | * 应用异常信息显示 bean 28 | * @param pid APP 进程 ID 29 | * @param userId APP 用户 ID 30 | * @param packageName APP 包名 31 | * @param processName APP 进程名 32 | * @param appName APP 名称 33 | * @param title 标题 34 | * @param isShowAppInfoButton 是否显示应用信息按钮 35 | * @param isShowCloseAppButton 是否显示关闭应用按钮 36 | * @param isShowReopenButton 是否显示重新打开按钮 37 | */ 38 | data class AppErrorsDisplayBean( 39 | var pid: Int, 40 | var userId: Int, 41 | var packageName: String, 42 | var processName: String, 43 | var appName: String, 44 | var title: String, 45 | var isShowAppInfoButton: Boolean, 46 | var isShowCloseAppButton: Boolean, 47 | var isShowReopenButton: Boolean 48 | ) : Serializable -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/bean/AppFiltersBean.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/4. 21 | */ 22 | package com.fankes.apperrorstracking.bean 23 | 24 | import com.fankes.apperrorstracking.bean.enum.AppFiltersType 25 | import java.io.Serializable 26 | 27 | /** 28 | * 应用过滤条件 bean 29 | * @param name 名称或包名 30 | * @param type 过滤条件类型 31 | */ 32 | data class AppFiltersBean( 33 | var name: String = "", 34 | var type: AppFiltersType = AppFiltersType.USER 35 | ) : Serializable -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/bean/AppInfoBean.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/8. 21 | */ 22 | package com.fankes.apperrorstracking.bean 23 | 24 | import android.graphics.drawable.Drawable 25 | import java.io.Serializable 26 | 27 | /** 28 | * 应用信息 bean 29 | * @param icon 图标 30 | * @param name APP 名称 31 | * @param packageName APP 包名 32 | */ 33 | data class AppInfoBean( 34 | var icon: Drawable? = null, 35 | var name: String, 36 | var packageName: String 37 | ) : Serializable -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/bean/MutedErrorsAppBean.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/3. 21 | */ 22 | package com.fankes.apperrorstracking.bean 23 | 24 | import java.io.Serializable 25 | 26 | /** 27 | * 已忽略异常的应用 bean 28 | * @param type 类型 29 | * @param packageName 包名 30 | */ 31 | data class MutedErrorsAppBean( 32 | var type: MuteType, 33 | var packageName: String 34 | ) : Serializable { 35 | 36 | /** 37 | * 已忽略的异常类型 38 | */ 39 | enum class MuteType { UNTIL_UNLOCKS, UNTIL_REBOOTS } 40 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/bean/enum/AppFiltersType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/1/22. 21 | */ 22 | package com.fankes.apperrorstracking.bean.enum 23 | 24 | /** 25 | * 应用过滤条件类型定义类 26 | */ 27 | enum class AppFiltersType { 28 | /** 用户 */ 29 | USER, 30 | 31 | /** 系统 */ 32 | SYSTEM, 33 | 34 | /** 全部 */ 35 | ALL 36 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/const/ConstFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/9/19. 21 | */ 22 | @file:Suppress("MemberVisibilityCanBePrivate") 23 | 24 | package com.fankes.apperrorstracking.const 25 | 26 | import com.fankes.apperrorstracking.generated.ModuleAppProperties 27 | import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper 28 | 29 | /** 30 | * 包名常量定义类 31 | */ 32 | object PackageName { 33 | 34 | /** 系统框架 */ 35 | const val SYSTEM_FRAMEWORK = "android" 36 | } 37 | 38 | /** 39 | * 模块版本常量定义类 40 | */ 41 | object ModuleVersion { 42 | 43 | /** 当前 GitHub 提交的 ID (CI 自动构建) */ 44 | const val GITHUB_COMMIT_ID = ModuleAppProperties.GITHUB_CI_COMMIT_ID 45 | 46 | /** 版本名称 */ 47 | const val NAME = BuildConfigWrapper.VERSION_NAME 48 | 49 | /** 版本号 */ 50 | const val CODE = BuildConfigWrapper.VERSION_CODE 51 | 52 | /** 是否为 CI 自动构建版本 */ 53 | val isCiMode = GITHUB_COMMIT_ID.isNotBlank() 54 | 55 | /** 当前版本名称后缀 */ 56 | val suffix = GITHUB_COMMIT_ID.let { if (it.isNotBlank()) "-$it" else "" } 57 | 58 | override fun toString() = "$NAME$suffix($CODE)" 59 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/data/enum/AppErrorsConfigType.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/1/20. 21 | */ 22 | package com.fankes.apperrorstracking.data.enum 23 | 24 | /** 25 | * 应用配置模版类型定义类 26 | */ 27 | enum class AppErrorsConfigType { 28 | /** 跟随全局配置 */ 29 | GLOBAL, 30 | 31 | /** 对话框 */ 32 | DIALOG, 33 | 34 | /** 通知 */ 35 | NOTIFY, 36 | 37 | /** Toast */ 38 | TOAST, 39 | 40 | /** 什么也不显示 */ 41 | NOTHING 42 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/data/factory/CompoundButtonFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/2/3. 21 | */ 22 | @file:Suppress("unused", "MemberVisibilityCanBePrivate") 23 | 24 | package com.fankes.apperrorstracking.data.factory 25 | 26 | import android.widget.CompoundButton 27 | import com.fankes.apperrorstracking.data.ConfigData 28 | import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData 29 | 30 | /** 31 | * 绑定到 [CompoundButton] 自动设置选中状态 32 | * @param data 键值数据模板 33 | * @param initiate 方法体 34 | */ 35 | fun CompoundButton.bind(data: PrefsData, initiate: CompoundButtonDataBinder.(CompoundButton) -> Unit = {}) { 36 | val binder = CompoundButtonDataBinder(button = this).also { initiate(it, this) } 37 | isChecked = ConfigData.getBoolean(data).also { binder.initializeCallback?.invoke(it) } 38 | binder.applyChangesCallback = { ConfigData.putBoolean(data, it) } 39 | setOnCheckedChangeListener { button, isChecked -> 40 | if (button.isPressed) { 41 | if (binder.isAutoApplyChanges) binder.applyChangesCallback?.invoke(isChecked) 42 | binder.changedCallback?.invoke(isChecked) 43 | } 44 | } 45 | } 46 | 47 | /** 48 | * [CompoundButton] 数据绑定管理器实例 49 | * @param button 当前实例 50 | */ 51 | class CompoundButtonDataBinder(private val button: CompoundButton) { 52 | 53 | /** 状态初始化回调事件 */ 54 | internal var initializeCallback: ((Boolean) -> Unit)? = null 55 | 56 | /** 状态改变回调事件 */ 57 | internal var changedCallback: ((Boolean) -> Unit)? = null 58 | 59 | /** 应用更改回调事件 */ 60 | internal var applyChangesCallback: ((Boolean) -> Unit)? = null 61 | 62 | /** 是否启用自动应用更改 */ 63 | var isAutoApplyChanges = true 64 | 65 | /** 66 | * 监听状态初始化 67 | * @param result 回调结果 68 | */ 69 | fun onInitialize(result: (Boolean) -> Unit) { 70 | initializeCallback = result 71 | } 72 | 73 | /** 74 | * 监听状态改变 75 | * @param result 回调结果 76 | */ 77 | fun onChanged(result: (Boolean) -> Unit) { 78 | changedCallback = result 79 | } 80 | 81 | /** 重新初始化 */ 82 | fun reinitialize() { 83 | initializeCallback?.invoke(button.isChecked) 84 | } 85 | 86 | /** 应用更改并重新初始化 */ 87 | fun applyChangesAndReinitialize() { 88 | applyChanges() 89 | reinitialize() 90 | } 91 | 92 | /** 应用更改 */ 93 | fun applyChanges() { 94 | applyChangesCallback?.invoke(button.isChecked) 95 | } 96 | 97 | /** 取消更改 */ 98 | fun cancelChanges() { 99 | button.isChecked = button.isChecked.not() 100 | } 101 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/hook/HookEntry.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/7. 21 | */ 22 | package com.fankes.apperrorstracking.hook 23 | 24 | import com.fankes.apperrorstracking.data.ConfigData 25 | import com.fankes.apperrorstracking.generated.locale.ModuleAppLocale 26 | import com.fankes.apperrorstracking.hook.entity.FrameworkHooker 27 | import com.fankes.apperrorstracking.locale.locale 28 | import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed 29 | import com.highcapable.yukihookapi.hook.factory.configs 30 | import com.highcapable.yukihookapi.hook.factory.encase 31 | import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit 32 | 33 | @InjectYukiHookWithXposed(entryClassName = "AppErrorsTracking", isUsingResourcesHook = false) 34 | object HookEntry : IYukiHookXposedInit { 35 | 36 | override fun onInit() = configs { 37 | debugLog { 38 | tag = "AppErrorsTracking" 39 | isRecord = true 40 | } 41 | isDebug = false 42 | } 43 | 44 | override fun onHook() = encase { 45 | loadSystem { 46 | locale = ModuleAppLocale.attach { moduleAppResources } 47 | ConfigData.init(this) 48 | loadHooker(FrameworkHooker) 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/locale/LocaleFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/10/13. 21 | */ 22 | @file:Suppress("StaticFieldLeak") 23 | 24 | package com.fankes.apperrorstracking.locale 25 | 26 | import com.fankes.apperrorstracking.generated.locale.ModuleAppLocale 27 | 28 | /** I18ns 实例 */ 29 | lateinit var locale: ModuleAppLocale -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/service/QuickStartTileService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/11. 21 | */ 22 | package com.fankes.apperrorstracking.service 23 | 24 | import android.service.quicksettings.TileService 25 | import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity 26 | import com.fankes.apperrorstracking.utils.factory.navigate 27 | 28 | class QuickStartTileService : TileService() { 29 | 30 | override fun onClick() { 31 | super.onClick() 32 | /** 启动异常历史记录窗口 */ 33 | navigate() 34 | } 35 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/ui/activity/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/7. 21 | */ 22 | @file:Suppress("DEPRECATION") 23 | 24 | package com.fankes.apperrorstracking.ui.activity.base 25 | 26 | import android.app.ActivityManager 27 | import android.content.Intent 28 | import android.os.Build 29 | import android.os.Bundle 30 | import androidx.appcompat.app.AppCompatActivity 31 | import androidx.core.content.res.ResourcesCompat 32 | import androidx.core.view.WindowCompat 33 | import androidx.viewbinding.ViewBinding 34 | import com.fankes.apperrorstracking.R 35 | import com.fankes.apperrorstracking.utils.factory.isNotSystemInDarkMode 36 | import com.fankes.apperrorstracking.utils.factory.toast 37 | import com.highcapable.yukihookapi.hook.factory.current 38 | import com.highcapable.yukihookapi.hook.factory.method 39 | import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass 40 | 41 | abstract class BaseActivity : AppCompatActivity() { 42 | 43 | /** 获取绑定布局对象 */ 44 | lateinit var binding: VB 45 | 46 | override fun onCreate(savedInstanceState: Bundle?) { 47 | super.onCreate(savedInstanceState) 48 | binding = current().generic()?.argument()?.method { 49 | name = "inflate" 50 | param(LayoutInflaterClass) 51 | }?.get()?.invoke(layoutInflater) ?: error("binding failed") 52 | if (Build.VERSION.SDK_INT >= 35) binding.root.fitsSystemWindows = true 53 | setContentView(binding.root) 54 | /** 隐藏系统的标题栏 */ 55 | supportActionBar?.hide() 56 | /** 初始化沉浸状态栏 */ 57 | WindowCompat.getInsetsController(window, window.decorView).apply { 58 | isAppearanceLightStatusBars = isNotSystemInDarkMode 59 | isAppearanceLightNavigationBars = isNotSystemInDarkMode 60 | } 61 | ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also { 62 | window?.statusBarColor = it 63 | window?.navigationBarColor = it 64 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) window?.navigationBarDividerColor = it 65 | } 66 | /** 装载子类 */ 67 | onCreate() 68 | } 69 | 70 | /** 回调 [onCreate] 方法 */ 71 | abstract fun onCreate() 72 | 73 | /** 74 | * 在旧版的 Android 系统中使用了 activity-alias 标签从启动器启动 Activity 会造成其组件名称 (完整类名) 为代理名称 75 | * 76 | * 为了获取真实的顶层 Activity 组件名称 (完整类名) - 如果名称不正确将自动执行一次结束并重新打开当前 Activity 77 | */ 78 | fun checkingTopComponentName() { 79 | /** 当前顶层的 Activity 组件名称 (完整类名) */ 80 | val topComponentName = runCatching { 81 | @Suppress("DEPRECATION") 82 | (getSystemService(ACTIVITY_SERVICE) as? ActivityManager?) 83 | ?.getRunningTasks(9999)?.firstOrNull()?.topActivity?.className ?: "" 84 | }.getOrNull() ?: "" 85 | if (topComponentName.isNotBlank() && topComponentName != javaClass.name) { 86 | finish() 87 | startActivity(Intent(this, javaClass)) 88 | } 89 | } 90 | 91 | /** 92 | * 弹出提示并退出 93 | * @param name 名称 94 | */ 95 | fun toastAndFinish(name: String) { 96 | toast(msg = "Invalid $name, exit") 97 | finish() 98 | } 99 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsMutedActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/3. 21 | */ 22 | package com.fankes.apperrorstracking.ui.activity.errors 23 | 24 | import androidx.core.view.isVisible 25 | import com.fankes.apperrorstracking.bean.MutedErrorsAppBean 26 | import com.fankes.apperrorstracking.databinding.ActivityAppErrorsMutedBinding 27 | import com.fankes.apperrorstracking.databinding.AdapterAppErrorsMutedBinding 28 | import com.fankes.apperrorstracking.locale.locale 29 | import com.fankes.apperrorstracking.ui.activity.base.BaseActivity 30 | import com.fankes.apperrorstracking.utils.factory.appIconOf 31 | import com.fankes.apperrorstracking.utils.factory.appNameOf 32 | import com.fankes.apperrorstracking.utils.factory.bindAdapter 33 | import com.fankes.apperrorstracking.utils.factory.showDialog 34 | import com.fankes.apperrorstracking.utils.tool.FrameworkTool 35 | 36 | class AppErrorsMutedActivity : BaseActivity() { 37 | 38 | /** 回调适配器改变 */ 39 | private var onChanged: (() -> Unit)? = null 40 | 41 | /** 全部的已忽略异常的 APP 信息 */ 42 | private val listData = ArrayList() 43 | 44 | override fun onCreate() { 45 | binding.titleBackIcon.setOnClickListener { onBackPressed() } 46 | binding.unmuteAllIcon.setOnClickListener { 47 | showDialog { 48 | title = locale.notice 49 | msg = locale.areYouSureUnmuteAll 50 | confirmButton { FrameworkTool.unmuteAllErrorsApps(context) { refreshData() } } 51 | cancelButton() 52 | } 53 | } 54 | /** 设置列表元素和 Adapter */ 55 | binding.listView.bindAdapter { 56 | onBindDatas { listData } 57 | onBindViews { binding, position -> 58 | listData[position].also { bean -> 59 | binding.appIcon.setImageDrawable(appIconOf(bean.packageName)) 60 | binding.appNameText.text = appNameOf(bean.packageName).ifBlank { bean.packageName } 61 | binding.muteTypeText.text = when (bean.type) { 62 | MutedErrorsAppBean.MuteType.UNTIL_UNLOCKS -> locale.muteIfUnlock 63 | MutedErrorsAppBean.MuteType.UNTIL_REBOOTS -> locale.muteIfRestart 64 | } 65 | binding.unmuteButton.setOnClickListener { FrameworkTool.unmuteErrorsApp(context, bean) { refreshData() } } 66 | } 67 | } 68 | }.apply { onChanged = { notifyDataSetChanged() } } 69 | } 70 | 71 | /** 更新列表数据 */ 72 | private fun refreshData() { 73 | FrameworkTool.fetchMutedErrorsAppsData(context = this) { 74 | listData.clear() 75 | it.takeIf { e -> e.isNotEmpty() }?.forEach { e -> listData.add(e) } 76 | onChanged?.invoke() 77 | binding.unmuteAllIcon.isVisible = listData.isNotEmpty() 78 | binding.listView.isVisible = listData.isNotEmpty() 79 | binding.listNoDataView.isVisible = listData.isEmpty() 80 | } 81 | } 82 | 83 | override fun onResume() { 84 | super.onResume() 85 | /** 执行更新 */ 86 | refreshData() 87 | } 88 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/ui/widget/ItemLinearLayout.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/1. 21 | */ 22 | package com.fankes.apperrorstracking.ui.widget 23 | 24 | import android.content.Context 25 | import android.util.AttributeSet 26 | import android.view.Gravity 27 | import android.widget.LinearLayout 28 | import com.fankes.apperrorstracking.utils.factory.dp 29 | import top.defaults.drawabletoolbox.DrawableBuilder 30 | 31 | class ItemLinearLayout(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { 32 | 33 | init { 34 | gravity = Gravity.CENTER or Gravity.START 35 | background = DrawableBuilder() 36 | .rounded() 37 | .cornerRadius(15.dp(context)) 38 | .ripple() 39 | .rippleColor(0xFFAAAAAA.toInt()) 40 | .build() 41 | } 42 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/ui/widget/MaterialSwitch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/5/14. 21 | */ 22 | @file:Suppress("SameParameterValue") 23 | 24 | package com.fankes.apperrorstracking.ui.widget 25 | 26 | import android.content.Context 27 | import android.content.res.ColorStateList 28 | import android.graphics.Color 29 | import android.text.TextUtils 30 | import android.util.AttributeSet 31 | import androidx.appcompat.widget.SwitchCompat 32 | import com.fankes.apperrorstracking.utils.factory.dp 33 | import com.fankes.apperrorstracking.utils.factory.isSystemInDarkMode 34 | import top.defaults.drawabletoolbox.DrawableBuilder 35 | 36 | class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) { 37 | 38 | private fun toColors(selected: Int, pressed: Int, normal: Int): ColorStateList { 39 | val colors = intArrayOf(selected, pressed, normal) 40 | val states = arrayOfNulls(3) 41 | states[0] = intArrayOf(android.R.attr.state_checked) 42 | states[1] = intArrayOf(android.R.attr.state_pressed) 43 | states[2] = intArrayOf() 44 | return ColorStateList(states, colors) 45 | } 46 | 47 | private val thumbColor get() = if (context.isSystemInDarkMode) 0xFF7C7C7C else 0xFFCCCCCC 48 | 49 | init { 50 | trackDrawable = DrawableBuilder() 51 | .rectangle() 52 | .rounded() 53 | .solidColor(0xFF656565.toInt()) 54 | .height(20.dp(context)) 55 | .cornerRadius(15.dp(context)) 56 | .build() 57 | thumbDrawable = DrawableBuilder() 58 | .rectangle() 59 | .rounded() 60 | .solidColor(Color.WHITE) 61 | .size(20.dp(context), 20.dp(context)) 62 | .cornerRadius(20.dp(context)) 63 | .strokeWidth(8.dp(context)) 64 | .strokeColor(Color.TRANSPARENT) 65 | .build() 66 | trackTintList = toColors( 67 | 0xFF656565.toInt(), 68 | thumbColor.toInt(), 69 | thumbColor.toInt() 70 | ) 71 | isSingleLine = true 72 | ellipsize = TextUtils.TruncateAt.END 73 | } 74 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/factory/BaseAdapterFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/6/3. 21 | */ 22 | package com.fankes.apperrorstracking.utils.factory 23 | 24 | import android.content.Context 25 | import android.view.LayoutInflater 26 | import android.view.View 27 | import android.view.ViewGroup 28 | import android.widget.BaseAdapter 29 | import android.widget.ListView 30 | import androidx.viewbinding.ViewBinding 31 | import com.highcapable.yukihookapi.hook.factory.method 32 | import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass 33 | 34 | /** 35 | * 绑定 [BaseAdapter] 到 [ListView] 36 | * @param initiate 方法体 37 | * @return [BaseAdapter] 38 | */ 39 | inline fun ListView.bindAdapter(initiate: BaseAdapterCreater.() -> Unit) = 40 | BaseAdapterCreater(context).apply(initiate).baseAdapter?.apply { adapter = this } ?: error("BaseAdapter not binded") 41 | 42 | /** 43 | * [BaseAdapter] 创建类 44 | * @param context 实例 45 | */ 46 | class BaseAdapterCreater(val context: Context) { 47 | 48 | /** 当前 [List] 回调 */ 49 | var listDataCallback: (() -> List<*>)? = null 50 | 51 | /** 当前 [BaseAdapter] */ 52 | var baseAdapter: BaseAdapter? = null 53 | 54 | /** 55 | * 绑定 [List] 到 [ListView] 56 | * @param result 回调数据 57 | */ 58 | fun onBindDatas(result: (() -> List<*>)) { 59 | listDataCallback = result 60 | } 61 | 62 | /** 63 | * 绑定 [BaseAdapter] 到 [ListView] 64 | * @param bindViews 回调 - ([VB] 每项,[Int] 下标) 65 | */ 66 | inline fun onBindViews(crossinline bindViews: (binding: VB, position: Int) -> Unit) { 67 | baseAdapter = object : BaseAdapter() { 68 | override fun getCount() = listDataCallback?.let { it() }?.size ?: 0 69 | override fun getItem(position: Int) = listDataCallback?.let { it() }?.get(position) 70 | override fun getItemId(position: Int) = position.toLong() 71 | override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { 72 | var holderView = convertView 73 | val holder: VB 74 | if (convertView == null) { 75 | holder = VB::class.java.method { 76 | name = "inflate" 77 | param(LayoutInflaterClass) 78 | }.get().invoke(LayoutInflater.from(context)) ?: error("ViewHolder binding failed") 79 | holderView = holder.root.apply { tag = holder } 80 | } else holder = convertView.tag as VB 81 | bindViews(holder, position) 82 | return holderView ?: error("ViewHolder binding failed") 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/factory/GsonFormatFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/10/3. 21 | */ 22 | package com.fankes.apperrorstracking.utils.factory 23 | 24 | import com.google.gson.Gson 25 | import com.google.gson.GsonBuilder 26 | import com.google.gson.JsonIOException 27 | import com.google.gson.JsonSyntaxException 28 | import com.google.gson.reflect.TypeToken 29 | 30 | /** 31 | * 创建 [Gson] 实例 32 | * @return [Gson] 33 | */ 34 | val GSON by lazy { GsonBuilder().setLenient().create() ?: error("Gson create failed") } 35 | 36 | /** 37 | * 实体类转 Json 字符串 38 | * @return [String] 39 | * @throws [JsonIOException] 如果不是有效的 Json 数据 40 | */ 41 | fun Any?.toJson() = GSON.toJson(this) ?: "" 42 | 43 | /** 44 | * 实体类转 Json 字符串 45 | * @return [String] or null 46 | */ 47 | fun Any?.toJsonOrNull() = runCatching { toJson() }.getOrNull() 48 | 49 | /** 50 | * Json 字符串转实体类 51 | * @return [T] or null 52 | * @throws [JsonSyntaxException] 如果 Json 格式不正确 53 | */ 54 | inline fun String.toEntity(): T? = takeIf { it.isNotBlank() }.let { GSON.fromJson(this, object : TypeToken() {}.type) } 55 | 56 | /** 57 | * Json 字符串转实体类 58 | * @return [T] or null 59 | */ 60 | inline fun String.toEntityOrNull(): T? = runCatching { toEntity() }.getOrNull() -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/factory/ThreadPoolFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/10/3. 21 | */ 22 | package com.fankes.apperrorstracking.utils.factory 23 | 24 | import java.util.concurrent.ExecutorService 25 | import java.util.concurrent.Executors 26 | 27 | /** 28 | * 创建当前线程池服务 29 | * @return [ExecutorService] 30 | */ 31 | private val currentThreadPool get() = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) 32 | 33 | /** 34 | * 创建并启动新的临时线程池 35 | * 36 | * 等待 [block] 执行完成并自动释放 37 | * @param block 方法块 38 | */ 39 | fun newThread(block: () -> Unit) { 40 | currentThreadPool.apply { 41 | execute { 42 | block() 43 | shutdown() 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/tool/AppAnalyticsTool.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2022/10/5. 21 | */ 22 | @file:Suppress("unused") 23 | 24 | package com.fankes.apperrorstracking.utils.tool 25 | 26 | import android.app.Application 27 | import android.widget.CompoundButton 28 | import com.fankes.apperrorstracking.generated.ModuleAppProperties 29 | import com.highcapable.yukihookapi.hook.factory.prefs 30 | import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData 31 | import com.microsoft.appcenter.AppCenter 32 | import com.microsoft.appcenter.analytics.Analytics 33 | import com.microsoft.appcenter.crashes.Crashes 34 | 35 | /** 36 | * Microsoft App Center 工具 37 | */ 38 | object AppAnalyticsTool { 39 | 40 | /** App Secret */ 41 | private const val APP_CENTER_SECRET = ModuleAppProperties.APP_CENTER_SECRET 42 | 43 | /** 启用匿名统计收集使用情况功能 */ 44 | private val ENABLE_APP_CENTER_ANALYTICS = PrefsData("_enable_app_center_analytics", true) 45 | 46 | /** 当前实例 */ 47 | private var instance: Application? = null 48 | 49 | /** 50 | * 是否启用匿名统计收集使用情况功能 51 | * @return [Boolean] 52 | */ 53 | private var isEnableAppCenterAnalytics 54 | get() = instance?.prefs()?.get(ENABLE_APP_CENTER_ANALYTICS) ?: true 55 | set(value) { 56 | instance?.prefs()?.edit { put(ENABLE_APP_CENTER_ANALYTICS, value) } 57 | } 58 | 59 | /** 是否可用 */ 60 | val isAvailable = APP_CENTER_SECRET.isNotBlank() 61 | 62 | /** 绑定到 [CompoundButton] 自动设置选中状态 */ 63 | fun CompoundButton.bindAppAnalytics() { 64 | isChecked = isEnableAppCenterAnalytics 65 | setOnCheckedChangeListener { button, isChecked -> 66 | if (button.isPressed.not()) return@setOnCheckedChangeListener 67 | isEnableAppCenterAnalytics = isChecked 68 | } 69 | } 70 | 71 | /** 72 | * 上传分析日志 73 | * @param name 事件名称 74 | * @param data 事件详细内容 - 默认空 75 | */ 76 | fun trackEvent(name: String, data: HashMap? = null) { 77 | if (data != null) Analytics.trackEvent(name, data) 78 | else Analytics.trackEvent(name) 79 | } 80 | 81 | /** 82 | * 初始化 App Center 83 | * @param instance 实例 84 | */ 85 | fun init(instance: Application) { 86 | this.instance = instance 87 | if (isEnableAppCenterAnalytics && isAvailable) 88 | AppCenter.start(instance, APP_CENTER_SECRET, Analytics::class.java, Crashes::class.java) 89 | } 90 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/tool/GithubReleaseTool.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/1/23. 21 | */ 22 | package com.fankes.apperrorstracking.utils.tool 23 | 24 | import android.app.Activity 25 | import android.content.Context 26 | import android.icu.text.SimpleDateFormat 27 | import android.icu.util.Calendar 28 | import android.icu.util.TimeZone 29 | import com.fankes.apperrorstracking.locale.locale 30 | import com.fankes.apperrorstracking.utils.factory.openBrowser 31 | import com.fankes.apperrorstracking.utils.factory.showDialog 32 | import okhttp3.Call 33 | import okhttp3.Callback 34 | import okhttp3.OkHttpClient 35 | import okhttp3.Request 36 | import okhttp3.Response 37 | import org.json.JSONObject 38 | import java.io.IOException 39 | import java.io.Serializable 40 | import java.util.Locale 41 | 42 | /** 43 | * 获取 GitHub Release 最新版本工具类 44 | */ 45 | object GithubReleaseTool { 46 | 47 | /** 仓库作者 */ 48 | private const val REPO_AUTHOR = "KitsunePie" 49 | 50 | /** 仓库名称 */ 51 | private const val REPO_NAME = "AppErrorsTracking" 52 | 53 | /** 54 | * 获取最新版本信息 55 | * @param context 实例 56 | * @param version 当前版本 57 | * @param result 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体) 58 | */ 59 | fun checkingForUpdate(context: Context, version: String, result: (String, () -> Unit) -> Unit) = runCatching { 60 | OkHttpClient().newBuilder().build().newCall( 61 | Request.Builder() 62 | .url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest") 63 | .get() 64 | .build() 65 | ).enqueue(object : Callback { 66 | override fun onFailure(call: Call, e: IOException) {} 67 | 68 | override fun onResponse(call: Call, response: Response) = runCatching { 69 | JSONObject(response.body.string()).apply { 70 | GithubReleaseBean( 71 | name = getString("name"), 72 | htmlUrl = getString("html_url"), 73 | content = getString("body"), 74 | date = getString("published_at").localTime() 75 | ).apply { 76 | fun showUpdate() = context.showDialog { 77 | title = locale.latestVersion(name) 78 | msg = locale.latestVersionTip(date, content) 79 | confirmButton(locale.updateNow) { context.openBrowser(htmlUrl) } 80 | cancelButton() 81 | } 82 | if (name != version) (context as? Activity?)?.runOnUiThread { 83 | showUpdate() 84 | result(name) { showUpdate() } 85 | } 86 | } 87 | } 88 | }.getOrNull().let {} 89 | }) 90 | }.getOrNull().let {} 91 | 92 | /** 93 | * 格式化时间为本地时区 94 | * @return [String] 本地时区时间 95 | */ 96 | private fun String.localTime() = replace("T", " ").replace("Z", "").let { 97 | runCatching { 98 | val local = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone } 99 | val current = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") } 100 | local.format(current.parse(it)) 101 | }.getOrNull() ?: it 102 | } 103 | 104 | /** 105 | * GitHub Release bean 106 | * @param name 版本名称 107 | * @param htmlUrl 网页地址 108 | * @param content 更新日志 109 | * @param date 发布时间 110 | */ 111 | private data class GithubReleaseBean( 112 | var name: String, 113 | var htmlUrl: String, 114 | var content: String, 115 | var date: String 116 | ) : Serializable 117 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/utils/tool/StackTraceShareHelper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/11/3. 21 | */ 22 | package com.fankes.apperrorstracking.utils.tool 23 | 24 | import android.content.Context 25 | import com.fankes.apperrorstracking.databinding.DiaStackTraceShareBinding 26 | import com.fankes.apperrorstracking.utils.factory.showDialog 27 | 28 | /** 29 | * 异常堆栈分享工具类 30 | */ 31 | object StackTraceShareHelper { 32 | 33 | /** 34 | * 显示分享选择器 35 | * @param context 当前实例 36 | * @param title 对话框标题 37 | * @param onChoose 回调选择的结果 38 | */ 39 | fun showChoose( 40 | context: Context, 41 | title: String, 42 | onChoose: (sDeviceBrand: Boolean, sDeviceModel: Boolean, sDisplay: Boolean, sPackageName: Boolean) -> Unit 43 | ) { 44 | context.showDialog { 45 | this.title = title 46 | confirmButton { 47 | val sDeviceBrand = binding.configCheck0.isChecked 48 | val sDeviceModel = binding.configCheck1.isChecked 49 | val sDisplay = binding.configCheck2.isChecked 50 | val sPackageName = binding.configCheck3.isChecked 51 | onChoose(sDeviceBrand, sDeviceModel, sDisplay, sPackageName) 52 | cancel() 53 | } 54 | cancelButton() 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /module-app/src/main/java/com/fankes/apperrorstracking/wrapper/BuildConfigWrapper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. 3 | * Copyright (C) 2017 Fankes Studio(qzmmcn@163.com) 4 | * https://github.com/KitsunePie/AppErrorsTracking 5 | * 6 | * This software is non-free but opensource software: you can redistribute it 7 | * and/or modify it under the terms of the GNU Affero General Public License 8 | * as published by the Free Software Foundation; either 9 | * version 3 of the License, or any later version. 10 | * 11 | * This software is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * and eula along with this software. If not, see 18 | * 19 | * 20 | * This file is created by fankes on 2023/9/19. 21 | */ 22 | @file:Suppress("unused") 23 | 24 | package com.fankes.apperrorstracking.wrapper 25 | 26 | import com.fankes.apperrorstracking.BuildConfig 27 | 28 | /** 29 | * 对 [BuildConfig] 的包装 30 | */ 31 | object BuildConfigWrapper { 32 | const val APPLICATION_ID = BuildConfig.APPLICATION_ID 33 | const val VERSION_NAME = BuildConfig.VERSION_NAME 34 | const val VERSION_CODE = BuildConfig.VERSION_CODE 35 | val isDebug = BuildConfig.DEBUG 36 | } -------------------------------------------------------------------------------- /module-app/src/main/res/drawable-night/bg_dark_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable-night/bg_permotion_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable-night/bg_permotion_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_black_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_blue_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_button_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_dark_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_green_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_logger_d_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_logger_e_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_logger_i_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_logger_w_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_orange_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_permotion_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_permotion_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_red_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_stack_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/bg_yellow_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_android.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 15 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_appcenter.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_baseline_bug_report.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_baseline_close.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_baseline_eject.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_baseline_info.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_baseline_refresh.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_batch.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_clear.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_copy.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_cpp.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_debug.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_exception.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_export.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_filter.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_function.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 27 | 34 | 40 | 46 | 52 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_github.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_global.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_home.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 19 | 25 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_java.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 14 | 17 | 20 | 23 | 26 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_notify.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_preference.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_print.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_refresh.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_restart.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_statistics.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_success.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_theme.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 16 | 22 | 28 | 34 | -------------------------------------------------------------------------------- /module-app/src/main/res/drawable/ic_warn.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/activity_app_errors_display.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/activity_app_errors_muted.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 31 | 32 | 42 | 43 | 52 | 53 | 54 | 58 | 59 | 69 | 70 | 84 | 85 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/adapter_app_errors_muted.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 19 | 20 | 24 | 25 | 26 | 34 | 35 | 45 | 46 | 54 | 55 | 56 | 67 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/adapter_app_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 19 | 20 | 24 | 25 | 26 | 33 | 34 | 44 | 45 | 53 | 54 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/adapter_logger.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 24 | 25 | 32 | 33 | 42 | 43 | 52 | 53 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/dia_app_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 24 | 25 | 33 | 34 | 41 | 42 | 49 | 50 | 57 | 58 | 65 | 66 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/dia_apps_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 22 | 23 | 24 | 29 | 30 | 39 | 40 | 48 | 49 | 56 | 57 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/dia_logger_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 | 23 | 30 | 31 | 38 | 39 | 46 | 47 | 54 | -------------------------------------------------------------------------------- /module-app/src/main/res/layout/dia_stack_trace_share.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 | 23 | 33 | 34 | 41 | 42 | 49 | 50 | 57 | 58 | 65 | 66 | 73 | -------------------------------------------------------------------------------- /module-app/src/main/res/menu/menu_list_detail_action.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /module-app/src/main/res/menu/menu_logger_action.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxhdpi/bg_payment_code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxhdpi/bg_payment_code.jpg -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxhdpi/ic_yukihookapi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxhdpi/ic_yukihookapi.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /module-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KitsunePie/AppErrorsTracking/5a60ef47b52f734416f705e3f892de461c348489/module-app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /module-app/src/main/res/values-night/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF2D2D2D 4 | #FFCFCFCF 5 | #FFD3D3D3 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | -------------------------------------------------------------------------------- /module-app/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | android 5 | 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | #FF777777 5 | #FF323B42 6 | -------------------------------------------------------------------------------- /module-app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #656565 4 | #FF000000 5 | #FFFFFFFF 6 | #00000000 7 | -------------------------------------------------------------------------------- /module-app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF6200 4 | -------------------------------------------------------------------------------- /module-app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 28 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /module-app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module-app/src/main/res/xml/locales_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /module-app/src/test/java/com/fankes/apperrorstracking/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.fankes.apperrorstracking 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | plugins { 9 | id("com.highcapable.sweetdependency") version "1.0.4" 10 | id("com.highcapable.sweetproperty") version "1.0.5" 11 | } 12 | sweetProperty { 13 | global { 14 | all { 15 | permanentKeyValues( 16 | "GITHUB_CI_COMMIT_ID" to "", 17 | "APP_CENTER_SECRET" to "" 18 | ) 19 | generateFrom(ROOT_PROJECT, SYSTEM_ENV) 20 | } 21 | sourcesCode { 22 | propertiesFileNames(".secret/secret.properties") 23 | includeKeys("GITHUB_CI_COMMIT_ID", "APP_CENTER_SECRET") 24 | // 关闭类型自动转换功能,防止一些特殊 "COMMIT ID" 被生成为数值 25 | isEnableTypeAutoConversion = false 26 | } 27 | } 28 | rootProject { all { isEnable = false } } 29 | } 30 | rootProject.name = "AppErrorsTracking" 31 | include(":module-app", ":demo-app") --------------------------------------------------------------------------------