BCR es una sencilla aplicación de grabación de llamadas de Android para dispositivos rooteados o dispositivos que ejecutan firmware personalizado. Una vez habilitado, permanece apartado y registra automáticamente las llamadas entrantes y salientes en segundo plano.
Como su nombre indica, BCR pretende ser lo más básico posible. El proyecto habrá logrado su objetivo si las únicas actualizaciones que necesita son para la compatibilidad con las nuevas versiones de Android. Por lo tanto, muchas funciones potencialmente útiles nunca se implementarán, como por ejemplo:
VOICE_CALL
(por ejemplo, usar micrófono + altavoz)Descargue la última versión desde la página de lanzamientos. Para verificar la firma digital, consulte la sección de verificación de firmas digitales.
Instale BCR como una aplicación del sistema.
Para dispositivos rooteados con Magisk/KernelSU , simplemente actualice el zip como un módulo Magisk/KernelSU desde la aplicación respectiva.
.apk
del zip e instálelo manualmente antes de reiniciar. Esto es necesario para solucionar un error en el firmware donde no se crea el directorio de datos de la aplicación, lo que hace que BCR se abra en una pantalla en blanco.Para firmware personalizado no rooteado , actualice el zip mientras arranca en recuperación.
READ_CALL_LOG
está estrictamente restringido en Android 10+, lo que impide que se conceda, incluso a través de la configuración de Android. Para eliminar esta restricción, ejecute adb después de reiniciar en 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
del firmware personalizado está formateada con erofs
, entonces el sistema de archivos es de solo lectura y no es posible utilizar este método.system/
en el zip también funcionará siempre que los archivos tengan permisos 644
y la etiqueta SELinux u:object_r:system_file:s0
.Reinicie y abra BCR.
Si hay otras grabadoras de llamadas instaladas, asegúrese de desactivar su función de grabación de llamadas telefónicas. En la mayoría de los dispositivos, dos aplicaciones no pueden grabar una llamada telefónica al mismo tiempo. Sin embargo, está bien que BCR registre las llamadas telefónicas y otra aplicación registre, por ejemplo. Llamadas VoIP.
Habilite la grabación de llamadas y elija un directorio de salida.
Si no se selecciona ningún directorio de salida o si ya no se puede acceder al directorio de salida, las grabaciones se guardarán en /sdcard/Android/data/com.chiller3.bcr/files
. Tenga en cuenta que en Android 12+, solo se puede acceder /sdcard/Android/data/
a través de USB o DocumentsUI (el administrador de archivos integrado de AOSP).
Al habilitar la grabación de llamadas por primera vez, BCR solicitará permisos de micrófono, notificación (Android 13+), registro de llamadas, contactos y teléfono. Solo se requieren permisos de micrófono y notificación para la funcionalidad básica de grabación de llamadas. Si se otorgan permisos adicionales, se agrega más información al nombre del archivo de salida. Por ejemplo, el permiso de contactos permitirá que el nombre del contacto se agregue al nombre del archivo.
Consulte la sección de permisos a continuación para obtener más detalles sobre los permisos.
Para instalar futuras actualizaciones, existen un par de métodos:
.apk
también se puede extraer del zip e instalarlo directamente. Con este método, la versión anterior existe como una aplicación del sistema y la nueva versión existe como una actualización de la aplicación del sistema instalada por el usuario. Este método es más conveniente si BCR está integrado en la imagen del firmware de Android. A diferencia de la función de grabación de llamadas incorporada de la aplicación de marcador preinstalada en algunos dispositivos, BCR no anuncia que la llamada se está grabando a la otra parte. BCR nunca emite audio de ningún tipo al flujo de audio de la llamada.
Cuando BCR está habilitado, evite usar la grabadora de llamadas incorporada del marcador. Existe una gran posibilidad de que su uso provoque un comportamiento inesperado, como que ambas grabaciones fallen o que el marcador anuncie que la llamada se está grabando.
Si vive en una jurisdicción donde se requiere el consentimiento de ambas partes, usted es responsable de informar a la otra parte que la llamada se está grabando. Si es necesario, se pueden utilizar reglas de grabación automática para descartar grabaciones de forma predeterminada. Sin embargo, tenga en cuenta que si elige conservar la grabación durante la mitad de la llamada, la grabación contendrá la llamada completa, no solo la parte posterior al consentimiento de la otra parte.
BCR reconoce el arranque directo, lo que significa que es capaz de ejecutar y grabar llamadas antes de que el dispositivo se desbloquee inicialmente después de un reinicio. En este estado, la mayoría de las funciones de BCR seguirán funcionando, aparte de las funciones que requieren la lista de contactos o el registro de llamadas. En la práctica, esto significa:
Sin embargo, si el dispositivo se desbloquea antes de que finalice la llamada, no se aplica ninguna de estas limitaciones.
Tenga en cuenta que el directorio de salida no está disponible antes de que se desbloquee el dispositivo por primera vez. Las grabaciones realizadas mientras se encuentra en el estado se almacenan en un directorio interno al que el usuario no puede acceder. Una vez desbloqueado el dispositivo, BCR moverá los archivos al directorio de salida. Esto puede tardar unos minutos en completarse.
CAPTURE_AUDIO_OUTPUT
( otorgado automáticamente por los permisos de la aplicación del sistema )CONTROL_INCALL_EXPERIENCE
( otorgado automáticamente por los permisos de la aplicación del sistema )RECORD_AUDIO
( debe ser otorgado por el usuario )FOREGROUND_SERVICE
, FOREGROUND_SERVICE_MICROPHONE
( concedido automáticamente en el momento de la instalación )POST_NOTIFICATIONS
( debe ser otorgado por el usuario en Android 13+ )READ_CALL_LOG
( opcional )READ_CONTACTS
( opcional )RECEIVE_BOOT_COMPLETED
, FOREGROUND_SERVICE_SPECIAL_USE
( concedido automáticamente en el momento de la instalación )READ_PHONE_STATE
( opcional )REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
( opcional )VIBRATE
( otorgado automáticamente en el momento de la instalación ) Tenga en cuenta que INTERNET
no está en la lista. BCR no accede ni accederá nunca a la red. BCR tampoco se comunicará nunca con otras aplicaciones, excepto si el usuario toca explícitamente los botones Open
o Share
en la notificación que se muestra cuando se completa una grabación. En ese escenario, la aplicación de destino solo tiene acceso a esa única grabación.
BCR tiene soporte limitado para aplicaciones de redirección de llamadas, como Google Voice. Las llamadas redirigidas solo se pueden grabar si el servicio de redirección de llamadas utiliza llamadas telefónicas estándar entre bastidores (en lugar de VOIP).
Existen varias limitaciones al grabar llamadas redirigidas en comparación con las llamadas normales:
All other calls
.Estas limitaciones existen porque cuando se redirige una llamada, solo la aplicación del marcador conoce el número de teléfono original. El sistema de telefonía Android no es consciente de ello. BCR solo puede encontrar el número de teléfono original buscando en el registro de llamadas del sistema cuando el marcador agrega la entrada al final de la llamada.
BCR admite la personalización de la plantilla utilizada para determinar los nombres de los archivos de salida de las grabaciones. La plantilla predeterminada es:
{date}[_{direction}|][_sim{sim_slot}|][_{phone_number}|][_[{contact_name}|{caller_name}|{call_log_name}]|]
{var}
) se utilizan para referirse a variables. Las variables se reemplazan por el valor que representan. Por ejemplo, {phone_number}
se reemplaza por el número de teléfono real de la llamada.[{var}|default]
) se utilizan para especificar alternativas. Por ejemplo, [{contact_name}|{caller_name}|Unknown]
insertará el nombre del contacto si el número está en los contactos. De lo contrario, recurrirá al identificador de llamadas o Unknown
si no existen ni el nombre del contacto ni el identificador de llamadas. Recurrir a una cadena vacía también es perfectamente válido. Por ejemplo, [{contact_name}|]
se evalúa como el nombre del contacto o nada.{date}
: la marca de tiempo de la llamada. El formato de marca de tiempo predeterminado intenta ser lo más inequívoco posible y tiene el formato: 20230414_215701.088-0400
. Se puede especificar un formato de marca de tiempo personalizado con {date:<format string>}
. Por ejemplo, {date:yyyy-MM-dd @ h.mm.ss a}
produciría 2023-04-14 @ 9.57.01 PM
. Puede encontrar una lista completa de caracteres de formato de marca de tiempo en: https://developer.android.com/reference/java/time/format/DateTimeFormatterBuilder#appendPattern(java.lang.String).{phone_number}{date}
hará que se deshabilite la retención de archivos, pero {phone_number} ({date})
funciona porque hay algo de texto (
entre las dos variables.yyMMdd_HHmmss
se cambió a HHmmss_yyMMdd
, las marcas de tiempo de los nombres de archivo de la grabación anterior se analizarían incorrectamente y podrían eliminarse.{direction}
: [solo Android 10+] Para llamadas 1 a 1, ya sea in
o out
dependiendo de si la llamada es entrante o saliente. Si la llamada es una llamada de conferencia, entonces se utiliza conference
.{sim_slot}
: [solo Android 11+] El número de ranura SIM para la llamada (contando desde 1). Esto solo se define para dispositivos multi-SIM que tienen varias SIM activas y si a BCR se le otorga el permiso de teléfono.{sim_slot:always}
.{phone_number}
: el número de teléfono de la llamada. Esto no está definido para llamadas privadas. Opciones de formato disponibles:{phone_number:E.164}
: predeterminado (igual que {phone_number}
). Número de teléfono formateado en el formato internacional E.164 ( +<country code><subscriber>
).{phone_number:digits_only}
: número de teléfono solo con dígitos (sin +
ni separadores).{phone_number:formatted}
: número de teléfono formateado con el estilo específico del país.{caller_name}
: el identificador de llamadas proporcionado por CNAP del operador.{contact_name}
El nombre del (primer) contacto asociado con el número de teléfono. Esto solo se define si a BCR se le concede el permiso de Contactos.{call_log_name}
: el nombre que se muestra en el registro de llamadas. Esto puede incluir más información, como el nombre de la empresa, si el marcador del sistema realiza búsquedas inversas. Esto solo se define si a BCR se le concede el permiso Leer registros de llamadas. La plantilla de nombre de archivo admite la especificación de subdirectorios utilizando el carácter /
. Se permiten barras diagonales en cualquier lugar dentro de la plantilla de nombre de archivo, incluido {date}
(p. ej., {date:yyyy/MM/dd}
). Sin embargo, cualquier barra diagonal que aparezca después de expandir otras variables se reemplazará con guiones bajos. Por ejemplo, si el identificador de llamadas para una llamada es First/Last
, entonces {caller_name}
se expande a First_Last
.
Tenga en cuenta que debido al bajo rendimiento de Android Storage Access Framework, el uso de subdirectorios puede ralentizar significativamente el almacenamiento de la grabación en algunos dispositivos. En compilaciones de Android con una buena implementación de SAF, esto puede durar solo unos segundos. En la versión OEM de Android con la peor implementación SAF conocida, esto podría tardar varios minutos. El retraso es proporcional a la cantidad de archivos en el directorio de salida.
Si la opción Write metadata file
está habilitada, BCR escribirá un archivo JSON en el directorio de salida que contiene todos los detalles que BCR conoce sobre la llamada, así como información sobre el audio grabado. El archivo tiene el mismo nombre que el archivo de audio, excepto que tiene la extensión .json
.
La estructura JSON se muestra en el siguiente ejemplo. Tenga en cuenta que solo se garantiza la existencia de timestamp_unix_ms
, timestamp
y output.format.*
. Si no se puede determinar el valor de un campo (por ejemplo, cuando se produce un error o se deniega un permiso requerido), se establece en 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
}
}
}
Esta sección describe las funciones avanzadas ocultas de BCR.
BCR tiene un modo de depuración oculto que se puede habilitar o deshabilitar presionando prolongadamente el número de versión.
Cuando el modo de depuración está habilitado, BCR escribirá un archivo de registro en el directorio de salida después de que se complete la grabación de una llamada. Tiene el mismo nombre que el archivo de audio. El archivo de registro contiene los mismos mensajes que mostraría adb logcat
, excepto que los mensajes que no son relevantes para BCR se filtran (BCR no tiene permiso para acceder a esos mensajes de todos modos).
Dentro del archivo de registro, BCR pretende no registrar nunca información confidencial. La información sobre la llamada actual, como el número de teléfono, se reemplaza con marcadores de posición, como <phone number>
. Sin embargo, otra información que no se puede redactar fácilmente de esta manera se truncará. Por ejemplo, cuando la función de retención de archivos limpia archivos antiguos, nombres de archivos como 20230101_010203.456+0000_out_1234567890_John_Doe.oga
se registran como 20<...>ga
.
Cuando informe errores, incluya el archivo de registro, ya que es extremadamente útil para identificar qué podría estar mal. (¡Pero verifique dos veces el archivo de registro para asegurarse de que no haya información confidencial!)
BCR depende en gran medida de los permisos de las aplicaciones del sistema para funcionar correctamente. Esto se debe principalmente a dos permisos:
CONTROL_INCALL_EXPERIENCE
Este permiso permite que el servicio de telefonía de Android se vincule con InCallService
de BCR sin que BCR sea una aplicación complementaria portátil, una interfaz de usuario para automóvil o el marcador predeterminado. Una vez vinculado, el servicio recibirá devoluciones de llamada para eventos de cambio de llamada (por ejemplo, llamada entrante en estado de timbre). Este método es mucho más confiable que usar el permiso READ_PHONE_STATE
y confiar en las transmisiones de android.intent.action.PHONE_STATE
.
Este método tiene un par de beneficios adicionales. Debido a la forma en que el servicio de telefonía se vincula con InCallService
de BCR, el servicio puede aparecer y salir del primer plano según sea necesario cuando hay una llamada en curso y acceder a la transmisión de audio sin afectar las limitaciones de acceso al micrófono en segundo plano de Android 12+. Tampoco requiere que el servicio se inicie manualmente desde un receptor de transmisión ACTION_BOOT_COMPLETED
y, por lo tanto, no se ve afectado por los retrasos de esa transmisión durante el inicio inicial.
CAPTURE_AUDIO_OUTPUT
Este permiso se utiliza para grabar desde la transmisión de audio VOICE_CALL
. No se puede acceder a esta transmisión, junto con algunas otras, como VOICE_DOWNLINK
y VOICE_UPLINK
, sin el permiso de este sistema.
Con estos dos permisos, BCR puede detectar de manera confiable llamadas telefónicas y grabar el flujo de audio de la llamada. El proceso de grabación extrae audio sin procesar PCM s16le y utiliza los codificadores integrados de Android para producir el archivo de salida comprimido.
Tanto el archivo zip como el APK que contiene están firmados digitalmente. NOTA : El mecanismo de firma de archivos zip cambió de GPG a SSH a partir de la versión 1.31. Para verificar las firmas de versiones anteriores, consulte README.md
de la versión 1.30.
Para verificar las firmas digitales de las descargas, sigue los pasos aquí.
Primero, extrae el apk del zip y luego ejecuta:
apksigner verify --print-certs system/priv-app/com.chiller3.bcr/app-release.apk
Luego, verifique que el resumen SHA-256 del certificado de firma APK sea:
d16f9b375df668c58ef4bb855eae959713d6d02e45f7f2c05ce2c27ae944f4f9
BCR se puede crear como la mayoría de las otras aplicaciones de Android usando Android Studio o la línea de comandos de Gradle.
Para construir el APK:
./gradlew assembleDebug
Para compilar el módulo zip de Magisk (que ejecuta automáticamente la tarea assembleDebug
si es necesario):
./gradlew zipDebug
El archivo de salida se escribe en app/build/distributions/debug/
. El APK se firmará con la clave de depuración generada automáticamente de forma predeterminada.
Para crear una versión de lanzamiento con una clave de firma específica, configure las siguientes variables de entorno:
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
y luego compila el zip de lanzamiento:
./gradlew zipRelease
¡Las solicitudes de corrección de errores y traducción son bienvenidas y muy apreciadas!
Si está interesado en implementar una nueva característica y le gustaría que se incluya en BCR, abra un problema para discutirlo primero. Mi intención es que BCR sea lo más simple y de bajo mantenimiento posible, por lo que no estoy muy inclinado a agregar ninguna característica nueva, pero podría estar convencido de lo contrario.
BCR tiene licencia GPLv3. Consulte LICENSE
para obtener el texto completo de la licencia.