BCR — это простое приложение для записи звонков Android для устройств с root-доступом или устройств с собственной прошивкой. После включения он остается в стороне и автоматически записывает входящие и исходящие вызовы в фоновом режиме.
Как следует из названия, BCR стремится быть максимально простым. Проект достигнет своей цели, если единственные обновления, которые ему когда-либо понадобятся, будут связаны с совместимостью с новыми версиями Android. Таким образом, многие потенциально полезные функции никогда не будут реализованы, например:
VOICE_CALL
(например, использование микрофона + громкая связь)Загрузите последнюю версию со страницы выпусков. Чтобы проверить цифровую подпись, обратитесь к разделу «Проверка цифровой подписи».
Установите BCR как системное приложение.
Для устройств, рутированных с помощью Magisk/KernelSU , просто прошейте zip-архив как модуль Magisk/KernelSU из соответствующего приложения.
.apk
из zip-архива и установите его вручную перед перезагрузкой. Это необходимо, чтобы обойти ошибку в прошивке, из-за которой каталог данных приложения не создается, из-за чего BCR открывается на пустой экран.Для нерутированной кастомной прошивки прошейте zip-архив во время загрузки в рекавери.
READ_CALL_LOG
жестко ограничено в Android 10+, поэтому его невозможно предоставить даже через настройки Android. Чтобы снять это ограничение, запустите через adb после перезагрузки обратно в Android: # If rooted, run inside of `su`:
CLASSPATH=/system/priv-app/com.chiller3.bcr/app-release.apk app_process / com.chiller3.bcr.standalone.RemoveHardRestrictionsKt
# If unrooted, install BCR as both a user app and a system app:
pm install /system/priv-app/com.chiller3.bcr/app-release.apk
system
раздел пользовательской прошивки отформатирован с помощью erofs
, то файловая система доступна только для чтения и использовать этот метод невозможно.system/
в zip-архиве также будет работать, если файлы имеют права доступа 644
и метку SELinux u:object_r:system_file:s0
.Перезагрузитесь и откройте BCR.
Если установлены другие устройства записи вызовов, обязательно отключите их функцию записи телефонных разговоров. На большинстве устройств телефонный звонок не может быть записан двумя приложениями одновременно. Тем не менее, вполне нормально, если BCR записывает телефонные звонки и запись другого приложения, например. VOIP-звонки.
Включите запись звонков и выберите выходной каталог.
Если выходной каталог не выбран или выходной каталог больше не доступен, записи будут сохранены в /sdcard/Android/data/com.chiller3.bcr/files
. Обратите внимание, что в Android 12+ /sdcard/Android/data/
доступен только через USB или DocumentsUI (встроенный файловый менеджер AOSP).
При первом включении записи вызовов BCR предложит указать микрофон, уведомление (Android 13+), журнал вызовов, контакты и разрешения телефона. Для базовой функции записи разговоров требуются только разрешения на микрофон и уведомления. Если предоставлены дополнительные разрешения, к имени выходного файла добавляется дополнительная информация. Например, разрешение на контакты позволит добавлять имя контакта к имени файла.
Дополнительную информацию о разрешениях см. в разделе «Разрешения» ниже.
Чтобы установить будущие обновления, есть несколько способов:
.apk
также можно извлечь из zip-архива и установить напрямую. При использовании этого метода старая версия существует как системное приложение, а новая версия существует как установленное пользователем обновление системного приложения. Этот метод более удобен, если BCR встроен в образ прошивки Android. В отличие от встроенной функции записи звонков предустановленного приложения для набора номера на некоторых устройствах, BCR не уведомляет собеседника о том, что звонок записывается. BCR никогда не выводит какой-либо звук в аудиопоток вызова.
Если BCR включен, вообще избегайте использования встроенной записи звонков в номеронабирателе. Очень велика вероятность того, что его использование приведет к неожиданному поведению, например, к сбою записи или к тому, что номеронабиратель сообщит, что вызов записывается.
Если вы живете в юрисдикции, где требуется согласие двух сторон, вы несете ответственность за информирование другой стороны о том, что звонок записывается. При необходимости можно использовать правила автоматической записи для удаления записей по умолчанию. Однако учтите, что если вы решите сохранить запись во время разговора, запись будет содержать весь разговор, а не только ту его часть, которая была после согласия другой стороны.
BCR поддерживает прямую загрузку, что означает, что он способен выполнять и записывать вызовы до того, как устройство будет первоначально разблокировано после перезагрузки. В этом состоянии большая часть функций BCR по-прежнему будет работать, за исключением функций, для которых требуется список контактов или журнал вызовов. На практике это означает:
Однако если устройство разблокируется до завершения вызова, ни одно из этих ограничений не применяется.
Обратите внимание, что выходной каталог недоступен до первой разблокировки устройства. Записи, сделанные в этом состоянии, хранятся во внутреннем каталоге, недоступном для пользователя. После разблокировки устройства BCR переместит файлы в выходной каталог. Это может занять несколько минут.
CAPTURE_AUDIO_OUTPUT
( автоматически предоставляется разрешениями системного приложения )CONTROL_INCALL_EXPERIENCE
( автоматически предоставляется разрешениями системного приложения )RECORD_AUDIO
( должен быть предоставлен пользователем )FOREGROUND_SERVICE
, FOREGROUND_SERVICE_MICROPHONE
( автоматически предоставляется во время установки )POST_NOTIFICATIONS
( должен быть предоставлен пользователем на Android 13+ )READ_CALL_LOG
( необязательно )READ_CONTACTS
( необязательно )RECEIVE_BOOT_COMPLETED
, FOREGROUND_SERVICE_SPECIAL_USE
( автоматически предоставляется во время установки )READ_PHONE_STATE
( необязательно )REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
( необязательно )VIBRATE
( автоматически предоставляется во время установки ) Обратите внимание, что INTERNET
в списке отсутствует . BCR не имеет и никогда не будет иметь доступа к сети. BCR также никогда не будет взаимодействовать с другими приложениями, за исключением случаев, когда пользователь явно нажимает кнопки Open
или Share
в уведомлении, отображаемом после завершения записи. В этом сценарии целевому приложению предоставляется доступ только к этой единственной записи.
BCR имеет ограниченную поддержку приложений перенаправления вызовов, таких как Google Voice. Перенаправленные вызовы могут быть записаны только в том случае, если служба перенаправления вызовов использует стандартные телефонные звонки за кулисами (вместо VOIP).
Существует несколько ограничений при записи перенаправленных вызовов по сравнению с обычными вызовами:
All other calls
.Эти ограничения существуют потому, что при перенаправлении вызова только само приложение дозвона знает исходный номер телефона. Телефонная система Android об этом не знает. BCR может найти исходный номер телефона только путем поиска в журнале системных вызовов, когда дозвонщик добавляет запись в конце вызова.
BCR поддерживает настройку шаблона, используемого для определения имен выходных файлов записей. Шаблон по умолчанию:
{date}[_{direction}|][_sim{sim_slot}|][_{phone_number}|][_[{contact_name}|{caller_name}|{call_log_name}]|]
{var}
) используются для обозначения переменных. Переменные заменяются значениями, которые они представляют. Например, {phone_number}
заменяется фактическим номером телефона звонка.[{var}|default]
) используются для указания резервных вариантов. Например, [{contact_name}|{caller_name}|Unknown]
вставит имя контакта, если номер есть в контактах. В противном случае он вернется к идентификатору вызывающего абонента или Unknown
если ни имя контакта, ни идентификатор вызывающего абонента не существуют. Возврат к пустой строке также вполне допустим. Например, [{contact_name}|]
возвращает либо имя контакта, либо ничего.{date}
: временная метка звонка. Формат метки времени по умолчанию старается быть как можно более однозначным и имеет следующий вид: 20230414_215701.088-0400
. Пользовательский формат метки времени можно указать с помощью {date:<format string>}
. Например, {date:yyyy-MM-dd @ h.mm.ss a}
даст 2023-04-14 @ 9.57.01 PM
. Полный список символов форматирования меток времени можно найти по адресу: https://developer.android.com/reference/java/time/format/DateTimeFormatterBuilder#appendPattern(java.lang.String).{phone_number}{date}
приведет к отключению сохранения файлов, но {phone_number} ({date})
работает, поскольку между двумя переменными есть некоторый текст (
.yyMMdd_HHmmss
было изменено на HHmmss_yyMMdd
, временные метки из имен файлов старой записи будут проанализированы неправильно и могут быть удалены.{direction}
: [только для Android 10+] Для вызовов 1-на-1, in
или out
в зависимости от того, является ли вызов входящим или исходящим. Если вызов является конференц-вызовом, то вместо него используется conference
.{sim_slot}
: [только для Android 11+] Номер слота SIM-карты для вызова (считается с 1). Это определено только для устройств с несколькими SIM-картами, на которых установлено несколько активных SIM-карт, и если BCR предоставлено разрешение «Телефон».{sim_slot:always}
.{phone_number}
: номер телефона для звонка. Это не определено для частных вызовов. Доступные параметры форматирования:{phone_number:E.164}
: по умолчанию (то же, что и {phone_number}
). Номер телефона в международном формате E.164 ( +<country code><subscriber>
).{phone_number:digits_only}
: номер телефона, состоящий только из цифр (без +
и разделителей).{phone_number:formatted}
: номер телефона, отформатированный в стиле конкретной страны.{caller_name}
: идентификатор вызывающего абонента, предоставленный CNAP от оператора связи.{contact_name}
Имя (первого) контакта, связанного с номером телефона. Это определяется только в том случае, если BCR предоставлено разрешение «Контакты».{call_log_name}
: имя, отображаемое в журнале вызовов. Это может включать дополнительную информацию, например название компании, если системный номеронабиратель выполняет обратный поиск. Это определяется только в том случае, если BCR предоставлено разрешение на чтение журналов вызовов. Шаблон имени файла поддерживает указание подкаталогов с помощью символа /
. Косые черты разрешены в любом месте шаблона имени файла, включая {date}
(например, {date:yyyy/MM/dd}
). Однако любые косые черты, которые появляются после раскрытия других переменных, будут заменены символами подчеркивания. Например, если идентификатор вызывающего абонента для вызова — First/Last
, то {caller_name}
расширяется до First_Last
.
Обратите внимание, что из-за низкой производительности Android Storage Access Framework использование подкаталогов может значительно замедлить сохранение записи на некоторых устройствах. В сборках Android с хорошей реализацией SAF это может занять всего несколько секунд. В OEM-сборке Android с худшей известной реализацией SAF это может занять несколько минут. Задержка пропорциональна количеству файлов в выходном каталоге.
Если опция Write metadata file
включена, BCR запишет файл JSON в выходной каталог, содержащий все сведения, которые BCR знает о вызове, а также информацию о записанном звуке. Файл имеет то же имя, что и аудиофайл, но с расширением .json
.
Структура JSON показана в следующем примере. Обратите внимание, что гарантированно существуют только timestamp_unix_ms
, timestamp
и output.format.*
. Если значение поля невозможно определить (например, при возникновении ошибки или отказе в требуемом разрешении), ему присваивается значение null
.
{
// The timestamp represented as milliseconds since the Unix epoch in UTC.
"timestamp_unix_ms" : 1689817988931 ,
// The timestamp represented as ISO8601 (+ offset) in the local time zone.
"timestamp" : "2023-07-19T21:53:08.931-04:00" ,
// The call direction ("in", "out", or "conference").
// [Android 10+ only]
"direction" : "in" ,
// The SIM slot used for the call.
// [Android 11+ only; requires the Phone permission]
"sim_slot" : 1 ,
// The name shown in the dialer's call log. This may include the business'
// name for dialers that perform reverse lookups.
// [Requires the Call Log permission]
"call_log_name" : "John Doe" ,
// Details about the other party or parties in the call. There will be
// multiple entries for conference calls.
"calls" : [
{
// The raw phone number as reported by Android. For outgoing calls,
// this is usually what the user typed. For incoming calls, this is
// usually E.164 formatted. This will be null for private calls.
"phone_number" : "+11234567890" ,
// The phone number formatted using the country-specific style. This
// will be null for private calls or if Android cannot determine the
// country.
"phone_number_formatted" : "+1 123-456-7890" ,
// The caller name/ID as reported by CNAP from the carrier.
"caller_name" : "John Doe" ,
// The contact name associated with the phone number.
// [Requires the Contacts permission]
"contact_name" : "John Doe"
}
] ,
// Details about the output file.
"output" : {
// Details about the output file format.
"format" : {
// The audio encoding format.
"type" : "OGG/Opus" ,
// The MIME type of the container format (eg. OGG).
"mime_type_container" : "audio/ogg" ,
// The MIME type of the raw audio stream (eg. Opus).
"mime_type_audio" : "audio/opus" ,
// The type of the parameter value below. Either "bitrate",
// "compression_level", or "none".
"parameter_type" : "bitrate" ,
// The encoder quality/size parameter.
"parameter" : 48000 ,
} ,
// Details about the recording and encoding process. If the recording
// process fails, this is set to null.
"recording" : {
// The total number of audio frames that BCR read from the audio
// device. This includes the periods of time when the recording was
// paused or on hold.
// (Number of frames == number of samples * channel count)
"frames_total" : 96000 ,
// The number of audio frames that were actually saved to the output
// file. This excludes the periods of time when the recording was
// paused or on hold.
// (Number of frames == number of samples * channel count)
"frames_encoded" : 48000 ,
// The number of samples per second of audio.
"sample_rate" : 48000 ,
// The number of channels in the audio. This is currently always 1
// because no device supports stereo call audio.
"channel_count" : 1 ,
// The total time in seconds that BCR read from the audio device.
// (Equal to: frames_total / sample_rate / channel_count)
"duration_secs_total" : 2.0 ,
// The time in seconds of audio actually saved to the output file.
// (Equal to: frames_encoded / sample_rate / channel_count)
"duration_secs_encoded" : 1.0 ,
// The size of the recording buffer in frames. This is the maximum
// number of audio frames read from the audio driver before it is
// passed to the audio encoder.
"buffer_frames" : 640 ,
// The number of buffer overruns. This is the number of times that
// the CPU or storage couldn't keep up while encoding the raw audio,
// resulting in skips (loss of audio).
"buffer_overruns" : 0 ,
// Whether the call was ever paused by the user.
"was_ever_paused" : false ,
// Whether the call was ever placed on hold (call waiting).
"was_ever_holding" : false
}
}
}
В этом разделе описаны скрытые расширенные функции BCR.
BCR имеет скрытый режим отладки, который можно включить или отключить, нажав и удерживая номер версии.
Если режим отладки включен, BCR запишет файл журнала в выходной каталог после завершения записи разговора. Он называется так же, как и аудиофайл. Файл журнала содержит те же сообщения, что и adb logcat
, за исключением того, что сообщения, не относящиеся к BCR, отфильтровываются (BCR все равно не имеет разрешения на доступ к этим сообщениям).
BCR стремится никогда не регистрировать в файле журнала какую-либо конфиденциальную информацию. Информация о текущем вызове, такая как номер телефона, заменяется заполнителями, например <phone number>
. Однако другую информацию, которую нелегко отредактировать, вместо этого она будет усечена. Например, когда функция хранения файлов очищает старые файлы, имена файлов типа 20230101_010203.456+0000_out_1234567890_John_Doe.oga
регистрируются как 20<...>ga
.
Сообщая об ошибках, включите файл журнала, поскольку он чрезвычайно полезен для определения того, что может быть не так. (Но, пожалуйста, дважды проверьте файл журнала, чтобы убедиться, что в нем нет конфиденциальной информации!)
Для правильной работы BCR в значительной степени зависит от разрешений системных приложений. В первую очередь это связано с двумя разрешениями:
CONTROL_INCALL_EXPERIENCE
Это разрешение позволяет службе телефонии Android привязываться к InCallService
BCR, при этом BCR не является носимым сопутствующим приложением, автомобильным пользовательским интерфейсом или номеронабирателем по умолчанию. После привязки служба будет получать обратные вызовы для событий изменения вызова (например, входящий вызов в состоянии звонка). Этот метод гораздо более надежен, чем использование разрешения READ_PHONE_STATE
и использование широковещательных рассылок android.intent.action.PHONE_STATE
.
Этот метод имеет несколько дополнительных преимуществ. Благодаря тому, как служба телефонии привязывается к InCallService
BCR, служба может включаться и выходить из переднего плана по мере необходимости во время вызова и получать доступ к аудиопотоку, не нарушая ограничений доступа к фоновому микрофону Android 12+. Он также не требует запуска службы вручную из приемника широковещательной передачи ACTION_BOOT_COMPLETED
и, следовательно, на нее не влияют задержки этой широковещательной передачи во время начальной загрузки.
CAPTURE_AUDIO_OUTPUT
Это разрешение используется для записи аудиопотока VOICE_CALL
. Доступ к этому потоку, а также к некоторым другим, таким как VOICE_DOWNLINK
и VOICE_UPLINK
, невозможен без разрешения системы.
Благодаря этим двум разрешениям BCR может надежно обнаруживать телефонные звонки и записывать аудиопоток звонка. Процесс записи извлекает необработанный звук PCM s16le и использует встроенные кодеры Android для создания сжатого выходного файла.
И zip-файл, и содержащийся в нем APK имеют цифровую подпись. ПРИМЕЧАНИЕ . Начиная с версии 1.31 механизм подписи zip-файлов переключен с GPG на SSH. Чтобы проверить подписи для старых версий, см. README.md
версии 1.30.
Чтобы проверить цифровые подписи загрузок, выполните следующие действия.
Сначала извлеките APK из zip-архива, а затем запустите:
apksigner verify --print-certs system/priv-app/com.chiller3.bcr/app-release.apk
Затем убедитесь, что дайджест SHA-256 сертификата подписи APK:
d16f9b375df668c58ef4bb855eae959713d6d02e45f7f2c05ce2c27ae944f4f9
BCR можно создать, как и большинство других приложений Android, с помощью Android Studio или командной строки gradle.
Чтобы собрать APK:
./gradlew assembleDebug
Чтобы собрать zip-архив модуля Magisk (который при необходимости автоматически запускает задачу assembleDebug
):
./gradlew zipDebug
Выходной файл записывается в app/build/distributions/debug/
. APK-файл будет подписан автоматически сгенерированным ключом отладки по умолчанию.
Чтобы создать сборку выпуска с определенным ключом подписи, настройте следующие переменные среды:
export RELEASE_KEYSTORE=/path/to/keystore.jks
export RELEASE_KEY_ALIAS=alias_name
read -r -s RELEASE_KEYSTORE_PASSPHRASE
read -r -s RELEASE_KEY_PASSPHRASE
export RELEASE_KEYSTORE_PASSPHRASE
export RELEASE_KEY_PASSPHRASE
а затем создайте zip-архив выпуска:
./gradlew zipRelease
Запросы на исправление ошибок и перевод приветствуются и очень ценятся!
Если вы заинтересованы во внедрении новой функции и хотите, чтобы она была включена в BCR, сначала откройте проблему, чтобы обсудить ее. Я хочу, чтобы BCR был максимально простым и не требующим особого обслуживания, поэтому я не слишком склонен добавлять какие-либо новые функции, но меня могут убедить в обратном.
BCR распространяется по лицензии GPLv3. Полный текст лицензии см. в разделе LICENSE
.