BCR は、root 化されたデバイスまたはカスタム ファームウェアを実行しているデバイス用のシンプルな Android 通話録音アプリです。有効にすると、邪魔にならず、バックグラウンドで着信および発信通話を自動的に記録します。
名前が示すように、BCR は可能な限り基本的なものであることを目指しています。必要なアップデートが新しい Android バージョンとの互換性だけであれば、プロジェクトは目標を達成したことになります。したがって、次のような潜在的に役立つ機能の多くは実装されません。
VOICE_CALL
オーディオ ソースをサポートしていないデバイスの回避策 (例: マイク + スピーカーフォンの使用)リリース ページから最新バージョンをダウンロードします。デジタル署名を検証するには、「デジタル署名の検証」セクションを参照してください。
BCR をシステム アプリとしてインストールします。
Magisk/KernelSU でルート化されたデバイスの場合は、それぞれのアプリケーション内から zip を Magisk/KernelSU モジュールとしてフラッシュするだけです。
.apk
抽出し、手動でインストールします。これは、アプリ データ ディレクトリが作成されず、BCR が空白の画面で開くというファームウェアのバグを回避するために必要です。ルート化されていないカスタム ファームウェアの場合は、リカバリで起動するときに zip をフラッシュします。
READ_CALL_LOG
権限が厳しく制限されているため、Android の設定を介しても許可されません。この制限を削除するには、Android を再起動した後、adb 経由で実行します。 # 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
でフォーマットされている場合、ファイル システムは読み取り専用になるため、この方法は使用できません。644
アクセス許可とu:object_r:system_file:s0
SELinux ラベルが付いている限り、zip 内のsystem/
フォルダーからファイルを手動で抽出することもできます。再起動してBCRを開きます。
他の通話レコーダーがインストールされている場合は、必ずその通話録音機能を無効にしてください。ほとんどのデバイスでは、2 つのアプリで同時に通話を録音することはできません。ただし、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
ボタンをユーザーが明示的にタップした場合を除き、他のアプリと通信することもありません。そのシナリオでは、ターゲット アプリにはその 1 つの録画へのアクセスのみが許可されます。
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]
は、その番号が連絡先にある場合は連絡先名を挿入します。それ以外の場合は、連絡先名も発信者 ID も存在しない場合は、発信者 ID または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})
2 つの変数の間にテキスト(
があるため機能します。yyMMdd_HHmmss
HHmmss_yyMMdd
に変更された場合、古い記録のファイル名のタイムスタンプが正しく解析されず、削除される可能性があります。{direction}
: [Android 10+ のみ] 1 対 1 通話の場合、通話が着信かout
in
発信のいずれかになります。通話が電話会議の場合は、代わりにconference
が使用されます。{sim_slot}
: [Android 11 以降のみ]通話の SIM スロット番号 (1 から数えます)。これは、複数の SIM がアクティブで、BCR に電話のアクセス許可が付与されているマルチ SIM デバイスに対してのみ定義されます。{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 によって通信事業者から提供された発信者 ID。{contact_name}
電話番号に関連付けられた (最初の) 連絡先の名前。これは、BCR に連絡先権限が付与されている場合にのみ定義されます。{call_log_name}
: 通話ログに表示される名前。システム ダイヤラが逆引き参照を実行する場合、これには企業名などの詳細情報が含まれる場合があります。これは、BCR に通話ログの読み取り権限が付与されている場合にのみ定義されます。ファイル名テンプレートは、 /
文字を使用したサブディレクトリの指定をサポートしています。スラッシュは、 {date}
を含むファイル名テンプレート内のどこでも使用できます (例: {date:yyyy/MM/dd}
)。ただし、他の変数を展開した後に表示されるスラッシュはアンダースコアに置き換えられます。たとえば、通話の発信者 ID がFirst/Last
の場合、 {caller_name}
はFirst_Last
に展開されます。
Android Storage Access Framework のパフォーマンスが低いため、サブディレクトリを使用すると、一部のデバイスで録画の保存が大幅に遅くなる可能性があることに注意してください。適切な SAF 実装を備えた Android ビルドでは、これはわずか数秒である可能性があります。既知の最悪の SAF 実装を使用した OEM Android ビルドでは、これに数分かかる可能性があります。遅延は、出力ディレクトリ内のファイルの数に比例します。
Write metadata file
オプションが有効になっている場合、BCR は、BCR が認識している通話に関するすべての詳細と録音された音声に関する情報を含む JSON ファイルを出力ディレクトリに書き込みます。このファイルの名前は、拡張子が.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 は通話録音の完了後にログ ファイルを出力ディレクトリに書き込みます。音声ファイルと同じ名前が付けられます。ログ ファイルには、BCR に関連しないメッセージが除外されることを除いて、 adb logcat
表示するメッセージと同じメッセージが含まれます (BCR にはこれらのメッセージにアクセスする権限がありません)。
BCR は、ログ ファイル内に機密情報を一切記録しないことを目指しています。現在の通話に関する情報 (電話番号など) は、代わりに<phone number>
などのプレースホルダーに置き換えられます。ただし、他の情報はこの方法では簡単に編集できず、代わりに切り捨てられます。たとえば、ファイル保持機能が古いファイルをクリーンアップすると、 20230101_010203.456+0000_out_1234567890_John_Doe.oga
のようなファイル名は20<...>ga
として記録されます。
バグを報告する場合は、何が問題なのかを特定するのに非常に役立つため、ログ ファイルを含めてください。 (ただし、ログ ファイルを再確認して、機密情報が含まれていないことを確認してください。)
BCR が適切に機能するためには、システム アプリの権限に大きく依存します。これは主に次の 2 つの権限によるものです。
CONTROL_INCALL_EXPERIENCE
この権限により、BCR がウェアラブル コンパニオン アプリ、車の UI、またはデフォルトのダイヤラーにならずに、Android のテレフォニー サービスが BCR のInCallService
にバインドできるようになります。バインドされると、サービスは通話変更イベント (呼び出し中状態の着信など) のコールバックを受信します。この方法は、 READ_PHONE_STATE
権限を使用してandroid.intent.action.PHONE_STATE
ブロードキャストに依存するよりもはるかに信頼性が高くなります。
この方法にはさらにいくつかの利点があります。テレフォニー サービスが BCR のInCallService
にバインドされる方法により、サービスは、通話の進行中に必要に応じてフォアグラウンドに入ったりフォアグラウンドから抜け出したり、Android 12 以降のバックグラウンド マイク アクセス制限に達することなくオーディオ ストリームにアクセスしたりできます。また、 ACTION_BOOT_COMPLETED
ブロードキャスト レシーバーからサービスを手動で開始する必要がないため、初期起動時のブロードキャストの遅延の影響を受けません。
CAPTURE_AUDIO_OUTPUT
この権限は、 VOICE_CALL
オーディオ ストリームから録音するために使用されます。このストリームは、 VOICE_DOWNLINK
やVOICE_UPLINK
などの他のストリームと同様に、このシステム権限がなければアクセスできません。
これら 2 つの権限により、BCR は通話を確実に検出し、通話の音声ストリームから録音できます。録音プロセスでは、PCM s16le の生オーディオを取得し、Android の内蔵エンコーダーを使用して圧縮出力ファイルを生成します。
zip ファイルとそれに含まれる APK は両方ともデジタル署名されています。注: zip ファイルの署名メカニズムは、バージョン 1.31 から GPG から SSH に切り替わりました。古いバージョンの署名を確認するには、バージョン 1.30 のREADME.md
参照してください。
ダウンロードのデジタル署名を検証するには、ここの手順に従ってください。
まず、zip から apk を抽出し、次を実行します。
apksigner verify --print-certs system/priv-app/com.chiller3.bcr/app-release.apk
次に、APK 署名証明書の SHA-256 ダイジェストが次であることを確認します。
d16f9b375df668c58ef4bb855eae959713d6d02e45f7f2c05ce2c27ae944f4f9
BCR は、他のほとんどの Android アプリと同様に、Android Studio または Gradle コマンド ラインを使用して構築できます。
APK をビルドするには:
./gradlew assembleDebug
Magisk モジュール zip をビルドするには (必要に応じて、 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
を参照してください。