BCR هو تطبيق بسيط لتسجيل مكالمات Android للأجهزة ذات الجذور أو الأجهزة التي تقوم بتشغيل البرامج الثابتة المخصصة. بمجرد تمكينه، يظل بعيدًا عن الطريق ويسجل المكالمات الواردة والصادرة تلقائيًا في الخلفية.
كما يوحي الاسم، تعتزم BCR أن تكون أساسية قدر الإمكان. سيكون المشروع قد نجح في تحقيق هدفه إذا كانت التحديثات الوحيدة التي يحتاجها هي التوافق مع إصدارات Android الجديدة. وبالتالي، لن يتم تنفيذ العديد من الميزات المفيدة المحتملة أبدًا، مثل:
VOICE_CALL
(على سبيل المثال، استخدام الميكروفون + مكبر الصوت)قم بتنزيل أحدث إصدار من صفحة الإصدارات. للتحقق من التوقيع الرقمي، راجع قسم التحقق من التوقيعات الرقمية.
قم بتثبيت BCR كتطبيق نظام.
بالنسبة للأجهزة التي تم الوصول إلى جذرها باستخدام Magisk/KernelSU ، ما عليك سوى تثبيت الملف المضغوط كوحدة Magisk/KernelSU من داخل التطبيق المعني.
.apk
من الملف المضغوط وتثبيته يدويًا قبل إعادة التشغيل. يعد ذلك ضروريًا للتغلب على خطأ في البرنامج الثابت حيث لا يتم إنشاء دليل بيانات التطبيق، مما يتسبب في فتح BCR على شاشة فارغة.بالنسبة للبرامج الثابتة المخصصة غير الجذر ، قم بتفليش الملف المضغوط أثناء التمهيد في الاسترداد.
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/
المجلد الموجود في ملف مضغوط طالما أن الملفات تحتوي على 644
إذنًا وتسمية u:object_r:system_file:s0
SELinux.أعد التشغيل وافتح BCR.
إذا تم تثبيت مسجلات مكالمات أخرى، فتأكد من تعطيل وظيفة تسجيل المكالمات الهاتفية الخاصة بها. في معظم الأجهزة، لا يمكن تسجيل مكالمة هاتفية بواسطة تطبيقين في نفس الوقت. ومع ذلك، من الجيد أن يكون لديك BCR لتسجيل المكالمات الهاتفية وسجل تطبيق آخر، على سبيل المثال. مكالمات VOIP.
تمكين تسجيل المكالمات واختيار دليل الإخراج.
إذا لم يتم تحديد أي دليل إخراج أو إذا لم يعد من الممكن الوصول إلى دليل الإخراج، فسيتم حفظ التسجيلات في /sdcard/Android/data/com.chiller3.bcr/files
. لاحظ أنه على نظام التشغيل Android 12+، لا يمكن الوصول إلى /sdcard/Android/data/
إلا عبر USB أو DocumentsUI (مدير الملفات المدمج في AOSP).
عند تمكين تسجيل المكالمات في المرة الأولى، سيطالب BCR بالميكروفون والإشعارات (Android 13+) وسجل المكالمات وجهات الاتصال وأذونات الهاتف. مطلوب فقط أذونات الميكروفون والإشعارات لوظيفة تسجيل المكالمات الأساسية. إذا تم منح أذونات إضافية، فسيتم إضافة المزيد من المعلومات إلى اسم ملف الإخراج. على سبيل المثال، سيسمح إذن جهات الاتصال بإضافة اسم جهة الاتصال إلى اسم الملف.
راجع قسم الأذونات أدناه للحصول على مزيد من التفاصيل حول الأذونات.
لتثبيت التحديثات المستقبلية، هناك طريقتان:
.apk
من الملف المضغوط وتثبيته مباشرة. باستخدام هذه الطريقة، يوجد الإصدار القديم كتطبيق نظام ويوجد الإصدار الجديد كتحديث مثبت بواسطة المستخدم لتطبيق النظام. تعد هذه الطريقة أكثر ملاءمة إذا تم دمج 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+ فقط] للمكالمات الفردية، سواء 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 لإنتاج ملف الإخراج المضغوط.
يتم توقيع كل من الملف المضغوط وملف APK الموجود بداخله رقميًا. ملاحظة : تم تحويل آلية توقيع الملف المضغوط من GPG إلى SSH اعتبارًا من الإصدار 1.31. للتحقق من التوقيعات للإصدارات القديمة، راجع README.md
للإصدار 1.30.
للتحقق من التوقيعات الرقمية للتنزيلات، اتبع الخطوات هنا.
أولاً، قم باستخراج ملف APK من الملف المضغوط ثم قم بتشغيل:
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
لإنشاء وحدة 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
ثم قم ببناء ملف الإصدار المضغوط:
./gradlew zipRelease
نرحب بطلبات إصلاح الأخطاء وسحب الترجمة ونقدرها كثيرًا!
إذا كنت مهتمًا بتنفيذ ميزة جديدة وترغب في رؤيتها مدرجة في BCR، فيرجى فتح مشكلة لمناقشتها أولاً. أنوي أن يكون BCR بسيطًا ومنخفض الصيانة قدر الإمكان، لذلك لا أميل إلى إضافة أي ميزات جديدة، ولكن يمكن أن أقتنع بخلاف ذلك.
BCR مرخص بموجب GPLv3. يرجى الاطلاع على LICENSE
للحصول على نص الترخيص الكامل.