Güncelleme 3: Başka bir geliştiriciyle ortaklık kurdum ve bunu büyük miktarda parayla yapabilecek birini bulduk. Bize bir test apk gönderdiler ve çalışıyor gibi görünüyor. Biz devam edip kaynağı satın alacağız. Umarım dolandırılmayız. Öğrendiğimde güncelleyeceğim
Güncelleme 2: Hala üzerinde çalışıyoruz. Daha sancılı günlerden sonra artık fantezi bir şey olmadığını düşünüyorum ama onlar sadece AudioFlinger :: setParameters'ı çağırmak için yerel tarafta AudioFlinger'ı ( bağlantıya bakın ) kullanıyorlar.
AudioFlinger :: setParameters'ı audio_io_handle_t ioHandle, const String8 & keyValuePairs ile çağırmak için nasıl basit bir JNI yazabileceğimi şimdi arıyorum.
KeyValuePairs'in ne olabileceğini biliyorum ama audio_io_handle_t hakkında bir ipucu değil
Güncelleme: Şimdi diğer uygulamaların CAF ile QCOM sesini kullanıyor olabileceğine inanıyorum. Aynı bağlantıda audio_extn_utils_send_audio_calibration'a bakın
ve voice_get_incall_rec_snd_device aynı bağlantıda
C / ++ bilgim yok. Bu yöntemleri yerel taraftan çağırıp çağıramayacağımı nasıl öğrenebilirim? Diğer uygulamalar yapabildiğinden, bir yolu olmalı.
40 günden fazla süredir bununla günde en az 5-6 saat uğraşıyorum. SO tarafından buna izin verilip verilmediğinden emin değilim, ancak doğru yanıt için bağış yapmaktan da mutluyum.
VOICE_CALL ses kaynağı kullanan bir çağrı kaydetme uygulamam var. ASOP bunu uygulamasa / zorunlu kılmasa da, çoğu üretici VOICE_CALL uygulamıştır ve VOICE_CALL ses kaynağı kullanan uygulamalar birçok cihazda iyi çalıştı. Bu Android 6'ya kadar.
Google bu davranışı Android 6 ile değiştirdi. VOICE_CALL ses kaynağının açılması artık android.permission.CAPTURE_AUDIO_OUTPUT gerektiriyor ve bu sadece sistem uygulamalarına veriliyor.
Bu, esasen arama kaydını durdurur, yoksa olmalıydı. Benimki ve bu sınırlamayı aşmanın bir yolunu bulan 3 dışında diğer 200'den fazla arama kayıt uygulaması için geçerli.
Bu uygulamaları Android 6 ile birçok farklı telefonda deniyor ve kaydetmeyi başardıkları şekilde belirli özellikleri buldum.
Hepsi Android AudioRecord sınıfını kullanır ve MIC ses kaynağını açar. Ben de yaptım; ancak uygulamamda, diğer taraftan değil, yalnızca MIC'den ses alıyorum. Öğrendiğim şey, kayda başlamadan hemen sonra veya hemen önce bir tür sistem çağrısı yaptıklarını söylüyor.
Kayıt için MIC kullanmasına rağmen VOICE_CALL'u başarıyla kaydeden uygulamalardan biri olan aşağıdaki günlük formuna bir göz atın. Görünüşe göre uygulama, VOICE_CALL ses kaynağını MIC'e karıştırmayı / yönlendirmeyi / aktarmayı / birleştirmeyi nasıl yönetiyor.
- D/audio_hw_primary: in_set_parameters: enter: kvpairs=input_source=1;routing=-2147483644
- D/PermissionCache: checking android.permission.MODIFY_AUDIO_SETTINGS for uid=10286 => granted (432 us)
- D/audio_hw_primary: in_set_parameters: enter: kvpairs=input_source=4;routing=-2147483584;format=1
- D/audio_hw_primary: select_devices: out_snd_device(0: ) in_snd_device(283: voice-dmic-ef)
- D/hardware_info: hw_info_append_hw_type : device_name = voice-dmic-ef
- D/voice: voice_get_incall_rec_snd_device: in_snd_device(283: voice-dmic-ef) incall_record_device(283: voice-dmic-ef)
İlk satırda görebileceğiniz gibi, MIC ses kaynağı input_source = 1 ile başlıyor; yönlendirme = -2147483644.
Ardından, ikinci satırda bir şey yapar ve normal izin olan android.permission.MODIFY_AUDIO_SETTINGS verilir ve uygulamam da buna sahiptir. Bu en önemli kısım gibi görünüyor ve görünüşe göre 3'ü de VOICE_CALL ses kaynağının MIC'ye akışını / birleştirilmesini tetiklemek ve standart AudioRecorder API ile kayıt yapmak için yaptıkları her şeyi yapmak için JNI kullanıyor.
Sonraki satırda, MIC (1) ses kaynağını açmış olsalar bile ses donanımının VOICE_CALL (input_source = 4) karıştırmaya başladığını görüyorsunuz.
Kullandıklarını varsaydım
AudioManager.setParameters("key=value")
ve birçok varyasyon denedi.
AudioManager.setParameters("input_source=4;routing=-2147483584;format=1")
şanssız.
Ardından, Android, NDK, Ses yönlendirme, kulaklıktan ses zorlama buldum ve VOICE_CALL'u mevcut AudioRecord oturumuna nasıl karıştırır / yönlendirir / yayınlar / birleştirir ve (C bilgisine sahip olmadığım için) reflasyonu kullanmayı denedim aynı şeyi aşağıdaki kodla (tekrar) şanssız başarmak.
private static void setForceUseOn() {
/*
setForceUse(int usage, int config);
----usage for setForceUse, must match AudioSystem::force_use
public static final int FOR_COMMUNICATION = 0;
public static final int FOR_MEDIA = 1;
public static final int FOR_RECORD = 2;
public static final int FOR_DOCK = 3;
public static final int FOR_SYSTEM = 4;
public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
----device categories config for setForceUse, must match AudioSystem::forced_config
public static final int FORCE_NONE = 0;
public static final int FORCE_SPEAKER = 1;
public static final int FORCE_HEADPHONES = 2;
public static final int FORCE_BT_SCO = 3;
public static final int FORCE_BT_A2DP = 4;
public static final int FORCE_WIRED_ACCESSORY = 5;
public static final int FORCE_BT_CAR_DOCK = 6;
public static final int FORCE_BT_DESK_DOCK = 7;
public static final int FORCE_ANALOG_DOCK = 8;
public static final int FORCE_DIGITAL_DOCK = 9;
public static final int FORCE_NO_BT_A2DP = 10;
public static final int FORCE_SYSTEM_ENFORCED = 11;
public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
public static final int FORCE_DEFAULT = FORCE_NONE;
*/
try {
Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
setForceUse.invoke(null, 0, 0); // setForceUse(FOR_RECORD, FORCE_NONE)
} catch (Exception e) {
e.printStackTrace();
}
}
Açıkçası, kaydetmeyi mümkün kılan bir şey eksik.
Bu bilgiyi almak için ödeme yapmayı bile teklif ettim, hepsi reddetti. Yeterince adil dedim. Bir kez yayınlayacağım / bulursam!
Ne yaptıkları konusunda bir fikriniz var mı?