From d1798456f17dfae691afaf58558d307585b626ae Mon Sep 17 00:00:00 2001 From: PatrickMis <24607131+PatrickMis@users.noreply.github.com> Date: Wed, 23 Nov 2022 15:06:28 +0100 Subject: [PATCH] wip: refactor to BAR --- .gitignore | 10 +- CHANGELOG.md | 317 -------------- README.md | 182 +------- RELEASE.md | 4 +- app/build.gradle.kts | 402 ++---------------- app/magisk/customize.sh | 43 -- app/magisk/update-binary | 44 -- app/magisk/updater-script | 1 - app/magisk/updates/release/changelog.txt | 1 - app/magisk/updates/release/info.json | 6 - app/proguard-rules.pro | 5 +- .../chiller3/bcr/ExampleInstrumentedTest.kt | 24 -- app/src/main/AndroidManifest.xml | 42 +- .../com/chiller3/bcr/RecorderInCallService.kt | 319 -------------- .../com/chiller3/bcr/RecorderTileService.kt | 64 --- .../patrykmis/bar}/AudioFormatExtension.kt | 2 +- .../com/patrykmis/bar}/ChipGroupCentered.kt | 2 +- .../patrykmis/bar}/DocumentFileExtensions.kt | 2 +- .../com/patrykmis/bar}/FilenameTemplate.kt | 4 +- .../patrykmis/bar}/LongClickablePreference.kt | 2 +- .../bar}/NotificationActionService.kt | 2 +- .../com/patrykmis/bar}/Notifications.kt | 2 +- .../bar}/OpenPersistentDocumentTree.kt | 2 +- .../com/patrykmis/bar}/OutputDirUtils.kt | 2 +- .../OutputDirectoryBottomSheetFragment.kt | 4 +- .../com/patrykmis/bar}/OutputFile.kt | 2 +- .../bar}/OutputFormatBottomSheetFragment.kt | 8 +- .../com/patrykmis/bar}/Permissions.kt | 8 +- .../com/patrykmis/bar}/Preferences.kt | 6 +- .../com/patrykmis/bar}/RecorderApplication.kt | 2 +- .../patrykmis/bar}/RecorderMicTileService.kt | 2 +- .../com/patrykmis/bar}/RecorderProvider.kt | 4 +- .../com/patrykmis/bar}/RecorderThread.kt | 19 +- .../com/patrykmis/bar}/Retention.kt | 2 +- .../com/patrykmis/bar}/SettingsActivity.kt | 16 +- .../com/patrykmis/bar}/UriExtensions.kt | 2 +- .../com/patrykmis/bar}/format/AacFormat.kt | 2 +- .../com/patrykmis/bar}/format/Container.kt | 2 +- .../com/patrykmis/bar}/format/Encoder.kt | 2 +- .../patrykmis/bar}/format/FlacContainer.kt | 2 +- .../com/patrykmis/bar}/format/FlacFormat.kt | 2 +- .../com/patrykmis/bar}/format/Format.kt | 6 +- .../patrykmis/bar}/format/FormatParamInfo.kt | 2 +- .../bar}/format/MediaCodecEncoder.kt | 2 +- .../bar}/format/MediaMuxerContainer.kt | 2 +- .../com/patrykmis/bar}/format/OpusFormat.kt | 2 +- .../bar}/format/PassthroughEncoder.kt | 2 +- .../com/patrykmis/bar}/format/SampleRate.kt | 7 +- .../patrykmis/bar}/format/WaveContainer.kt | 2 +- .../com/patrykmis/bar}/format/WaveFormat.kt | 2 +- .../res/layout/output_format_bottom_sheet.xml | 4 +- .../main/res/raw/filename_template.properties | 8 +- app/src/main/res/values-es/strings.xml | 10 +- app/src/main/res/values-fr/strings.xml | 8 +- app/src/main/res/values-iw/strings.xml | 12 +- app/src/main/res/values-pl/strings.xml | 10 +- app/src/main/res/values-ru/strings.xml | 8 +- app/src/main/res/values-sk/strings.xml | 12 +- app/src/main/res/values-tr/strings.xml | 8 +- app/src/main/res/values/strings.xml | 12 +- app/src/main/res/values/themes.xml | 2 +- app/src/main/res/xml/root_preferences.xml | 2 +- .../java/com/chiller3/bcr/ExampleUnitTest.kt | 17 - build.gradle.kts | 14 +- gradle.properties | 2 + settings.gradle.kts | 9 +- 66 files changed, 181 insertions(+), 1553 deletions(-) delete mode 100644 app/magisk/customize.sh delete mode 100644 app/magisk/update-binary delete mode 100644 app/magisk/updater-script delete mode 100644 app/magisk/updates/release/changelog.txt delete mode 100644 app/magisk/updates/release/info.json delete mode 100644 app/src/androidTest/java/com/chiller3/bcr/ExampleInstrumentedTest.kt delete mode 100644 app/src/main/java/com/chiller3/bcr/RecorderInCallService.kt delete mode 100644 app/src/main/java/com/chiller3/bcr/RecorderTileService.kt rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/AudioFormatExtension.kt (80%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/ChipGroupCentered.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/DocumentFileExtensions.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/FilenameTemplate.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/LongClickablePreference.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/NotificationActionService.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/Notifications.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/OpenPersistentDocumentTree.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/OutputDirUtils.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/OutputDirectoryBottomSheetFragment.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/OutputFile.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/OutputFormatBottomSheetFragment.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/Permissions.kt (89%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/Preferences.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/RecorderApplication.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/RecorderMicTileService.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/RecorderProvider.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/RecorderThread.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/Retention.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/SettingsActivity.kt (95%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/UriExtensions.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/AacFormat.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/Container.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/Encoder.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/FlacContainer.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/FlacFormat.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/Format.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/FormatParamInfo.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/MediaCodecEncoder.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/MediaMuxerContainer.kt (96%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/OpusFormat.kt (97%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/PassthroughEncoder.kt (98%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/SampleRate.kt (89%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/WaveContainer.kt (99%) rename app/src/main/{java/com/chiller3/bcr => kotlin/com/patrykmis/bar}/format/WaveFormat.kt (96%) delete mode 100644 app/src/test/java/com/chiller3/bcr/ExampleUnitTest.kt diff --git a/.gitignore b/.gitignore index faf530b2d..16db17273 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ -*.iml -.gradle +/.gradle /local.properties -/.idea/ +/.idea .DS_Store /build -/captures -.externalNativeBuild -.cxx -local.properties +/keystore.properties diff --git a/CHANGELOG.md b/CHANGELOG.md index 3582c0952..0358e1eef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,320 +1,3 @@ -### Version 1.39 - -* Update Russian translations (PR: #277, @bogachenko) -* Add Simplified Chinese translations (PR: #283, @Yee2) - -### Version 1.38 - -* Update all dependencies (PR: #266, #272, @PatrykMis) -* Mark quick settings tile as toggleable for accessibility (PR: #270, @PatrykMis) -* Add support for Android 13's per-app language preferences (PR: #271, @PatrykMis) -* Fix crash when changing the output directory if the previous output directory was associated with a cloud provider app that is no longer installed (PR: #273, @chenxiaolong) -* Show friendly path name instead of `content://` when the output directory points to a cloud provider app (PR: #274, @chenxiaolong) - -### Version 1.37 - -* Fix custom filename templates breaking after version 1.35 in release builds (Issue: #260, PR: #261, @chenxiaolong) - -### Version 1.36 - -* Fix loss of file extension when the output file needs to be renamed (PR: #259, @chenxiaolong) - -### Version 1.35 - -* Fix missing BCR app when doing a direct (non-Magisk module) installation (Issue: #253, PR: #254, @chenxiaolong) - * This bug was introduced in version 1.34 and was caused by an oversight when adding the workaround for overlayfs. -* Work around absurdly slow SAF (Android Storage Access Framework) on some devices (Issue: #252, PR: #257, @chenxiaolong) - * This fixes audio being chopped off the beginning of the call recording. Some devices' SAF implementations are slow to the point where checking the existence of a file may take upwards of 8 seconds (vs. 2ms with native file access). - * This only affected users who picked a custom output directory. The default output directory uses native file access instead of SAF. -* Fix caller ID and contact name potentially ending up in the log file if they change during the middle of a call (PR: #258, @chenxiaolong) - -### Version 1.34 - -* Write `crash.log` to output directory if BCR crashes outside of the scope of a phone call (Issue: #243, PR: #245, @chenxiaolong) -* Set default notification importance to high for the persistent notification during a all (Issue: #248, PR: #249, @chenxiaolong) - * This makes it easier to access the pause/resume button in the notification. - * This change only affects new installs and the user's notification preferences in Android's settings will always take precedence. -* Work around broken NFC and possible bootloops on MIUI when `/system` contains overlayfs mount points (Issue: #242, #246, PR: #250, @chenxiaolong) - * This is only a workaround for a bug in Magisk's mount logic. The actual Magisk bug will be fixed by: https://github.com/topjohnwu/Magisk/pull/6588. - -### Version 1.33 - -* Fix crash caused by a workaround for a old material3 library bug that has since been fixed (Issue: #240, PR: #241, @chenxiaolong) - -### Version 1.32 - -* Add Hebrew translations (PR: #232, @Mosheh65) - -### Version 1.31 - -* For the OGG/Opus bitrate option, reduce the number of steps between 6 kbps and 510 kbps from 253 to 25 (Issue: #237, PR: #239, @chenxiaolong) - -Non-user-facing changes: - -* Updated all dependencies (PR: #238, @chenxiaolong) - -Signing changes: - -* Switch from GPG signing to SSH signing for new release zips, git commits, and git tags (PR: #229, @chenxiaolong) - * The goal is to switch to stronger cryptography and rely on a simpler tool that everybody already has installed (including on Windows). For folks who were previously verifying signatures using GPG, please see the updated documentation for how to verify signatures with SSH. - * For folks who want to verify that this change is legitimate, see commit 0bc3935fe2a1b6e3d56049503db521877501edc1. That commit, which introduced this change, was signed using the original GPG key. - * The APK signing key remains unchanged. - -### Version 1.30 - -* Update Slovak translations (PR: #217, @pvagner) -* Update Polish translations (PR: #219, @Twoomatch) -* Improve English description of `initially paused` preference (PR: #220, @Twoomatch) -* Update Spanish translations (PR: #222, @nmayorga092) - -Magisk module updater changes: - -* Show changelog for the correct version, excluding unreleased changes (PR: #223, @chenxiaolong) - -Documentation changes: - -* README.md: Fix typos (PR: #221, @Twoomatch) - -### Version 1.29 - -* Add a new option for starting the recording in the paused state (Issue: #198, PR: #211, @chenxiaolong) - * If enabled, this allows the user to choose whether a call is recorded. If a recording starts in the paused state and is never resumed, then the empty output file is not saved. - -Documentation changes: - -* README.md: Document hidden/advanced features (Issue: #212, PR: #213, @chenxiaolong) - -### Version 1.28 - -* Inform the user that the device/firmware might not support call recording if an error origates from Android's internal components (PR: #206, @chenxiaolong) -* Fix crash if any filename template value (eg. caller/contact name) contains \ or $ (Issue: #207, PR: #209, @chenxiaolong) -* Add support for pausing/resuming the recording (Issue: #198, PR: #210, @chenxiaolong) - * The button is in the `Call recording in progress` notification - -### Version 1.27 - -* Update Polish translations (PR: #192, @Twoomatch) -* Update Spanish translations (PR: #201, @nmayorga092) -* Fix silent crash causing recording to not happen when debug mode is enabled (Issue: #195, PR: #203, @chenxiaolong) - * The bug was introduced in version 1.26 -* Add support for changing the filename timestamp format (Issue: #204, PR: #205, @chenxiaolong) - * Similar to the existing output filename options, this can only be done via the `bcr.properties` config file - -Non-user-facing changes: - -* Update Kotlin and AndroidX (PR: #196, @PatrykMis) -* Update Build Tools (PR: #199, @PatrykMis) - -### Version 1.26 - -* Update Turkish and Russian translations (PR: #188, @EleoXDA) -* Add hidden feature to customize the output filename (PR: #189, @chenxiaolong) - * To avoid complicating BCR's code, there is no UI option for this - * To customize the output filenames, copy [the default template](./app/src/main/res/raw/filename_template.properties) to `bcr.properties` in the output directory and edit the file - -### Version 1.25 - -* Add SIM slot ID to the filename if there are multiple active SIMs (Issue: #177, PR: #178, @chenxiaolong) -* Fix share action in the recording complete notification always referencing an old recording (PR: #181, @chenxiaolong) -* Add a new Delete action alongside Open and Share in the notifications (Issue: #179, PR: #182, @chenxiaolong) -* Allow changing output settings when call recording is disabled (PR: #183, @chenxiaolong) - -Documentation changes: - -* README.md: Explain what every permission is used for (PR: #180, @chenxiaolong) - -Non-user-facing changes: - -* Update gradle wrapper to 7.6.0 (PR: #174, @PatrykMis) - -### Version 1.24 - -* Notification improvements (PR: #169, @chenxiaolong) - * A notification is now shown when a recording completes, with options for opening or sharing the recording in a 3rd party app. - * **NOTE: Manual action required.** For opening/sharing recordings to work, reset the output directory to the default and then select the output directory again. This is required because BCR previously only requested write access to the output directory, but not read access. - * These new notifications can be disabled in Android's settings by turning off the `Success alerts` notification channel. - * The file path in error notifications is now human readable instead of a URL-encoded `content://...`. -* BCR will explicitly vibrate if vibration is enabled for its notification channels (PR: #167, #171, @quyenvsp, @chenxiaolong) - * This is needed because Android will not respect the notification vibration option during a phone call. - -Non-user-facing changes: - -* Updated all dependencies (PR: #160, @PatrykMis) -* Fixed Gradle non-laziness, causing the execution of specific tasks to be slower (PR: #168, @chenxiaolong) - -### Version 1.23 - -* Update all dependencies and fix build system lint issues (PR: #155, @PatrykMis) -* Add Slovak translation (PR: #161, @pvagner) - -### Version 1.22 - -* (Direct installs only) Add `/system/addon.d/` script to persist installation across OS updates (Issue: #142, PR: #144, @chenxiaolong) - * Only applies to LineageOS-based firmware -* Improve logging in debug mode (Issue: #143, PR: #145, #147, #148, @chenxiaolong) - * Run logcat interactively for the duration of the call to ensure no lost log messages due to logcat overflow - * Include BCR version number in the logs -* Improve output file writing reliability (Issue: #143, PR: #146, #149, #150, @chenxiaolong) -* Improve call disconnection detection on buggy firmware (Issue: #143, PR: #151, @chenxiaolong) - * Works around Samsung OneUI's telephony framework bug where Android does not notify apps (including their own) when a call disconnects -* Use non-blocking reads from call audio stream (Issue: #143, PR: #152, @chenxiaolong) - * Fixes recordings not stopping until another call becomes active on Samsung OneUI because `AudioRecord.read()` blocks forever as soon as a call disconnects - -### Version 1.21 - -* (Direct installs only) Explicitly remount system as writable and ignore `ENOENT` errors during cleanup (Issue: #108, #138, PR: #139, @chenxiaolong) -* Updated all dependencies (PR: #140, @chenxiaolong) - -### Version 1.20 - -* Update dependencies (PR: #121, #132, @PatrykMis) -* Perform a direct install if `/system/bin/recovery` exists in the environment (Issue: #131, PR: #133, @chenxiaolong) - * Previously, only `/sbin/recovery` was used to detect if booted into recovery - -### Version 1.19 - -* Add support for flashing via recovery (Issue: #128, PR: #130, @chenxiaolong) - * This is for unrooted (non-Magisk) installs only. BCR will be installed to the system partition directly when flashed via recovery. - -### Version 1.18 - -* Update gradle wrapper to 7.5.1 (PR: #116, @PatrykMis) -* Fix plurals in Russian translations (PR: #117, @EleoXDA) -* Add French translation (PR: #120, @NSO73) - -### Version 1.17 - -* Update dependencies and gradle wrapper (PR: #112, @PatrykMis) -* Update Polish translations (PR: #112, @PatrykMis) -* Fix silent crash when receiving a call from a private number (Issue: #111, PR: #114, @chenxiaolong) - -### Version 1.16 - -* Update Turkish translations (PR: #106, @EleoXDA) -* Update Russian translations (PR: #107, @EleoXDA) - -### Version 1.15 - -* Update Spanish translations (PR: #92, @nmayorga092) -* Update Turkish translations (PR: #97, @EleoXDA) - -### Version 1.14 - -* Add support for a basic file retention policy (Issue: #25 #81 #88, PR: #90, @chenxiaolong) - -Non-user-facing changes: - -* Improve type-safety when loading and saving preferences (PR: #91, @chenxiaolong) - -### Version 1.13 - -* Add Polish translations (PR: #76, @uvzen) -* Target stable API 33 (Tiramisu) (PR: #82, @chenxiaolong) -* Add optional contacts permission to initial permissions prompt (Issue: #78 #80, PR: #84, @chenxiaolong) - * If allowed, contact names are added to the output filenames. - * This feature was implemented in version 1.5, but required the user to manually enable from the system settings. - -Non-user-facing changes: - -* Update Android gradle plugin to 7.2.1 and Kotlin to 1.7.0 (PR: #83, @chenxiaolong) - -### Version 1.12 - -* Fix potential crash when showing user-friendly output directory path (PR: #74, @chenxiaolong) - * Fixes regression in version 1.11 - -### Version 1.11 - -* Fix persistent notification icon being too small (PR: #67, @chenxiaolong) -* Increase internal buffer sizes to reduce chance of encoding slowdowns causing audible artifacts (Issue: #39 #54, PR: #69 #73, @chenxiaolong) - * The native sample rate option had to be removed for this change -* Show user-friendly path instead of a raw URI for the output directory (PR: #71, @chenxiaolong) -* Work around SAF slowness by recording to the default directory and then moving to the user directory after recording is completed (Issue: #39 #54, PR: #72, @chenxiaolong) - -Non-user-facing changes: - -* Change Container abstract class to an interface (PR: #68, @chenxiaolong) -* Update all gradle dependencies (PR: #70, @chenxiaolong) - -### Version 1.10 - -* Update Spanish translations (PR: #64, @nmayorga092) -* Add hidden debug mode, which saves logs for each recording (long press version number to enable) (PR: #65, @chenxiaolong) -* Set recording thread priority to THREAD_PRIORITY_URGENT_AUDIO (Issue: #39 #54, PR: #66, @chenxiaolong) - -### Version 1.9 - -* Improve buffering to reduce chance of audio drops (Issue: #39 #54, PR: #61, @chenxiaolong) - -### Version 1.8 - -* Update Turkish translations (PR: #58, @fnldstntn) -* Fix overlapping audio and other audible artifacts when using an encoded format (OPUS, AAC, or FLAC) (Issue: #39 #54, PR: #59, @chenxiaolong) - -### Version 1.7 - -* Change output format button group to material chips to prevent text from being cut off with narrower screen widths (Issue: #52, PR: #55, @chenxiaolong) -* Add support for configuring the capture sample rate (PR: #56, @chenxiaolong) -* Send notification if an error occurs during call recording (PR: #57, @chenxiaolong) - -### Version 1.6 - -* Enable minification (without obfuscation) to shrink the download size by ~64% (PR: #45, @chenxiaolong) -* Update Turkish translations (PR: #46, @fnldstntn) -* Add support for WAV/PCM output for troubleshooting (bypasses encoding/compression pipeline) (PR: #48, @chenxiaolong) - -Non-user-facing changes: - -* Improve output format parameter abstraction (PR: #49, @chenxiaolong) -* Use view binding instead of findViewById where possible (PR: #50, @chenxiaolong) - -### Version 1.5 - -* Optionally add contact name to output filename if Contacts permission is granted (Android 11+) (Issue: #28, PR: #42, @chenxiaolong) -* Add Spanish translation (PR: #41, @nmayorga092) -* Redact sensitive information from logcat logs (PR: #43, @chenxiaolong) - -### Version 1.4 - -* Add support for configurable output formats: OGG/Opus (Android 10+), M4A/AAC, FLAC (Issue: #21, PR: #29, #32, #34, #35, #38, @chenxiaolong) -* README.md: Remove mention of cloud storage. Android's Storage Access Framework does not support cloud storage when opening folders (Issue: #30, PR: #31, @chenxiaolong) -* Add full changelog text for updates from Magisk Manager (PR: #36, @chenxiaolong) - -Non-user-facing changes: - -* Fix minor compiler warnings (PR: #37, @chenxiaolong) - -### Version 1.3 - -* Write audio duration to FLAC metadata after recording is complete (Issue: #19, PR: #20, @chenxiaolong) -* Add Turkish translations (Issue: #18, PR: #22, @fnldstntn) - -Non-user-facing changes: - -* Don't add irrelevant update metadata to release zips (PR: #23, @chenxiaolong) -* Fix serialization exception when running the `updateJson` gradle tasks (PR: #24, @chenxiaolong) - -### Version 1.2 - -* Fix typo and improve wording of battery optimization preference (PR: #4, @EleoXDA) -* Add Russian translations (PR: #7, @marat2509) -* Add support for API 28 (Android 9) (Issue: #6, PR: #10, @chenxiaolong) -* Add incoming/outgoing tag to filenames (Issue: #3, PR: #11, @chenxiaolong) -* Add caller ID to filenames for incoming calls (Android 10+ only) (Issue: #3, PR: #13, @chenxiaolong) -* Fix filename timestamps to match the call log exactly (Issue: #3, PR: #12, @chenxiaolong) -* The about link in the app now links to the exact commit the version was built from (PR: #15, @chenxiaolong) -* Add support for Magisk's built-in module updater (PR: #16, @chenxiaolong) - -Non-user-facing changes: - -* Update gradle and Android gradle plugin dependencies (PR: #9, @chenxiaolong) -* Add git commit to version number for debug builds (PR: #14, @chenxiaolong) -* Ensure custom gradle tasks (`moduleProp`, `permissionsXml`, `zip`, and `updateJson`) rebuild when input variables (eg. git commit) change (PR: #17, @chenxiaolong) - -### Version 1.1 - -* Target Android SDK 32. BCR was previously targeting the Tiramisu (33) preview SDK, which made it not installable on stable Android versions. (Issue: #1, PR: #2, @chenxiaolong) - ### Version 1.0 * Initial release diff --git a/README.md b/README.md index 9a8a4fe45..12bdaa70d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@ -# Basic Call Recorder +# Basic Audio Recorder -app icon +![license badge](https://img.shields.io/github/license/PatrykMis/BAR) -![latest release badge](https://img.shields.io/github/v/release/chenxiaolong/BCR?sort=semver) -![license badge](https://img.shields.io/github/license/chenxiaolong/BCR) +BAR is a simple Android audio recording app forked from [BCR](https://github.com/chenxiaolong/BCR) with an addition of [this pull request from the original author](https://github.com/chenxiaolong/BCR/pull/165). This fork has stripped out functionality / code related to call recording and uses the same codebase as BCR. -BCR is a simple Android call recording app for rooted devices or devices running custom firmware. Once enabled, it stays out of the way and automatically records incoming and outgoing calls in the background. - -light mode screenshot dark mode screenshot +I've decided to fork because BCR has a robust audio recording/encoding pipeline that supports multiple output formats and accounts for many edge cases and failure conditions that other apps may ignore. It records from Android's MIC audio source (todo: source selector) and passes the audio through the same encoding pipeline as with call recording. The output files are saved with a _mic suffix in the output directory. ### Features @@ -20,181 +17,40 @@ BCR is a simple Android call recording app for rooted devices or devices running * Supports Android's Storage Access Framework (can record to SD cards, USB devices, etc.) * Quick settings toggle * Material You dynamic theming -* No persistent notification unless a recording is in progress * No network access permission * No third party dependencies -* Works with call screening on Pixel devices (records the caller, but not the automated system) ### Non-features -As the name alludes, BCR intends to be a basic as possible. The project will have succeeded at its goal if the only updates it ever needs are for compatibility with new Android versions. Thus, many potentially useful features will never be implemented, such as: +As the name alludes, BAR intends to be a basic as possible. The project will have succeeded at its goal if the only updates it ever needs are for compatibility with new Android versions. Thus, many potentially useful features will never be implemented, such as: -* Support for old Android versions (support is dropped as soon as maintenance becomes cumbersome) -* Workarounds for [OEM-specific battery optimization and app killing behavior](https://dontkillmyapp.com/) -* Workarounds for devices that don't support the [`VOICE_CALL` audio source](https://developer.android.com/reference/android/media/MediaRecorder.AudioSource#VOICE_CALL) (eg. using microphone + speakerphone) +* Changing the filename format +* Support for old (unsupported) Android versions (support is dropped as soon as maintenance becomes cumbersome) * Support for direct boot mode (the state before the device is initially unlocked after reboot) -* Support for stock, unrooted firmware ### Usage -1. Download the latest version from the [releases page](https://github.com/chenxiaolong/BCR/releases). To verify the digital signature, see the [verifying digital signatures](#verifying-digital-signatures) section. - -2. Install BCR as a system app. - - * **For devices rooted with Magisk**, simply flash the zip as a Magisk module from within the Magisk app. - * **For OnePlus and Realme devices running the stock firmware (or custom firmware based on the stock firmware)**, also extract the `.apk` from the zip and install it manually before rebooting. This is necessary to work around a bug in the firmware where the app data directory does not get created, causing BCR to open up to a blank screen. - - * **For unrooted custom firmware**, flash the zip while booted into recovery. - * **NOTE**: If the custom firmware's `system` partition is formatted with `erofs`, then the filesystem is read-only and it is not possible to use this method. - * Manually extracting the files from the `system/` folder in the zip will also work as long as the files have `644` permissions and the `u:object_r:system_file:s0` SELinux label. - -3. Reboot and open BCR. - -4. Enable call recording and pick an output directory. If no output directory is selected or if the output directory is no longer accessible, then recordings will be saved to `/sdcard/Android/data/com.chiller3.bcr/files`. - - When enabling call recording the first time, BCR will prompt for microphone, notification (Android 13+), contacts, and phone permissions. Only microphone and notification permissions are required basic call recording functionality. If additional permissions are granted, more information is added to the output filename. For example, the contacts permission will cause the contact name to be added to the filename and the phone permission will cause the SIM slot (if multiple SIMs are active) to be added to the filename. - - See the [permissions section](#permissions) below for more details about the permissions. - -5. To install future updates, there are a couple methods: - - * If installed via Magisk, the module can be updated right from Magisk Manager's modules tab. Flashing the new version in Magisk manually also works just as well. - * The `.apk` can also be extracted from the zip and be directly installed. With this method, the old version exists as a system app and the new version exists as a user-installed update to the system app. This method is more convenient if BCR is baked into the Android firmware image. - -### Permissions - -* `CAPTURE_AUDIO_OUTPUT` (**automatically granted by system app permissions**) - * Needed to capture the call audio stream. -* `CONTROL_INCALL_EXPERIENCE` (**automatically granted by system app permissions**) - * Needed to monitor the phone call state for starting and stopping the recording and gathering call information for the output filename. -* `RECORD_AUDIO` (**must be granted by the user**) - * Needed to capture the call audio stream. -* `FOREGROUND_SERVICE` (**automatically granted at install time**) - * Needed to run the call recording service. -* `POST_NOTIFICATIONS` (**must be granted by the user on Android 13+**) - * Needed to show notifications. - * A notification is required for running the call recording service in foreground mode or else Android will not allow access to the call audio stream. -* `READ_CONTACTS` (**optional**) - * If allowed, the contact name is added to the output filename. -* `READ_PHONE_STATE` (**optional**) - * If allowed, the SIM slot for devices with multiple active SIMs is added to the output filename. -* `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` (**optional**) - * If allowed, request Android to disable battery optimizations (app killing) for BCR. - * This is usually not needed. The way BCR hooks into the telephony system makes it unlikely to be killed. - * OEM Android builds that stray further from AOSP may ignore this. -* `VIBRATE` (**automatically granted at install time**) - * If vibration is enabled for BCR's notifications in Android's settings, BCR will perform the vibration. Android itself does not respect the vibration option when a phone call is active. - -Note that `INTERNET` is _not_ in the list. BCR does not and will never access the network. BCR will never communicate with other apps either, except if the user explicitly taps on the `Open` or `Share` buttons in the notification shown when a recording completes. In that scenario, the target app is granted access to that single recording only. - -### Advanced features - -This section describes BCR's advanced features that are hidden or only accessible via a config file. - -#### Debug mode - -BCR has a hidden debug mode that can be enabled or disabled by long pressing the version number. - -When debug mode is enabled, BCR will write a log file to the output directory after a call recording completes. It is named the same way as the audio file. The log file contains the same messages as what `adb logcat` would show, except messages not relevant to BCR are filtered out (BCR does not have permission to access those messages anyway). - -Within the log file, BCR aims to never log any sensitive information. Information about the current call, like the phone number, are replaced with placeholders instead, like ``. However, other information can't be easily redacted this way will be truncated instead. For example, when the file retention feature cleans up old files, filenames like `20230101_010203.456+0000_out_1234567890_John_Doe.oga` are logged as `20<...>ga`. - -When reporting bugs, please include the log file as it is extremely helpful for identifying what might be wrong. (But please double check the log file to ensure there's no sensitive information!) - -#### Customizing the output filename - -By default, BCR uses a filename template that includes the call timestamp, call direction, SIM slot, phone number, caller ID, and contact name. This can be customized, but only by editing a config file. To do so, the easiest way is to copy [the default config](./app/src/main/res/raw/filename_template.properties) to `bcr.properties` in the output directory and then edit it to your liking. Details about the available fields are documented in the default config file. - -For example, to customize the filename template to `__`, use the following config: - -```properties -filename.0.text = ${date:yyyyMMdd_HHmmss} - -filename.1.text = ${phone_number} -filename.1.prefix = _ - -filename.2.text = ${caller_name} -filename.2.prefix = _ -``` - -The are a couple limitations to note: - -* The date must always be at the beginning of the filename. This is required for the file retention feature to work. -* If the date format is changed (eg. from the default to `yyyyMMdd_HHmmss`), then you must manually rename the old recordings to use the new date format or they may be handled incorrectly by the file retention feature. To be safe, move the old recordings to a different folder while testing (or set the file retention to `Keep all`). - -If the config file has any error, BCR will use the default configuration. This ensures that recordings won't fail if the configuration is incorrect. To troubleshoot issues with the filename template, [enable debug mode](#debug-mode), and make a call. Then, search the log file for `FilenameTemplate`. - -### How it works +1. Download the latest version from the [todo: releases page](https://github.com/PatrykMis/BAR/releases). To verify the digital signature, see the [verifying digital signatures](#verifying-digital-signatures) section. -BCR relies heavily on system app permissions in order to function properly. This is primarily because of two permissions: +2. Install BAR. -* `CONTROL_INCALL_EXPERIENCE` +3. Reboot and open BAR. - This permission allows Android's telephony service to bind to BCR's `InCallService` without BCR being a wearable companion app, a car UI, or the default dialer. Once bound, the service will receive callbacks for call change events (eg. incoming call in the ringing state). This method is much more reliable than using the `READ_PHONE_STATE` permission and relying on `android.intent.action.PHONE_STATE` broadcasts. +4. Pick an output directory. If no output directory is selected or if the output directory is no longer accessible, then recordings will be saved to `/sdcard/Android/data/com.patrykmis.bar/files`. - This method has a couple additional benefits. Due to the way that the telephony service binds to BCR's `InCallService`, the service can bring itself in and out of the foreground as needed when a call is in progress and access the audio stream without hitting Android 12+'s background microphone access limitations. It also does not require the service to be manually started from an `ACTION_BOOT_COMPLETED` broadcast receiver and thus is not affected by that broadcast's delays during initial boot. - -* `CAPTURE_AUDIO_OUTPUT` - - This permission is used to record from the `VOICE_CALL` audio stream. This stream, along with some others, like `VOICE_DOWNLINK` and `VOICE_UPLINK`, cannot be accessed without this system permission. - -With these two permissions, BCR can reliably detect phone calls and record from the call's audio stream. The recording process pulls PCM s16le raw audio and uses Android's built-in encoders to produce the compressed output file. - -### Verifying digital signatures - -Both the zip file and the APK contained within are digitally signed. **NOTE**: The zip file signing mechanism switched from GPG to SSH as of version 1.31. To verify signatures for old versions, see version 1.30's [`README.md`](https://github.com/chenxiaolong/BCR/blob/v1.30/README.md#verifying-digital-signatures). - -#### Verifying zip file signature - -First save the public key to a file that lists which keys should be trusted. - -```bash -echo 'bcr ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDOe6/tBnO7xZhAWXRj3ApUYgn+XZ0wnQiXM8B7tPgv4' > bcr_trusted_keys -``` - -Then, verify the signature of the zip file using the list of trusted keys. - -```bash -ssh-keygen -Y verify -f bcr_trusted_keys -I bcr -n file -s BCR--release.zip.sig < BCR--release.zip -``` - -If the file is successfully verified, the output will be: - -``` -Good "file" signature for bcr with ED25519 key SHA256:Ct0HoRyrFLrnF9W+A/BKEiJmwx7yWkgaW/JvghKrboA -``` - -#### Verifying apk signature - -First, extract the apk from the zip and then run: - -``` -apksigner verify --print-certs system/priv-app/com.chiller3.bcr/app-release.apk -``` - -Then, check that the SHA-256 digest of the APK signing certificate is: - -``` -d16f9b375df668c58ef4bb855eae959713d6d02e45f7f2c05ce2c27ae944f4f9 -``` +For the first time, BAR will prompt for microphone, and notification (Android 13+) permissions. They are required for BAR to be able to record in the background. ### Building from source -BCR can be built like most other Android apps using Android Studio or the gradle command line. +BAR can be built like most other Android apps using Android Studio or the gradle command line. -To build the APK: +To build the debug APK: ```bash ./gradlew assembleDebug ``` -To build the Magisk module zip (which automatically runs the `assembleDebug` task if needed): - -```bash -./gradlew zipDebug -``` - -The output file is written to `app/build/distributions/debug/`. The APK will be signed with the default autogenerated debug key. +The output file is written to `app/build/outputs/apk/debug/`. The APK will be signed with the default autogenerated debug key. To create a release build with a specific signing key, set up the following environment variables: @@ -208,18 +64,18 @@ export RELEASE_KEYSTORE_PASSPHRASE export RELEASE_KEY_PASSPHRASE ``` -and then build the release zip: +and then build the release APK: ```bash -./gradlew zipRelease +./gradlew assembleRelease ``` ### Contributing Bug fix and translation pull requests are welcome and much appreciated! -If you are interested in implementing a new feature and would like to see it included in BCR, please open an issue to discuss it first. I intend for BCR to be as simple and low-maintenance as possible, so I am not too inclined to add any new features, but I could be convinced otherwise. +If you are interested in implementing a new feature and would like to see it included in BAR, please open an issue to discuss it first. I intend for BAR to be as simple and low-maintenance as possible, so I am not too inclined to add any new features, but I could be convinced otherwise. ### License -BCR is licensed under GPLv3. Please see [`LICENSE`](./LICENSE) for the full license text. +BAR is licensed under GPLv3. Please see [`LICENSE`](./LICENSE) for the full license text. diff --git a/RELEASE.md b/RELEASE.md index 6dac8d524..372e30dca 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,6 +2,4 @@ The changelog can be found at: [`CHANGELOG.md`](./CHANGELOG.md). --- -See [`README.md`](./README.md) for information on how to install and use BCR. - -The downloads are digitally signed. Please consider [verifying the digital signatures](./README.md#verifying-digital-signatures) because BCR is installed as a privileged system app. +See [`README.md`](./README.md) for information on how to install and use BAR. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f02945a54..9c7fe0a97 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,116 +1,50 @@ -import org.eclipse.jgit.api.ArchiveCommand -import org.eclipse.jgit.api.Git -import org.eclipse.jgit.archive.TarFormat -import org.eclipse.jgit.lib.ObjectId -import org.jetbrains.kotlin.backend.common.pop -import org.json.JSONObject +import java.io.FileInputStream +import java.util.Properties plugins { id("com.android.application") - id("org.jetbrains.kotlin.android") + kotlin("android") } -buildscript { - dependencies { - classpath("org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r") - classpath("org.eclipse.jgit:org.eclipse.jgit.archive:6.5.0.202303070854-r") - classpath("org.json:json:20230227") - } +val keystorePropertiesFile = rootProject.file("keystore.properties") +val useKeystoreProperties = keystorePropertiesFile.canRead() +val keystoreProperties = Properties() +if (useKeystoreProperties) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) } -typealias VersionTriple = Triple - -fun describeVersion(git: Git): VersionTriple { - // jgit doesn't provide a nice way to get strongly-typed objects from its `describe` command - val describeStr = git.describe().setLong(true).call() - - return if (describeStr != null) { - val pieces = describeStr.split('-').toMutableList() - val commit = git.repository.resolve(pieces.pop().substring(1)) - val count = pieces.pop().toInt() - val tag = pieces.joinToString("-") - - Triple(tag, count, commit) - } else { - val log = git.log().call().iterator() - val head = log.next() - var count = 1 - - while (log.hasNext()) { - log.next() - ++count - } - - Triple(null, count, head.id) +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) } } -fun getVersionCode(triple: VersionTriple): Int { - val tag = triple.first - val (major, minor) = if (tag != null) { - if (!tag.startsWith('v')) { - throw IllegalArgumentException("Tag does not begin with 'v': $tag") - } - - val pieces = tag.substring(1).split('.') - if (pieces.size != 2) { - throw IllegalArgumentException("Tag is not in the form 'v.': $tag") - } - - Pair(pieces[0].toInt(), pieces[1].toInt()) - } else { - Pair(0, 0) - } - - // 8 bits for major version, 8 bits for minor version, and 8 bits for git commit count - assert(major in 0 until 1.shl(8)) - assert(minor in 0 until 1.shl(8)) - assert(triple.second in 0 until 1.shl(8)) - - return major.shl(16) or minor.shl(8) or triple.second -} - -fun getVersionName(git: Git, triple: VersionTriple): String { - val tag = triple.first?.replace(Regex("^v"), "") ?: "NONE" - - return buildString { - append(tag) - - if (triple.second > 0) { - append(".r") - append(triple.second) - - append(".g") - git.repository.newObjectReader().use { - append(it.abbreviate(triple.third).name()) +android { + if (useKeystoreProperties) { + signingConfigs { + create("release") { + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storeFile = file(keystoreProperties["storeFile"]!!) + storePassword = keystoreProperties["storePassword"] as String + enableV2Signing = false + enableV3Signing = true + enableV4Signing = true } } } -} - -val git = Git.open(File(rootDir, ".git"))!! -val gitVersionTriple = describeVersion(git) -val gitVersionCode = getVersionCode(gitVersionTriple) -val gitVersionName = getVersionName(git, gitVersionTriple) - -val projectUrl = "https://github.com/chenxiaolong/BCR" -val releaseMetadataBranch = "master" -val extraDir = File(buildDir, "extra") -val archiveDir = File(extraDir, "archive") - -android { - namespace = "com.chiller3.bcr" + namespace = "com.patrykmis.bar" compileSdk = 33 buildToolsVersion = "33.0.2" defaultConfig { - applicationId = "com.chiller3.bcr" + applicationId = "com.patrykmis.bar" minSdk = 29 targetSdk = 33 - versionCode = gitVersionCode - versionName = gitVersionName + versionCode = 1 + versionName = versionCode.toString() resourceConfigurations.addAll(listOf( "en", "es", @@ -122,32 +56,12 @@ android { "tr", "zh-rCN" )) - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - - buildConfigField("String", "PROJECT_URL_AT_COMMIT", - "\"${projectUrl}/tree/${gitVersionTriple.third.name}\"") - + buildConfigField("String", "PROVIDER_AUTHORITY", "APPLICATION_ID + \".provider\"") resValue("string", "provider_authority", "$applicationId.provider") } - sourceSets { - getByName("main") { - assets { - srcDir(archiveDir) - } - } - } - signingConfigs { - create("release") { - val keystore = System.getenv("RELEASE_KEYSTORE") - storeFile = if (keystore != null) { File(keystore) } else { null } - storePassword = System.getenv("RELEASE_KEYSTORE_PASSPHRASE") - keyAlias = System.getenv("RELEASE_KEY_ALIAS") - keyPassword = System.getenv("RELEASE_KEY_PASSPHRASE") - } - } + buildTypes { getByName("debug") { buildConfigField("boolean", "FORCE_DEBUG_MODE", "true") @@ -170,7 +84,9 @@ android { isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - signingConfig = signingConfigs.getByName("release") + if (useKeystoreProperties) { + signingConfig = signingConfigs.getByName("release") + } } } compileOptions { @@ -178,11 +94,24 @@ android { targetCompatibility(JavaVersion.VERSION_11) } kotlinOptions { - jvmTarget = "11" + jvmTarget = JavaVersion.VERSION_11.toString() } buildFeatures { viewBinding = true } + + dependenciesInfo { + includeInApk = false + includeInBundle = false + } + packagingOptions { + resources.excludes.addAll(listOf( + "DebugProbesKt.bin", + "META-INF/**.version", + "kotlin-tooling-metadata.json", + "kotlin/**.kotlin_builtins" + )) + } } dependencies { @@ -193,245 +122,4 @@ dependencies { implementation("androidx.fragment:fragment-ktx:1.5.6") implementation("androidx.preference:preference-ktx:1.2.0") implementation("com.google.android.material:material:1.8.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") -} - -val archive = tasks.register("archive") { - inputs.property("gitVersionTriple.third", gitVersionTriple.third) - - val outputFile = File(archiveDir, "archive.tar") - outputs.file(outputFile) - - doLast { - val format = "tar_${Thread.currentThread().id}" - - ArchiveCommand.registerFormat(format, TarFormat()) - try { - outputFile.outputStream().use { - git.archive() - .setTree(git.repository.resolve(gitVersionTriple.third.name)) - .setFormat(format) - .setOutputStream(it) - .call() - } - } finally { - ArchiveCommand.unregisterFormat(format) - } - } -} - -android.applicationVariants.all { - val variant = this - val capitalized = variant.name.capitalize() - val variantDir = File(extraDir, variant.name) - - variant.preBuildProvider.configure { - dependsOn(archive) - } - - val moduleProp = tasks.register("moduleProp${capitalized}") { - inputs.property("projectUrl", projectUrl) - inputs.property("releaseMetadataBranch", releaseMetadataBranch) - inputs.property("variant.applicationId", variant.applicationId) - inputs.property("variant.name", variant.name) - inputs.property("variant.versionCode", variant.versionCode) - inputs.property("variant.versionName", variant.versionName) - - val outputFile = File(variantDir, "module.prop") - outputs.file(outputFile) - - doLast { - val props = LinkedHashMap() - props["id"] = variant.applicationId - props["name"] = "BCR" - props["version"] = "v${variant.versionName}" - props["versionCode"] = variant.versionCode.toString() - props["author"] = "chenxiaolong" - props["description"] = "Basic Call Recorder" - - if (variant.name == "release") { - props["updateJson"] = "${projectUrl}/raw/${releaseMetadataBranch}/app/magisk/updates/${variant.name}/info.json" - } - - outputFile.writeText(props.map { "${it.key}=${it.value}" }.joinToString("\n")) - } - } - - val permissionsXml = tasks.register("permissionsXml${capitalized}") { - inputs.property("variant.applicationId", variant.applicationId) - - val outputFile = File(variantDir, "privapp-permissions-${variant.applicationId}.xml") - outputs.file(outputFile) - - doLast { - outputFile.writeText(""" - - - - - - - - """.trimIndent()) - } - } - - val addonD = tasks.register("addonD${capitalized}") { - inputs.property("variant.applicationId", variant.applicationId) - - // To get output apk filename - dependsOn.add(variant.assembleProvider) - - val outputFile = File(variantDir, "51-${variant.applicationId}.sh") - outputs.file(outputFile) - - val backupFiles = variant.outputs.map { - "priv-app/${variant.applicationId}/${it.outputFile.name}" - } + listOf( - "etc/permissions/privapp-permissions-${variant.applicationId}.xml" - ) - - doLast { - outputFile.writeText(""" - #!/sbin/sh - # ADDOND_VERSION=2 - - . /tmp/backuptool.functions - - files="${backupFiles.joinToString(" ")}" - - case "${'$'}{1}" in - backup|restore) - for f in ${'$'}{files}; do - "${'$'}{1}_file" "${'$'}{S}/${'$'}{f}" - done - ;; - esac - """.trimIndent()) - } - } - - tasks.register("zip${capitalized}") { - inputs.property("variant.applicationId", variant.applicationId) - inputs.property("variant.name", variant.name) - inputs.property("variant.versionName", variant.versionName) - - archiveFileName.set("BCR-${variant.versionName}-${variant.name}.zip") - // Force instantiation of old value or else this will cause infinite recursion - destinationDirectory.set(destinationDirectory.dir(variant.name).get()) - - // Make the zip byte-for-byte reproducible (note that the APK is still not reproducible) - isPreserveFileTimestamps = false - isReproducibleFileOrder = true - - dependsOn.add(variant.assembleProvider) - - from(moduleProp.map { it.outputs }) - from(addonD.map { it.outputs }) { - fileMode = 0b111_101_101 // 0o755; kotlin doesn't support octal literals - into("system/addon.d") - } - from(permissionsXml.map { it.outputs }) { - into("system/etc/permissions") - } - from(variant.outputs.map { it.outputFile }) { - into("system/priv-app/${variant.applicationId}") - } - - val magiskDir = File(projectDir, "magisk") - - for (script in arrayOf("update-binary", "updater-script")) { - from(File(magiskDir, script)) { - into("META-INF/com/google/android") - } - } - - from(File(magiskDir, "customize.sh")) - - from(File(rootDir, "LICENSE")) - from(File(rootDir, "README.md")) - } - - tasks.register("updateJson${capitalized}") { - inputs.property("gitVersionTriple.first", gitVersionTriple.first) - inputs.property("projectUrl", projectUrl) - inputs.property("variant.name", variant.name) - inputs.property("variant.versionCode", variant.versionCode) - inputs.property("variant.versionName", variant.versionName) - - val magiskDir = File(projectDir, "magisk") - val updatesDir = File(magiskDir, "updates") - val variantUpdateDir = File(updatesDir, variant.name) - val jsonFile = File(variantUpdateDir, "info.json") - - outputs.file(jsonFile) - - doLast { - if (gitVersionTriple.second != 0) { - throw IllegalStateException("The release tag must be checked out") - } - - val root = JSONObject() - root.put("version", variant.versionName) - root.put("versionCode", variant.versionCode) - root.put("zipUrl", "${projectUrl}/releases/download/${gitVersionTriple.first}/BCR-${variant.versionName}-release.zip") - root.put("changelog", "${projectUrl}/raw/${gitVersionTriple.first}/app/magisk/updates/${variant.name}/changelog.txt") - - jsonFile.writer().use { - root.write(it, 4, 0) - } - } - } -} - -fun updateChangelog(version: String?, replaceFirst: Boolean) { - val file = File(rootDir, "CHANGELOG.md") - val expected = if (version != null) { "### Version $version" } else { "### Unreleased" } - - val changelog = mutableListOf().apply { - // This preserves a trailing newline, unlike File.readLines() - addAll(file.readText().lineSequence()) - } - - if (changelog.firstOrNull() != expected) { - if (replaceFirst) { - changelog[0] = expected - } else { - changelog.addAll(0, listOf(expected, "")) - } - } - - file.writeText(changelog.joinToString("\n")) -} - -fun updateMagiskChangelog(gitRef: String) { - File(File(File(File(projectDir, "magisk"), "updates"), "release"), "changelog.txt") - .writeText("The changelog can be found at: [`CHANGELOG.md`]($projectUrl/blob/$gitRef/CHANGELOG.md).\n") -} - -tasks.register("changelogPreRelease") { - doLast { - val version = project.property("releaseVersion") - - updateChangelog(version.toString(), true) - updateMagiskChangelog("v$version") - } -} - -tasks.register("changelogPostRelease") { - doLast { - updateChangelog(null, false) - updateMagiskChangelog(releaseMetadataBranch) - } -} - -tasks.register("preRelease") { - dependsOn("changelogPreRelease") -} - -tasks.register("postRelease") { - dependsOn("updateJsonRelease") - dependsOn("changelogPostRelease") } diff --git a/app/magisk/customize.sh b/app/magisk/customize.sh deleted file mode 100644 index 5404cc7a5..000000000 --- a/app/magisk/customize.sh +++ /dev/null @@ -1,43 +0,0 @@ -# Until Magisk supports overlayfs, we'll try to install to a non-overlayfs path -# that still supports privileged apps. -# https://github.com/topjohnwu/Magisk/pull/6588 - -has_overlays() { - local mnt="${1}" count - count=$(awk -v mnt="${mnt}" '$9 == "overlay" && $5 ~ mnt' /proc/self/mountinfo | wc -l) - [ "${count}" -gt 0 ] -} - -target= - -for mountpoint in /system /product /system_ext /vendor; do - if has_overlays "^${mountpoint}"; then - echo "Cannot use ${mountpoint}: contains overlayfs mounts" - # Magisk fails to mount files when the parent directory does not exist - elif [ ! -d "${mountpoint}/etc/permissions" ]; then - echo "Cannot use ${mountpoint}: etc/permissions/ does not exist" - elif [ ! -d "${mountpoint}/priv-app" ]; then - echo "Cannot use ${mountpoint}: priv-app/ does not exist" - else - echo "Using ${mountpoint} as the installation target" - target=${mountpoint} - break - fi -done - -if [ -z "${target}" ]; then - echo 'No suitable installation target found' - echo 'This OS is not supported' - rm -rv "${MODPATH}" 2>&1 - exit 1 -fi - -if [ "${target}" != /system ]; then - echo 'Removing addon.d script since installation target is not /system' - rm -rv "${MODPATH}/system/addon.d" 2>&1 || exit 1 - - echo "Adjusting overlay for installation to ${target}" - mv -v "${MODPATH}/system" "${MODPATH}/${target#/}" 2>&1 || exit 1 - mkdir -v "${MODPATH}/system" 2>&1 || exit 1 - mv -v "${MODPATH}/${target#/}" "${MODPATH}/system/${target#/}" 2>&1 || exit 1 -fi diff --git a/app/magisk/update-binary b/app/magisk/update-binary deleted file mode 100644 index 911344361..000000000 --- a/app/magisk/update-binary +++ /dev/null @@ -1,44 +0,0 @@ -#!/sbin/sh - -OUTFD=${2} -ZIPFILE=${3} - -umask 022 - -ui_print() { - printf "ui_print %s\nui_print\n" "${*}" > /proc/self/fd/"${OUTFD}" -} - -if [ -f /sbin/recovery ] || [ -f /system/bin/recovery ]; then - # Installing via recovery. Always do a direct install. - set -exu - - ui_print 'Mounting system' - if mount /system_root; then - mount -o remount,rw /system_root - root_dir=/system_root - else - mount /system - mount -o remount,rw /system - root_dir=/ - fi - - ui_print 'Extracting files' - - # Just overwriting isn't sufficient because the apk filenames are different - # between debug and release builds - app_id=$(unzip -p "${ZIPFILE}" module.prop | grep '^id=' | cut -d= -f2) - - # rm on some custom recoveries doesn't exit with 0 on ENOENT, even with -f - rm -rf "${root_dir}/system/priv-app/${app_id}" || : - - unzip -o "${ZIPFILE}" 'system/*' -d "${root_dir}" - - ui_print 'Done!' -else - # Installing via Magisk Manager. - - . /data/adb/magisk/util_functions.sh - - install_module -fi diff --git a/app/magisk/updater-script b/app/magisk/updater-script deleted file mode 100644 index 11d5c96e0..000000000 --- a/app/magisk/updater-script +++ /dev/null @@ -1 +0,0 @@ -#MAGISK diff --git a/app/magisk/updates/release/changelog.txt b/app/magisk/updates/release/changelog.txt deleted file mode 100644 index 2c57b7634..000000000 --- a/app/magisk/updates/release/changelog.txt +++ /dev/null @@ -1 +0,0 @@ -The changelog can be found at: [`CHANGELOG.md`](https://github.com/chenxiaolong/BCR/blob/v1.39/CHANGELOG.md). diff --git a/app/magisk/updates/release/info.json b/app/magisk/updates/release/info.json deleted file mode 100644 index 4b661a9e6..000000000 --- a/app/magisk/updates/release/info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "zipUrl": "https://github.com/chenxiaolong/BCR/releases/download/v1.38/BCR-1.38-release.zip", - "changelog": "https://github.com/chenxiaolong/BCR/raw/v1.38/app/magisk/updates/release/changelog.txt", - "version": "1.38", - "versionCode": 75264 -} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e396b8a1b..c70a9cd48 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -14,7 +14,7 @@ # Uncomment this to preserve the line number information for # debugging stack traces. --keepattributes SourceFile,LineNumberTable +# -keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. @@ -22,10 +22,11 @@ # Disable obfuscation completely for BCR. As an open source project, # shrinking is the only goal of minification. --dontobfuscate +# -dontobfuscate # We construct TreeDocumentFile via reflection in DocumentFileExtensions # to speed up SAF performance when doing path lookups. -keepclassmembers class androidx.documentfile.provider.TreeDocumentFile { (androidx.documentfile.provider.DocumentFile, android.content.Context, android.net.Uri); } +-keep class com.patrykmis.bar.ChipGroupCentered { *; } diff --git a/app/src/androidTest/java/com/chiller3/bcr/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/chiller3/bcr/ExampleInstrumentedTest.kt deleted file mode 100644 index 6dc91f3df..000000000 --- a/app/src/androidTest/java/com/chiller3/bcr/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.chiller3.bcr - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.chiller3.bcr", appContext.packageName) - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a3a2ee7fa..269fb6ce4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,21 +2,7 @@ - - - - - @@ -30,7 +16,7 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.BCR" + android:theme="@style/Theme.BAR" android:localeConfig="@xml/locales_config" tools:ignore="UnusedAttribute"> @@ -38,17 +24,6 @@ android:name=".NotificationActionService" android:exported="false" /> - - - - - - - - - - - - - () - - /** - * Number of threads pending exit after the call has been disconnected. This can be negative if - * the recording thread fails before the call is disconnected. - */ - private var pendingExit = 0 - - /** - * Token value for all intents received by this instance of the service. - * - * For the pause/resume functionality, we cannot use a bound service because [InCallService] - * uses its own non-extensible [onBind] implementation. So instead, we rely on [onStartCommand]. - * However, because this service is required to be exported, the intents could potentially come - * from third party apps and we don't want those interfering with the recordings. - */ - private val token = Random.Default.nextBytes(128) - - private val callback = object : Call.Callback() { - override fun onStateChanged(call: Call, state: Int) { - super.onStateChanged(call, state) - Log.d(TAG, "onStateChanged: $call, $state") - - handleStateChange(call, state) - } - - override fun onDetailsChanged(call: Call, details: Call.Details) { - super.onDetailsChanged(call, details) - Log.d(TAG, "onDetailsChanged: $call, $details") - - handleDetailsChange(call, details) - - // Due to firmware bugs, on older Samsung firmware, this callback (with the DISCONNECTED - // state) is the only notification we receive that a call ended - handleStateChange(call, null) - } - - override fun onCallDestroyed(call: Call) { - super.onCallDestroyed(call) - Log.d(TAG, "onCallDestroyed: $call") - - requestStopRecording(call) - } - } - - private fun createBaseIntent(): Intent = - Intent(this, RecorderInCallService::class.java).apply { - putExtra(EXTRA_TOKEN, token) - } - - private fun createPauseIntent(): Intent = - createBaseIntent().apply { - action = ACTION_PAUSE - } - - private fun createResumeIntent(): Intent = - createBaseIntent().apply { - action = ACTION_RESUME - } - - override fun onCreate() { - super.onCreate() - - prefs = Preferences(this) - notifications = Notifications(this) - } - - /** Handle intents triggered from notification actions for pausing and resuming. */ - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - try { - val receivedToken = intent?.getByteArrayExtra(EXTRA_TOKEN) - if (!receivedToken.contentEquals(token)) { - throw IllegalArgumentException("Invalid token") - } - - when (val action = intent?.action) { - ACTION_PAUSE, ACTION_RESUME -> { - for ((_, recorder) in recorders) { - recorder.isPaused = action == ACTION_PAUSE - } - updateForegroundState() - } - else -> throw IllegalArgumentException("Invalid action: $action") - } - } catch (e: Exception) { - Log.w(TAG, "Failed to handle intent: $intent", e) - } - - // All actions are oneshot actions that should not be redelivered if a restart occurs - stopSelf(startId) - return START_NOT_STICKY - } - - /** - * Always called when the telephony framework becomes aware of a new call. - * - * This is the entry point for a new call. [callback] is always registered to keep track of - * state changes. - */ - override fun onCallAdded(call: Call) { - super.onCallAdded(call) - Log.d(TAG, "onCallAdded: $call") - - // The callback is unregistered in requestStopRecording() - call.registerCallback(callback) - - // In case the call is already in the active state - handleStateChange(call, null) - } - - /** - * Called when the telephony framework destroys a call. - * - * This will request the cancellation of the recording, even if [call] happens to not be in one - * of the disconnecting states. - * - * This is NOT guaranteed to be called, notably on older Samsung firmware, due to bugs in the - * telephony framework. As a result, [handleStateChange] stop the recording if the call enters a - * disconnecting state. - */ - override fun onCallRemoved(call: Call) { - super.onCallRemoved(call) - Log.d(TAG, "onCallRemoved: $call") - - // Unconditionally request the recording to stop, even if it's not in a disconnecting state - // since no further events will be received for the call. - requestStopRecording(call) - } - - /** - * Start or stop recording based on the [call] state. - * - * If the state is [Call.STATE_ACTIVE], then recording will begin. If the state is either - * [Call.STATE_DISCONNECTING] or [Call.STATE_DISCONNECTED], then the cancellation of the active - * recording will be requested. If [state] is null, then the call state is queried from [call]. - */ - private fun handleStateChange(call: Call, state: Int?) { - val callState = state ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - call.details.state - } else { - @Suppress("DEPRECATION") - call.state - } - - Log.d(TAG, "handleStateChange: $call, $state, $callState") - - if (callState == Call.STATE_ACTIVE) { - startRecording(call) - } else if (callState == Call.STATE_DISCONNECTING || callState == Call.STATE_DISCONNECTED) { - // This is necessary because onCallRemoved() might not be called due to firmware bugs - requestStopRecording(call) - } - } - - /** - * Start a [RecorderThread] for [call]. - * - * If call recording is disabled or the required permissions aren't granted, then no - * [RecorderThread] will be created. - * - * This function is idempotent. - */ - private fun startRecording(call: Call) { - if (!prefs.isCallRecordingEnabled) { - Log.v(TAG, "Call recording is disabled") - } else if (!Permissions.haveRequired(this)) { - Log.v(TAG, "Required permissions have not been granted") - } else if (!recorders.containsKey(call)) { - val recorder = try { - RecorderThread(this, this, call) - } catch (e: Exception) { - notifyFailure(e.message, null) - throw e - } - recorders[call] = recorder - - updateForegroundState() - recorder.start() - } - } - - /** - * Request the cancellation of the [RecorderThread]. - * - * The [RecorderThread] is immediately removed from [recorders], but [pendingExit] will be - * incremented to keep the foreground notification alive until the [RecorderThread] exits and - * reports its status. The thread may exit, decrementing [pendingExit], before this function is - * called if an error occurs during recording. - * - * This function will also unregister [callback] from the call since it's no longer necessary to - * track further state changes. - * - * This function is idempotent. - */ - private fun requestStopRecording(call: Call) { - // This is safe to call multiple times in the AOSP implementation and also in heavily - // modified builds, like Samsung's firmware. If this ever becomes a problem, we can keep - // track of which calls have callbacks registered. - call.unregisterCallback(callback) - - val recorder = recorders[call] - if (recorder != null) { - recorder.cancel() - - recorders.remove(call) - - // Don't change the foreground state until the thread has exited - ++pendingExit - } - } - - /** - * Notify the recording thread of call details changes. - * - * The recording thread uses call details for generating filenames. - */ - private fun handleDetailsChange(call: Call, details: Call.Details) { - recorders[call]?.onCallDetailsChanged(details) - } - - /** - * Move to foreground, creating a persistent notification, when there are active calls or - * recording threads that haven't finished exiting yet. - */ - private fun updateForegroundState() { - if (recorders.isEmpty() && pendingExit == 0) { - stopForeground(STOP_FOREGROUND_REMOVE) - } else { - if (recorders.any { it.value.isPaused }) { - startForeground(1, notifications.createPersistentNotification( - R.string.notification_recording_paused, - R.drawable.ic_launcher_quick_settings, - R.string.notification_action_resume, - createResumeIntent(), - )) - } else { - startForeground(1, notifications.createPersistentNotification( - R.string.notification_recording_in_progress, - R.drawable.ic_launcher_quick_settings, - R.string.notification_action_pause, - createPauseIntent(), - )) - } - notifications.vibrateIfEnabled(Notifications.CHANNEL_ID_PERSISTENT) - } - } - - private fun notifySuccess(file: OutputFile) { - notifications.notifySuccess( - R.string.notification_recording_succeeded, - R.drawable.ic_launcher_quick_settings, - file, - ) - } - - private fun notifyFailure(errorMsg: String?, file: OutputFile?) { - notifications.notifyFailure( - R.string.notification_recording_failed, - R.drawable.ic_launcher_quick_settings, - errorMsg, - file, - ) - } - - private fun onThreadExited() { - --pendingExit - updateForegroundState() - } - - override fun onRecordingCompleted(thread: RecorderThread, file: OutputFile?) { - Log.i(TAG, "Recording completed: ${thread.id}: ${file?.redacted}") - handler.post { - onThreadExited() - - // If the recording was initially paused and the user never resumed it, there's no - // output file, so nothing needs to be shown. - if (file != null) { - notifySuccess(file) - } - } - } - - override fun onRecordingFailed(thread: RecorderThread, errorMsg: String?, file: OutputFile?) { - Log.w(TAG, "Recording failed: ${thread.id}: ${file?.redacted}") - handler.post { - onThreadExited() - - notifyFailure(errorMsg, file) - } - } -} diff --git a/app/src/main/java/com/chiller3/bcr/RecorderTileService.kt b/app/src/main/java/com/chiller3/bcr/RecorderTileService.kt deleted file mode 100644 index c4a0ae299..000000000 --- a/app/src/main/java/com/chiller3/bcr/RecorderTileService.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.chiller3.bcr - -import android.content.Intent -import android.content.SharedPreferences -import android.service.quicksettings.Tile -import android.service.quicksettings.TileService -import androidx.preference.PreferenceManager - -class RecorderTileService : TileService(), SharedPreferences.OnSharedPreferenceChangeListener { - private lateinit var prefs: Preferences - - override fun onCreate() { - super.onCreate() - - prefs = Preferences(this) - } - - override fun onStartListening() { - super.onStartListening() - val prefs = PreferenceManager.getDefaultSharedPreferences(this) - prefs.registerOnSharedPreferenceChangeListener(this) - - refreshTileState() - } - - override fun onStopListening() { - super.onStopListening() - val prefs = PreferenceManager.getDefaultSharedPreferences(this) - prefs.unregisterOnSharedPreferenceChangeListener(this) - } - - override fun onClick() { - super.onClick() - - if (!Permissions.haveRequired(this)) { - val intent = Intent(this, SettingsActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - startActivityAndCollapse(intent) - } else { - prefs.isCallRecordingEnabled = !prefs.isCallRecordingEnabled - } - - refreshTileState() - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { - refreshTileState() - } - - private fun refreshTileState() { - val tile = qsTile - - // Tile.STATE_UNAVAILABLE is intentionally not used when permissions haven't been granted. - // Clicking the tile in that state does not invoke the click handler, so it wouldn't be - // possible to launch SettingsActivity to grant the permissions. - if (Permissions.haveRequired(this) && prefs.isCallRecordingEnabled) { - tile.state = Tile.STATE_ACTIVE - } else { - tile.state = Tile.STATE_INACTIVE - } - - tile.updateTile() - } -} diff --git a/app/src/main/java/com/chiller3/bcr/AudioFormatExtension.kt b/app/src/main/kotlin/com/patrykmis/bar/AudioFormatExtension.kt similarity index 80% rename from app/src/main/java/com/chiller3/bcr/AudioFormatExtension.kt rename to app/src/main/kotlin/com/patrykmis/bar/AudioFormatExtension.kt index e30e3fe04..9ecf3c638 100644 --- a/app/src/main/java/com/chiller3/bcr/AudioFormatExtension.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/AudioFormatExtension.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.media.AudioFormat diff --git a/app/src/main/java/com/chiller3/bcr/ChipGroupCentered.kt b/app/src/main/kotlin/com/patrykmis/bar/ChipGroupCentered.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/ChipGroupCentered.kt rename to app/src/main/kotlin/com/patrykmis/bar/ChipGroupCentered.kt index 88fd5f069..b61ec9445 100644 --- a/app/src/main/java/com/chiller3/bcr/ChipGroupCentered.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/ChipGroupCentered.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.annotation.SuppressLint import android.content.Context diff --git a/app/src/main/java/com/chiller3/bcr/DocumentFileExtensions.kt b/app/src/main/kotlin/com/patrykmis/bar/DocumentFileExtensions.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/DocumentFileExtensions.kt rename to app/src/main/kotlin/com/patrykmis/bar/DocumentFileExtensions.kt index b7b07a5e3..1b0c17b64 100644 --- a/app/src/main/java/com/chiller3/bcr/DocumentFileExtensions.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/DocumentFileExtensions.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.ContentResolver import android.content.Context diff --git a/app/src/main/java/com/chiller3/bcr/FilenameTemplate.kt b/app/src/main/kotlin/com/patrykmis/bar/FilenameTemplate.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/FilenameTemplate.kt rename to app/src/main/kotlin/com/patrykmis/bar/FilenameTemplate.kt index d52538a5f..3123c7896 100644 --- a/app/src/main/java/com/chiller3/bcr/FilenameTemplate.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/FilenameTemplate.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import android.util.Log @@ -113,7 +113,7 @@ class FilenameTemplate private constructor(props: Properties, key: String) { Log.d(TAG, "Looking for custom filename template in: ${outputDir.uri}") - val templateFile = outputDir.findFileFast("bcr.properties") + val templateFile = outputDir.findFileFast("bar.properties") if (templateFile != null) { try { Log.d(TAG, "Loading custom filename template: ${templateFile.uri}") diff --git a/app/src/main/java/com/chiller3/bcr/LongClickablePreference.kt b/app/src/main/kotlin/com/patrykmis/bar/LongClickablePreference.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/LongClickablePreference.kt rename to app/src/main/kotlin/com/patrykmis/bar/LongClickablePreference.kt index dd01e60cd..5a4c07bd0 100644 --- a/app/src/main/java/com/chiller3/bcr/LongClickablePreference.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/LongClickablePreference.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import android.util.AttributeSet diff --git a/app/src/main/java/com/chiller3/bcr/NotificationActionService.kt b/app/src/main/kotlin/com/patrykmis/bar/NotificationActionService.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/NotificationActionService.kt rename to app/src/main/kotlin/com/patrykmis/bar/NotificationActionService.kt index afb152f51..831d4a76c 100644 --- a/app/src/main/java/com/chiller3/bcr/NotificationActionService.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/NotificationActionService.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.app.NotificationManager import android.app.Service diff --git a/app/src/main/java/com/chiller3/bcr/Notifications.kt b/app/src/main/kotlin/com/patrykmis/bar/Notifications.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/Notifications.kt rename to app/src/main/kotlin/com/patrykmis/bar/Notifications.kt index 1c8304dec..61c96bb81 100644 --- a/app/src/main/java/com/chiller3/bcr/Notifications.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/Notifications.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.annotation.SuppressLint import android.app.Notification diff --git a/app/src/main/java/com/chiller3/bcr/OpenPersistentDocumentTree.kt b/app/src/main/kotlin/com/patrykmis/bar/OpenPersistentDocumentTree.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/OpenPersistentDocumentTree.kt rename to app/src/main/kotlin/com/patrykmis/bar/OpenPersistentDocumentTree.kt index efb826768..4bd8090ac 100644 --- a/app/src/main/java/com/chiller3/bcr/OpenPersistentDocumentTree.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/OpenPersistentDocumentTree.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import android.content.Intent diff --git a/app/src/main/java/com/chiller3/bcr/OutputDirUtils.kt b/app/src/main/kotlin/com/patrykmis/bar/OutputDirUtils.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/OutputDirUtils.kt rename to app/src/main/kotlin/com/patrykmis/bar/OutputDirUtils.kt index 79d9a50fd..04fa691f0 100644 --- a/app/src/main/java/com/chiller3/bcr/OutputDirUtils.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/OutputDirUtils.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import android.net.Uri diff --git a/app/src/main/java/com/chiller3/bcr/OutputDirectoryBottomSheetFragment.kt b/app/src/main/kotlin/com/patrykmis/bar/OutputDirectoryBottomSheetFragment.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/OutputDirectoryBottomSheetFragment.kt rename to app/src/main/kotlin/com/patrykmis/bar/OutputDirectoryBottomSheetFragment.kt index a0e8d6248..366fdd067 100644 --- a/app/src/main/java/com/chiller3/bcr/OutputDirectoryBottomSheetFragment.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/OutputDirectoryBottomSheetFragment.kt @@ -1,10 +1,10 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.chiller3.bcr.databinding.OutputDirectoryBottomSheetBinding +import com.patrykmis.bar.databinding.OutputDirectoryBottomSheetBinding import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.slider.Slider diff --git a/app/src/main/java/com/chiller3/bcr/OutputFile.kt b/app/src/main/kotlin/com/patrykmis/bar/OutputFile.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/OutputFile.kt rename to app/src/main/kotlin/com/patrykmis/bar/OutputFile.kt index 7bd134e03..08349daf0 100644 --- a/app/src/main/java/com/chiller3/bcr/OutputFile.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/OutputFile.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.ContentResolver import android.content.Context diff --git a/app/src/main/java/com/chiller3/bcr/OutputFormatBottomSheetFragment.kt b/app/src/main/kotlin/com/patrykmis/bar/OutputFormatBottomSheetFragment.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/OutputFormatBottomSheetFragment.kt rename to app/src/main/kotlin/com/patrykmis/bar/OutputFormatBottomSheetFragment.kt index 2f3b21633..673f8b9e5 100644 --- a/app/src/main/java/com/chiller3/bcr/OutputFormatBottomSheetFragment.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/OutputFormatBottomSheetFragment.kt @@ -1,13 +1,13 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible -import com.chiller3.bcr.databinding.BottomSheetChipBinding -import com.chiller3.bcr.databinding.OutputFormatBottomSheetBinding -import com.chiller3.bcr.format.* +import com.patrykmis.bar.databinding.BottomSheetChipBinding +import com.patrykmis.bar.databinding.OutputFormatBottomSheetBinding +import com.patrykmis.bar.format.* import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.chip.ChipGroup import com.google.android.material.slider.Slider diff --git a/app/src/main/java/com/chiller3/bcr/Permissions.kt b/app/src/main/kotlin/com/patrykmis/bar/Permissions.kt similarity index 89% rename from app/src/main/java/com/chiller3/bcr/Permissions.kt rename to app/src/main/kotlin/com/patrykmis/bar/Permissions.kt index 103d26bb4..ace4ce548 100644 --- a/app/src/main/java/com/chiller3/bcr/Permissions.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/Permissions.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.Manifest import android.annotation.SuppressLint @@ -20,16 +20,12 @@ object Permissions { } val REQUIRED: Array = arrayOf(Manifest.permission.RECORD_AUDIO) + NOTIFICATION - val OPTIONAL: Array = arrayOf( - Manifest.permission.READ_CONTACTS, - Manifest.permission.READ_PHONE_STATE, - ) private fun isGranted(context: Context, permission: String) = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED /** - * Check if all permissions required for call recording have been granted. + * Check if all permissions required for recording have been granted. */ fun haveRequired(context: Context): Boolean = REQUIRED.all { isGranted(context, it) } diff --git a/app/src/main/java/com/chiller3/bcr/Preferences.kt b/app/src/main/kotlin/com/patrykmis/bar/Preferences.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/Preferences.kt rename to app/src/main/kotlin/com/patrykmis/bar/Preferences.kt index a8fcd3fce..018e88fef 100644 --- a/app/src/main/java/com/chiller3/bcr/Preferences.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/Preferences.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import android.content.Intent @@ -6,8 +6,8 @@ import android.net.Uri import android.util.Log import androidx.core.content.edit import androidx.preference.PreferenceManager -import com.chiller3.bcr.format.Format -import com.chiller3.bcr.format.SampleRate +import com.patrykmis.bar.format.Format +import com.patrykmis.bar.format.SampleRate import java.io.File class Preferences(private val context: Context) { diff --git a/app/src/main/java/com/chiller3/bcr/RecorderApplication.kt b/app/src/main/kotlin/com/patrykmis/bar/RecorderApplication.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/RecorderApplication.kt rename to app/src/main/kotlin/com/patrykmis/bar/RecorderApplication.kt index 2f736084d..6927d2dd5 100644 --- a/app/src/main/java/com/chiller3/bcr/RecorderApplication.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/RecorderApplication.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.app.Application import android.util.Log diff --git a/app/src/main/java/com/chiller3/bcr/RecorderMicTileService.kt b/app/src/main/kotlin/com/patrykmis/bar/RecorderMicTileService.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/RecorderMicTileService.kt rename to app/src/main/kotlin/com/patrykmis/bar/RecorderMicTileService.kt index bdd832ecb..3e3517d44 100644 --- a/app/src/main/java/com/chiller3/bcr/RecorderMicTileService.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/RecorderMicTileService.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Intent import android.os.Handler diff --git a/app/src/main/java/com/chiller3/bcr/RecorderProvider.kt b/app/src/main/kotlin/com/patrykmis/bar/RecorderProvider.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/RecorderProvider.kt rename to app/src/main/kotlin/com/patrykmis/bar/RecorderProvider.kt index 1936a40de..771d800ce 100644 --- a/app/src/main/java/com/chiller3/bcr/RecorderProvider.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/RecorderProvider.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.ContentProvider import android.content.ContentResolver @@ -9,7 +9,7 @@ import android.net.Uri import android.os.ParcelFileDescriptor /** - * This is an extremely minimal content provider so that BCR can provide an openable/shareable URI + * This is an extremely minimal content provider so that BAR can provide an openable/shareable URI * to other applications. SAF URIs cannot be shared directly because permission grants cannot be * propagated to the target app. * diff --git a/app/src/main/java/com/chiller3/bcr/RecorderThread.kt b/app/src/main/kotlin/com/patrykmis/bar/RecorderThread.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/RecorderThread.kt rename to app/src/main/kotlin/com/patrykmis/bar/RecorderThread.kt index 39783a466..250f2bf8b 100644 --- a/app/src/main/java/com/chiller3/bcr/RecorderThread.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/RecorderThread.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.Manifest import android.annotation.SuppressLint @@ -18,9 +18,9 @@ import android.telephony.TelephonyManager import android.util.Log import androidx.core.net.toFile import androidx.documentfile.provider.DocumentFile -import com.chiller3.bcr.format.Encoder -import com.chiller3.bcr.format.Format -import com.chiller3.bcr.format.SampleRate +import com.patrykmis.bar.format.Encoder +import com.patrykmis.bar.format.Format +import com.patrykmis.bar.format.SampleRate import java.lang.Process import java.nio.ByteBuffer import java.text.ParsePosition @@ -54,7 +54,6 @@ class RecorderThread( private val tag = "${RecorderThread::class.java.simpleName}/${id}" private val prefs = Preferences(context) private val isDebug = prefs.isDebugMode - private val isMic = call == null // Thread state @Volatile private var isCancelled = false @@ -276,7 +275,7 @@ class RecorderThread( var errorMsg: String? = null var resultUri: Uri? = null - val templateKey = if (pendingCallDetails == null) { "filename_mic" } else { "filename" } + val templateKey = "filename_mic" synchronized(filenameLock) { // We initially do not allow custom filename templates because SAF is extraordinarily @@ -527,11 +526,7 @@ class RecorderThread( Log.d(tag, "AudioRecord minimum buffer size: $minBufSize") val audioRecord = AudioRecord( - if (isMic) { - MediaRecorder.AudioSource.MIC - } else { - MediaRecorder.AudioSource.VOICE_CALL - }, + MediaRecorder.AudioSource.UNPROCESSED, sampleRate.value.toInt(), CHANNEL_CONFIG, ENCODING, @@ -668,7 +663,7 @@ class RecorderThread( } companion object { - private const val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO + private const val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO private const val ENCODING = AudioFormat.ENCODING_PCM_16BIT // Eg. 20220429_180249.123-0400 diff --git a/app/src/main/java/com/chiller3/bcr/Retention.kt b/app/src/main/kotlin/com/patrykmis/bar/Retention.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/Retention.kt rename to app/src/main/kotlin/com/patrykmis/bar/Retention.kt index c2a3afde3..34a09868f 100644 --- a/app/src/main/java/com/chiller3/bcr/Retention.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/Retention.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Context import java.time.Duration diff --git a/app/src/main/java/com/chiller3/bcr/SettingsActivity.kt b/app/src/main/kotlin/com/patrykmis/bar/SettingsActivity.kt similarity index 95% rename from app/src/main/java/com/chiller3/bcr/SettingsActivity.kt rename to app/src/main/kotlin/com/patrykmis/bar/SettingsActivity.kt index 4edb73b21..07427c00e 100644 --- a/app/src/main/java/com/chiller3/bcr/SettingsActivity.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/SettingsActivity.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.Intent import android.content.SharedPreferences @@ -9,10 +9,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat -import com.chiller3.bcr.format.Format -import com.chiller3.bcr.format.NoParamInfo -import com.chiller3.bcr.format.RangedParamInfo -import com.chiller3.bcr.format.SampleRate +import com.patrykmis.bar.format.Format +import com.patrykmis.bar.format.NoParamInfo +import com.patrykmis.bar.format.RangedParamInfo +import com.patrykmis.bar.format.SampleRate class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -152,7 +152,7 @@ class SettingsActivity : AppCompatActivity() { return true } else { // Ask for optional permissions the first time only - requestPermissionRequired.launch(Permissions.REQUIRED + Permissions.OPTIONAL) + requestPermissionRequired.launch(Permissions.REQUIRED) } // This is only reachable if battery optimization is not already inhibited prefInhibitBatteryOpt -> requestInhibitBatteryOpt.launch( @@ -175,8 +175,8 @@ class SettingsActivity : AppCompatActivity() { return true } prefVersion -> { - val uri = Uri.parse(BuildConfig.PROJECT_URL_AT_COMMIT) - startActivity(Intent(Intent.ACTION_VIEW, uri)) + // val uri = Uri.parse(BuildConfig.PROJECT_URL_AT_COMMIT) + // startActivity(Intent(Intent.ACTION_VIEW, uri)) return true } } diff --git a/app/src/main/java/com/chiller3/bcr/UriExtensions.kt b/app/src/main/kotlin/com/patrykmis/bar/UriExtensions.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/UriExtensions.kt rename to app/src/main/kotlin/com/patrykmis/bar/UriExtensions.kt index d879de025..34337cece 100644 --- a/app/src/main/java/com/chiller3/bcr/UriExtensions.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/UriExtensions.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr +package com.patrykmis.bar import android.content.ContentResolver import android.net.Uri diff --git a/app/src/main/java/com/chiller3/bcr/format/AacFormat.kt b/app/src/main/kotlin/com/patrykmis/bar/format/AacFormat.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/format/AacFormat.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/AacFormat.kt index 187e80cb6..e38b0009a 100644 --- a/app/src/main/java/com/chiller3/bcr/format/AacFormat.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/AacFormat.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodecInfo import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/Container.kt b/app/src/main/kotlin/com/patrykmis/bar/format/Container.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/format/Container.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/Container.kt index dd384b032..29c45cd12 100644 --- a/app/src/main/java/com/chiller3/bcr/format/Container.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/Container.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/Encoder.kt b/app/src/main/kotlin/com/patrykmis/bar/format/Encoder.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/format/Encoder.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/Encoder.kt index 04a07ccb1..d0cbb639f 100644 --- a/app/src/main/java/com/chiller3/bcr/format/Encoder.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/Encoder.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaFormat import java.nio.ByteBuffer diff --git a/app/src/main/java/com/chiller3/bcr/format/FlacContainer.kt b/app/src/main/kotlin/com/patrykmis/bar/format/FlacContainer.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/format/FlacContainer.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/FlacContainer.kt index 03d43e273..b030e871d 100644 --- a/app/src/main/java/com/chiller3/bcr/format/FlacContainer.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/FlacContainer.kt @@ -1,7 +1,7 @@ @file:Suppress("OPT_IN_IS_NOT_ENABLED") @file:OptIn(ExperimentalUnsignedTypes::class) -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/FlacFormat.kt b/app/src/main/kotlin/com/patrykmis/bar/format/FlacFormat.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/format/FlacFormat.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/FlacFormat.kt index 52ce86cb5..dd3486b69 100644 --- a/app/src/main/java/com/chiller3/bcr/format/FlacFormat.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/FlacFormat.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaFormat import java.io.FileDescriptor diff --git a/app/src/main/java/com/chiller3/bcr/format/Format.kt b/app/src/main/kotlin/com/patrykmis/bar/format/Format.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/format/Format.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/Format.kt index b4b38c6c7..cae39d821 100644 --- a/app/src/main/java/com/chiller3/bcr/format/Format.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/Format.kt @@ -1,9 +1,9 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.AudioFormat import android.media.MediaFormat -import com.chiller3.bcr.Preferences -import com.chiller3.bcr.frameSizeInBytesCompat +import com.patrykmis.bar.Preferences +import com.patrykmis.bar.frameSizeInBytesCompat import java.io.FileDescriptor sealed class Format { diff --git a/app/src/main/java/com/chiller3/bcr/format/FormatParamInfo.kt b/app/src/main/kotlin/com/patrykmis/bar/format/FormatParamInfo.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/format/FormatParamInfo.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/FormatParamInfo.kt index f2f24476d..959383399 100644 --- a/app/src/main/java/com/chiller3/bcr/format/FormatParamInfo.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/FormatParamInfo.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format sealed class FormatParamInfo(val default: UInt) { /** diff --git a/app/src/main/java/com/chiller3/bcr/format/MediaCodecEncoder.kt b/app/src/main/kotlin/com/patrykmis/bar/format/MediaCodecEncoder.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/format/MediaCodecEncoder.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/MediaCodecEncoder.kt index 863c08f2f..88186bc19 100644 --- a/app/src/main/java/com/chiller3/bcr/format/MediaCodecEncoder.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/MediaCodecEncoder.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaCodecList diff --git a/app/src/main/java/com/chiller3/bcr/format/MediaMuxerContainer.kt b/app/src/main/kotlin/com/patrykmis/bar/format/MediaMuxerContainer.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/format/MediaMuxerContainer.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/MediaMuxerContainer.kt index 49190bcd4..4522f3e4a 100644 --- a/app/src/main/java/com/chiller3/bcr/format/MediaMuxerContainer.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/MediaMuxerContainer.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/OpusFormat.kt b/app/src/main/kotlin/com/patrykmis/bar/format/OpusFormat.kt similarity index 97% rename from app/src/main/java/com/chiller3/bcr/format/OpusFormat.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/OpusFormat.kt index ec7d597e0..799581e29 100644 --- a/app/src/main/java/com/chiller3/bcr/format/OpusFormat.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/OpusFormat.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaFormat import android.media.MediaMuxer diff --git a/app/src/main/java/com/chiller3/bcr/format/PassthroughEncoder.kt b/app/src/main/kotlin/com/patrykmis/bar/format/PassthroughEncoder.kt similarity index 98% rename from app/src/main/java/com/chiller3/bcr/format/PassthroughEncoder.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/PassthroughEncoder.kt index eda71f377..a2a0b0cd1 100644 --- a/app/src/main/java/com/chiller3/bcr/format/PassthroughEncoder.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/PassthroughEncoder.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/SampleRate.kt b/app/src/main/kotlin/com/patrykmis/bar/format/SampleRate.kt similarity index 89% rename from app/src/main/java/com/chiller3/bcr/format/SampleRate.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/SampleRate.kt index 3e2a475d2..ec657481d 100644 --- a/app/src/main/java/com/chiller3/bcr/format/SampleRate.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/SampleRate.kt @@ -1,6 +1,6 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format -import com.chiller3.bcr.Preferences +import com.patrykmis.bar.Preferences @JvmInline value class SampleRate(val value: UInt) { @@ -19,7 +19,8 @@ value class SampleRate(val value: UInt) { SampleRate(12_000u), SampleRate(16_000u), SampleRate(24_000u), - SampleRate(48_000u), + SampleRate(44_100u), + SampleRate(48_000u) ) val default = all.last() diff --git a/app/src/main/java/com/chiller3/bcr/format/WaveContainer.kt b/app/src/main/kotlin/com/patrykmis/bar/format/WaveContainer.kt similarity index 99% rename from app/src/main/java/com/chiller3/bcr/format/WaveContainer.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/WaveContainer.kt index 77ffd52f4..b62f9c7fb 100644 --- a/app/src/main/java/com/chiller3/bcr/format/WaveContainer.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/WaveContainer.kt @@ -1,7 +1,7 @@ @file:Suppress("OPT_IN_IS_NOT_ENABLED") @file:OptIn(ExperimentalUnsignedTypes::class) -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaCodec import android.media.MediaFormat diff --git a/app/src/main/java/com/chiller3/bcr/format/WaveFormat.kt b/app/src/main/kotlin/com/patrykmis/bar/format/WaveFormat.kt similarity index 96% rename from app/src/main/java/com/chiller3/bcr/format/WaveFormat.kt rename to app/src/main/kotlin/com/patrykmis/bar/format/WaveFormat.kt index 92db7ce5c..8c32a9a1b 100644 --- a/app/src/main/java/com/chiller3/bcr/format/WaveFormat.kt +++ b/app/src/main/kotlin/com/patrykmis/bar/format/WaveFormat.kt @@ -1,4 +1,4 @@ -package com.chiller3.bcr.format +package com.patrykmis.bar.format import android.media.MediaFormat import java.io.FileDescriptor diff --git a/app/src/main/res/layout/output_format_bottom_sheet.xml b/app/src/main/res/layout/output_format_bottom_sheet.xml index 1545af510..912e51fef 100644 --- a/app/src/main/res/layout/output_format_bottom_sheet.xml +++ b/app/src/main/res/layout/output_format_bottom_sheet.xml @@ -18,7 +18,7 @@ android:text="@string/output_format_bottom_sheet_output_format" android:textAppearance="?attr/textAppearanceHeadline6" /> - - - BCR - Basic Call Recorder + BAR + Basic Audio Recorder General @@ -50,10 +51,6 @@ Alertas de errores durante la grabación de llamadas Alertas de éxito Alertas para grabaciones de llamadas exitosas - Grabación de llamadas en curso - Grabación de llamadas en pausa - No se pudo grabar la llamada - Llamada grabada con éxito La grabación falló en un componente interno de Android (%s). Es posible que este dispositivo o firmware no admita la grabación de llamadas. Abrir Compartir @@ -62,5 +59,4 @@ Reanudar - Grabación de llamada diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index bcc95ecab..4cf6c136c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,6 +1,7 @@ + - BCR - Basic Call Recorder + BAR + Basic Audio Recorder Général @@ -43,9 +44,6 @@ Service d\'arrière-plan Notification persistante pour l\'enregistrement en arrière-plan Alertes d\'erreurs pendant l\'enregistrement - Enregistrement d\'appel en cours - Enregistrement d\'appel échoué - Enregsitrement d\'appel diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index f271d14aa..23ce97a33 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -1,6 +1,7 @@ - - BCR - מקליט שיחות בסיסי + + + BAR + מקליט שמע בסיסי כללי @@ -50,10 +51,6 @@ התראות על שגיאות במהלך הקלטת שיחה התראות סיום הקלטה בהצלחה התראות הקלטות שיחות שהסתיימו בהצלחה - הקלטת שיחה מתבצעת - הקלטת שיחה מושהית - הקלטת שיחה נכשלה - השיחה הוקלטה בהצלחה ההקלטה נכשלה ברכיב Android פנימי (%s). ייתכן שהמכשיר או הקושחה אינם תומכים בהקלטת שיחות פתיחה שיתוף @@ -62,5 +59,4 @@ המשך - הקלטת שיחה diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 474ad4bd2..f614215f2 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,6 +1,7 @@ + - BCR - Podstawowy rejestrator rozmów + BAR + Podstawowy rejestrator dźwięku Ogólne @@ -52,12 +53,8 @@ Informacje o błędach podczas nagrywania rozmów Zakończone nagrywanie Informacje o pomyślnym nagraniu rozmowy - Trwa nagrywanie rozmowy Trwa nagrywanie dźwięku - Nagrywanie rozmowy wstrzymane - Nie udało się nagrać rozmowy Nie udało się nagrać dźwięku - Pomyślnie nagrano rozmowę Pomyślnie nagrano dźwięk Podczas nagrywania wystąpił błąd w wewnętrznym komponencie Androida (%s). To urządzenie lub system może nie obsługiwać nagrywania rozmów. Otwórz @@ -67,6 +64,5 @@ Wznów - Nagrywanie rozmów Nagrywanie dźwięku diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index cf79fab4e..a8730f8ab 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,6 +1,7 @@ + - BCR - Basic Call Recorder + BAR + Basic Audio Recorder Основное @@ -47,9 +48,7 @@ Фоновые сервисы Постоянное уведомление для записи вызовов в фоновом режиме - Происходит запись вызова Оповещение об ошибках во время записи разговора - Не удалось записать звонок Открыть Поделиться Удалить @@ -63,5 +62,4 @@ Возобновить - Запись звонков diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 731cbd49c..a0716c7fb 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -1,6 +1,7 @@ - - BCR - Základný nahrávač hovorov + + + BAR + Základný zvukový záznamník Všeobecné @@ -51,10 +52,6 @@ Upozornenia na chyby počas nahrávania Úspešné upozornenia Upozornenia na úspešne dokončené nahrávky hovorov - Nahrávanie hovoru - Nahrávanie hovoru pozastavené - Nahrávanie hovoru zlyhalo - Hovor úspešne nahratý Nahrávanie zlyhalo: interný komponent systému Android (%s). Toto zariadenie pravdepodobne nepodporuje nahrávanie hovorov. Otvoriť Zdieľať @@ -63,5 +60,4 @@ Pokračovať - Nahrávanie hovorov diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 40196f1f8..47de68f2e 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,6 +1,7 @@ + - BCR - Basic Call Recorder + BAR + Basic Audio Recorder Genel @@ -42,12 +43,9 @@ Arka plan servisleri Arka plan çağrı kaydı için kalıcı bildirim Kayıt esnasındaki hatalar için uyarılar - Çağrı kaydediliyor - Çağrı kaydı başarısız Paylaş Sil - Çağrı kaydı diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e2481543..47f4c17e1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ - - BCR - Basic Call Recorder + + + BAR + Basic Audio Recorder General @@ -50,13 +51,9 @@ Alerts for errors during call recording Success alerts Alerts for successful call recordings - Call recording in progress Mic recording in progress - Call recording paused Mic recording paused - Failed to record call Failed to record mic - Successfully recorded call Successfully recorded mic The recording failed in an internal Android component (%s). This device or firmware might not support call recording. @@ -67,6 +64,5 @@ Resume - Call recording Mic recording diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index b1f4645b5..3a3f4e333 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,5 +1,5 @@ -