更新 3:私は別の開発者と提携しており、多額のお金でこれを行うことができる誰かを見つけたようです. 彼らは私たちにテスト apk を送ってくれましたが、うまくいくようです。先に進み、ソースを購入します。私たちが詐欺に遭わないことを願っています。分かり次第更新します
更新 2:まだ作業中です。より辛い日々を過ごした後、私は今、特別なことは何も起こっていないと思いますが、ネイティブ側でAudioFlinger (リンクを参照) を使用してAudioFlinger::setParametersを呼び出しているだけです。
私は今、audio_io_handle_t ioHandle、const String8& keyValuePairs で AudioFlinger::setParameters を呼び出す単純な JNI を作成する方法を探しています。
keyValuePairsが何であるかは知っていますが、 audio_io_handle_tについての手がかりはありません
更新:他のアプリが CAF で QCOM オーディオを使用している可能性があると思います。同じものについては、リンクのaudio_extn_utils_send_audio_calibration を参照してください
同じリンクのvoice_get_incall_rec_snd_device
C/++ の知識はありません。これらのメソッドをネイティブ側から呼び出せるかどうかを確認するにはどうすればよいですか? 他のアプリができるので、方法があるに違いありません。
私はこれに40日以上、少なくとも1日5〜6時間苦労しています. SOが許可しているかどうかはわかりませんが、正解にも寄付をさせていただきます。
VOICE_CALL オーディオ ソースを使用する通話録音アプリがあります。ASOP はそれを実装/義務付けていませんが、ほとんどのメーカーは VOICE_CALL を実装しており、VOICE_CALL オーディオ ソースを使用するアプリは多くのデバイスで正常に動作しました。それはAndroid 6までです。
Google は Android 6 でこの動作を変更しました。VOICE_CALL オーディオ ソースを開くには、システム アプリケーションにのみ付与される android.permission.CAPTURE_AUDIO_OUTPUT が必要になりました。
これにより、基本的に通話録音が停止します。または停止する必要があります。まあ、この制限を回避する方法を見つけた3人を除いて、私と200以上の他の通話録音アプリで機能します.
Android 6 を搭載したさまざまなスマートフォンでこれらのアプリを試してみたところ、記録方法に特定の特徴があることがわかりました。
それらはすべて Android AudioRecord クラスとオープン MIC オーディオ ソースを使用します。私も; しかし、私のアプリでは、相手ではなくMICからのみ音声を取得します。私が見つけたのは、記録を開始する直後または開始する前に、ある種のシステム コールを発行していることです。
録音に MIC を使用しているにもかかわらず、VOICE_CALL を正常に録音したアプリの 1 つから、次のログを見てください。アプリは、VOICE_CALL オーディオ ソースを MIC にミックス/ルーティング/ストリーミング/マージする方法を管理しているようです。
- 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)
最初の行でわかるように、MIC オーディオ ソース input_source=1;routing=-2147483644 で始まっています。
次に、2行目で何かを行い、通常の許可である android.permission.MODIFY_AUDIO_SETTINGS を付与し、私のアプリにも許可します。これは最も重要な部分であると思われ、3 つすべてが JNI を使用して、VOICE_CALL オーディオ ソースの MIC へのストリーミング/マージをトリガーし、標準の AudioRecorder API で録音するために行うことを行っているようです。
次の行では、MIC(1) オーディオ ソースを開いているにもかかわらず、オーディオ ハードウェアが VOICE_CALL (input_source=4) のミキシングを開始していることがわかります。
私は彼らが使用したと仮定しました
AudioManager.setParameters("key=value")
などの多くのバリエーションを試しました
AudioManager.setParameters("input_source=4;routing=-2147483584;format=1")
運がなければ。
次に、Android、NDK、オーディオルーティング、ヘッドセットを介したオーディオの強制を見つけ、現在の AudioRecord セッションに VOICE_CALL をミックス/ルーティング/ストリーム/マージする方法である可能性があると考え、(C の知識がないため) リフレーションを使用しようとしました以下のコードで(再び)運がなければ同じことを達成する。
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();
}
}
明らかに、録音を可能にする何かが欠けています。
私はこの情報を得るためにお金を払うことさえ申し出ましたが、すべて拒否されました。私が言ったのは十分に公平です。一度公開します/見つけたら!
彼らが何をしているのか、何か心当たりはありますか?