4

I want to verify if the Audio source of voice_call is available:

MediaRecorder.AudioSource.VOICE_CALL

How to check if I can record phone calls programatically since some devices do not allow it?

thanks in advance.

Kobi

krasnoff
  • 847
  • 3
  • 17
  • 34
  • See this: https://stackoverflow.com/questions/22677749/how-to-check-if-android-microphone-is-available-for-use. From what I've just coded, I think you should use AudioRecord for normal audio sources, and MediaRecorder for non-normal sources, like `VOICE_CALL`. MR needs a file even to check the source, as opposite to AR, so should be secondary, as the user will need to give you permission to write a file just to check an audio source, which is weird. AR doesn't need this, but it won't let you use non-normal audio sources. Use MR if AR throws an exception or doesn't initialize, for example. – Edw590 Dec 28 '20 at 02:36
  • Actually, we can create a file in the Cache directory, which doesn't require any permissions. Though I think still checking for an exception on `start()` which I see happening but I don't see documented is not as good as checking if AudioRecord is recording or not with the specific method (which doesn't exist in MediaRecorder and we're forced to check for "non-existant"(?) exceptions). Anyone please correct me if something I said is wrong, like the "non-existant" exception, but I don't see it anywhere and it's still thrown. – Edw590 Dec 28 '20 at 02:59

3 Answers3

1

The way to check is to try and record and catch the exception. No one has figured out any other way to know in advance if the device will work or not. If you catch the exception, you can try starting the recording from MediaRecorder.AudioSource.MIC. If the phone's speaker is low, you'll find that only the handset owner will be recorded and the other party on the line won't, but that's the best you can do.

I haven't seen a list of phone models that have these features disabled. It certainly would be a handy list to have.

Erik Nedwidek
  • 6,134
  • 1
  • 25
  • 25
  • Where am I supposed to try/catch the exception? do I have to wrap `MediaRecorder.setAudioSource()`, `MediaRecorder.prepare()`, `MediaRecorder.start()`, or all of them? – ocramot Apr 24 '15 at 07:10
  • Had you resolved it. I am stuck in this some where could you help me please. – Rahul Vats Jun 10 '17 at 09:09
0

I think you can use MediaRecorder.AudioSource.MIC instead.

Bond
  • 501
  • 2
  • 6
  • 18
0

I did this process: I try to create a file in a try / catch block in the shape I want, at the start and stop recorder, all goes well, it worked with the selected audiosource.

public class sRecAudioMic extends Service {

DecimalFormat fCoordenadas = new DecimalFormat("##.00000000");
DecimalFormat fVelocidade = new DecimalFormat("##.0");
static String imei = "";

private static String FORMATO_AUDIO = ".aac";
static String AUDIO_RECORDER_FOLDER = "";
static String codigo_usuario = "";

int contSegundos = 0;

static MediaRecorder recorder;

Boolean cancelTask = false;

eChamada chamada;

Context context;

public sRecAudioMic() {
}



@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onCreate() {
    imei = Functions.getIMEI(sRecAudioMic.this);

    AUDIO_RECORDER_FOLDER = new _Path().getPathAudio();
}

@SuppressLint("InlinedApi")
@Override
public void onStart(Intent intent, int startId) {

    try
    {
        Bundle b = intent.getExtras();
        chamada = (eChamada) b.getSerializable("Chamada");

        //chamada = (eChamada) intent.getParcelableExtra("Chamada");
        String t = "";
        t = " ";
    }
    catch(Exception e)
    {
        String t = "";

        t = " ";
    }       

    String nomeArquivo = "";

    int cont = 0;

    Calendar lCDateTime = Calendar.getInstance();

    String t = String.valueOf(lCDateTime.getTimeInMillis());

    nomeArquivo = "recording_" + t + FORMATO_AUDIO;

    nomeArquivo = nomeArquivo.replace(" ", "_").replace(":", "_")
            .replace("-", "_");

    String caminhoArquivo = AUDIO_RECORDER_FOLDER + "/" + nomeArquivo;

    chamada.nomeArquivo = nomeArquivo;
    chamada.caminhoArquivo = caminhoArquivo;

    try {

        recorder = new MediaRecorder();

        try {

            MediaRecorder r = new MediaRecorder();
            r.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
            r.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            r.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            r.setOutputFile(caminhoArquivo);
            r.setAudioSamplingRate(96000);
            r.prepare();
            r.start();
            r.stop();
            r.reset();
            r.release();

            r = null;

            recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);

        } catch (Exception e) {

            MediaRecorder r = new MediaRecorder();
            r.setAudioSource(MediaRecorder.AudioSource.MIC);
            r.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            r.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            r.setOutputFile(caminhoArquivo);
            r.setAudioSamplingRate(96000);
            r.prepare();
            r.start();
            r.stop();
            r.reset();

            r = null;

            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        }

        recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        recorder.setAudioSamplingRate(96000);
        // recorder.setMaxDuration(30000);

        recorder.setOutputFile(caminhoArquivo);

        recorder.setOnErrorListener(errorListener);
        recorder.setOnInfoListener(infoListener);

        recorder.prepare();
        recorder.start();

    } catch (Exception e) {
        e.printStackTrace();

        new LOG().CriaLog("sRecAudioMic", "onStart()", e.getMessage(), "");

    } finally {

    }

}

@Override
public void onDestroy() {

    String time = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss")
            .format(new java.util.Date());

    if (null != recorder) {

        // para gravacao
        recorder.stop();
        recorder.reset();
        recorder.release();

        recorder = null;
    }

    chamada.timestampChamadaTerminada = time;

    ChamadasDataSource dsCham = new ChamadasDataSource(sRecAudioMic.this);

    dsCham.open();

    dsCham.insert(chamada);

    dsCham.close();

}

@SuppressLint("NewApi")
private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
    @Override
    public void onError(MediaRecorder mr, int what, int extra) {

    }
};

@SuppressLint("NewApi")
private MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
    @Override
    public void onInfo(MediaRecorder mr, int what, int extra) {

    }
};

}

Elton da Costa
  • 1,279
  • 16
  • 27
  • 1
    You shouldn't put this in portuguese ;-) (PT here haha). That should be in english, so that everyone can understand it. – Edw590 Dec 28 '20 at 00:33