Call recorder is recording blank for the duration in Android 10 (Pixel 3A). It was working fine for all phones till Android 8 and in Android 9 most phones were recording only one side voice (however it was working fine in pixel 3A)
Is there any way to record calls in Android 10?
The below code doesn't seem to be working anymore.
int audioSource = MediaRecorder.AudioSource.VOICE_CALL;
mediaRecorder.setAudioSource(audioSource);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioEncodingBitRate(32);
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setOutputFile(MediaUri);
mediaRecorder.prepare();
mediaRecorder.start();
If SDK 28 or below is used call recording happens for the whole duration but without any voice. If SDK 29 is used call recording fails at the beginning saying check available audio from callback.
I hope its a bug in Google Android 10 and some patch will fix it.
It's possible using Accessibility Service.
Remote call recorder and BoldBeast both record perfectly both side voice in Android 10 (Pixel 3A) without having to root or being a system app. Both of them use Accessibility service.
Detailed info here in this link.
As per Google's new permission policy no other third party apps (Except system apps) can record calls from Android 9 Pie.
This change will not affect previous recordings or call recording in general.
I am using Realme2pro device having version android 10 it is working for me by using Accessibility try this code
To implement Accessibility go through this link
public class Accessibility extends AccessibilityService {
Service mService = null;
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d("MyAccessibilityService", "Shrinidhi: onAccessibilityEvent");
}
#Override
public void onInterrupt() {
}
#Override
protected void onServiceConnected() {
Log.d("MyAccessibilityService", "Shrinidhi: onServiceConnected");
}
#Override
public void onCreate() {
this.mService = this;
Log.d("MyAccessibilityService", "Shrinidhi: onCreate");
}
}
and add AudioSource to recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(file.getAbsolutePath());
Hope it work :)
Related
The code for handling media buttons from headsets that I use in my Text-to-Speech app works great under Android API 22 through 25 (in older versions of Android they are handled by other, now depreciated means). However under Android 8 "Oreo", both public beta and final release, it does not work. Here is the relevant code:
When the service starts, I create MediaSessionCompact object:
mSession = new MediaSessionCompat(getApplicationContext(), "my.package.name._player_session");
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mSession.setActive(true);
mSession.setCallback(myMediaSessionCallback);
PlaybackStateCompat state = new PlaybackStateCompat.Builder()
.setActions(ACTION_PLAY_PAUSE | ACTION_PLAY | ACTION_PAUSE |
ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS |
ACTION_FAST_FORWARD | ACTION_REWIND
)
.setState(PlaybackStateCompat.STATE_PAUSED, 0 /*PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN*/, 1f)
.build();
mSession.setPlaybackState(state);
There is of course session media callback defined:
private MediaSessionCompat.Callback myMediaSessionCallback = new MediaSessionCompat.Callback() {
#Override
public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
// The log output below never appears on "Oreo", nothing comes here.
Log.d(TAG, "callback onMediaButtonEvent() Compat");
MediaButtonIntentReceiver.handleIntent(mediaButtonIntent.getAction(), (KeyEvent) mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
return true;
}
#Override
public void onSkipToNext() {
//...
}
// etc. other overrides
};
I also experimented with PendingIntent, using MediaButtonReceiver.buildMediaButtonPendingIntent() and set mSession.setMediaButtonReceiver(pendingIntent) for all the actions I'm interested in, then in my service onStartCommand() I call MediaButtonReceiver.handleIntent(mSession, intent):
// still in the same service:
mSession.setMediaButtonReceiver(
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
mMediaButtonReceiverComponentName,
ACTION_PLAY));
mSession.setMediaButtonReceiver(
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
mMediaButtonReceiverComponentName,
ACTION_PAUSE));
mSession.setMediaButtonReceiver(
MediaButtonReceiver.buildMediaButtonPendingIntent(
this,
mMediaButtonReceiverComponentName,
ACTION_PLAY_PAUSE));
and in the service onStartCommand():
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// ...
if (intent != null) {
MediaButtonReceiver.handleIntent(mSession, intent);
// ...
}
return START_NOT_STICKY;
}
Nothing, it's completely dumb to media buttons press events. What's wrong with "O" or my code there??? I'm completely baffled.
Update 8/32/2017
I also created a trivial but working app project that demonstrates the problem, please see: https://github.com/gregko/PlayerServiceSample. This project displays LogCat output when a media button is pressed on a headset under Android 5.x to 7.x, but fails completely under Android 8 "Oreo".
Update 9/1/2017
There is now an open issue on Android Issue Tracker about this, which I submitted, at https://issuetracker.google.com/issues/65175978. Still the media buttons work in several music player apps I tested on Oreo, I just can't figure out what do they do differently to make them work... The context of my app is not playing music, but reading aloud text with Text to Speech service, so a lot of code from Music Player examples does not apply.
Solved. On "Android 8.0 Behavior Changes" Google page we find this text:
In Android 8.0 (API level 26) the handling of media button events is different:
The handling of media buttons in a UI activity has not changed: foreground activities still get priority in handling media button events.
If the foreground activity does not handle the media button event, the system routes the event to the app that most recently played audio locally. The active status, flags, and playback state of a media session are not considered when determining which app receives media button events.
If the app's media session has been released, the system sends the media button event to the app's MediaButtonReceiver if it has one.
For every other case, the system discards the media button event.
All I had to do to make my trivial sample work was to play some sound with MediaPlayer. Apparently playing sound with Text-to-Speech API does not qualify, which in my opinion is a bug.
Here is the code I added to my trivial sample to make it work, playing a very brief and silent WAV file from Raw resources directory:
final MediaPlayer mMediaPlayer;
mMediaPlayer = MediaPlayer.create(this, R.raw.silent_sound);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
mMediaPlayer.release();
}
});
mMediaPlayer.start();
Update
Submitted the bug report to Android issue tracker at https://issuetracker.google.com/issues/65344811
Update 2, Oct. 10, 2017
Google now says that Oreo behavior in this respect is "by design" and won't fix it. Read the reply near the end of the issue tracker post above. I must say I'm disappointed.
In my application there is a feature to record voice calls and it works perfectly well. But when tested on (Samsung s7, s8 ) it doesn’t work well. The application is able to record only callers voice not the voice from the other end. Below is my code to check please suggest a solution
MediaRecd = new MediaRecorder();
MediaRecd.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL
);
MediaRecd.setAudioChannels(ConstantVariables.audioChannels);//monoRecording
MediaRecd.setAudioEncodingBitRate(64);
MediaRecd.setAudioSamplingRate(44100);
MediaRecd.setOutputFormat(output_formats[pos]);//.mp3
MediaRecd.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//I already try with all possible CAMCORDER , MIC , Default etc etc but none was working
MediaRecd.setOutputFile(Currentfilename);
try {
MediaRecd.prepare();
MediaRecd.start();
} catch (Exception e) {
MediaRecd.reset();
MediaRecd.release();
MediaRecd = null;
}
Please help
AudioSource.VOICE_CALL is not working in some android devices so
instead of VOICE_CALL use below
First try MediaRecorder.AudioSource.CAMCORDER
MediaRecd = new MediaRecorder();
MediaRecd.setAudioSource(MediaRecorder.AudioSource.CAMCORDER
);
If above is not working than use MediaRecorder.AudioSource.MIC
MediaRecd = new MediaRecorder();
MediaRecd.setAudioSource(MediaRecorder.AudioSource.MIC
);
i am working on AudioManager which is a Android SystemService.
with Android System 5.0+ , i encounter a problem which AudioManager the setMode method is not working .
i through a test ,
Android M, Lollipop.. 5.0+ version , AudioManager setMode is not working .
example :
public void initAudioImageIcon(boolean initLoad) {
boolean isAudioHeaderMode = IMSharedPreferences.getBooleanExtra(this, IMSPConstant.SP_NAME_MESSAGE,
IMSPConstant.SP_KEY_AUDIO_HEADER_MODE);
if (isAudioHeaderMode) {
mAudioHanderMode.setVisibility(View.VISIBLE);
// audioManager.setMode(AudioManager.MODE_IN_CALL) , but android system 5.0+ no any change, getMode() == AudioManager.MODE_NORMAL
setAudioMode(AudioManager.MODE_IN_CALL);
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
if (!initLoad) {
showAudioModePrompt(this.getText(R.string.im_audio_in_call), 1000);
}
} else {
mAudioHanderMode.setVisibility(View.GONE);
setAudioMode(AudioManager.MODE_NORMAL);
if (!initLoad) {
showAudioModePrompt(this.getText(R.string.im_audio_in_speeker), 1000);
}
}
}
but Android 3.0+,4.0+ is ok ,only 5.0+ .
so ,i don`t know where happen mistakes.
With audio mode set to :
setMode(AudioManager.MODE_IN_COMMUNICATION);
setSpeakerphoneOn(false);
while my audio stream is set to STREAM_MUSIC I can easily route audio to earpiece. I have tested it myself in AOSP Lollipop code.
Here in the question you have never mentioned about your stream type. Do set your stream to STREAM_MUSIC or STREAM_VOICE_CALL and the code should work for you too.
In android Lollipop setAudioMode(AudioManager.MODE_IN_CALL) is restricted. It can be used only by system application with MODIFY_PHONE_STATE permission. However you can use MODE_IN_COMMUNICATION and MODE_NORMAL in normal applications.
VOICE_CALL, VOICE_DOWNLINK ,VOICE_UPLINK
not working on android 4.0 but working on android 2.3 (Actual Device),I have uploaded a dummy project to record all outgoing call so that you can see it for your self
http://www.mediafire.com/?img6dg5y9ri5c7rrtcajwc5ycgpo2nf
you just have to change audioSource = MediaRecorder.AudioSource.MIC; to audioSource = MediaRecorder.AudioSource.VOICE_CALL; on line 118 in TService.java
If you come across any error, tell me. Any suggestion related to it will be accepted.
After a lot of search I Found that Some Manufactures have closed the access to such function because call recording is not allowed in some countries. If anyone finds such question and get the solution some other way then post it over here it may be helpful to many because many people are have the same issue.
Try to use MediaRecorder.AudioSource.VOICE_RECOGNITION. I had the same problem - ASUS Transformer uses microphone near the back camera by default and audio is very silent in this case. VOICE_CALL doesn't work on this tablet and I have tried VOICE_RECOGNITION - in that case it uses front microphone and audio volume is OK.
OK, in my case this code (thank you eyal!) worked for Samsung Galaxy Note 6:
String manufacturer = Build.MANUFACTURER;
if (manufacturer.toLowerCase().contains("samsung")) {
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
} else {
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
}
you try to add this,it may be
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mMediaRecorder.start();
}
}, 1000);
The Google Voice Search comes with a significant delay from the moment you call it via startActivityForResult() until its dialog box is displayed, ready to take your speech.
This requires the user to always look at the screen, waiting for the dialog box to be displayed, before speaking.
So I was thinking of generating an audible signal instead of the dialog box by implementing RecognitionListener and sounding a DTMF tone in onReadyForSpeech() as in the following snippet:
#Override
public void onReadyForSpeech(Bundle params) {
Log.d(LCTAG, "Called when the endpointer is ready for the user to start speaking.");
mToneGenerator.startTone(ToneGenerator.TONE_DTMF_1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Log.e(LCTAG, "InterruptedException while in Thread.sleep(50).");
e.printStackTrace();
} // SystemClock.sleep(50);
mToneGenerator.stopTone();
}
The tone sounds beautifully but... it is also "heard" by the microphone, arriving to the voice recognition service and always generating a recognition error ERROR_NO_MATCH.
Is there a way to work around this?
Here is a random idea, and it may very well not work.
Can you try disabling the microphone (maybe via AudioManager.setMicrophoneMute) while the tone is played?
Here's my code that's working for me, put into the onReadyForSpeech() callback of the RecognitionListener.
private void playSpeechReadyTone(){
audioManager.setMicrophoneMute(true);
MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer arg0) {
audioManager.setMicrophoneMute(false);
}
});
mediaPlayer.start();
}
I'm afraid that there isn't an easy&clean way to do that. As srf appointed, you shouldn't rely on AudioManager.setMicrophoneMute(boolean), so, AFAIK, the possibles are:
Play an audio file before call SpeechRecognizer.startListening(intent):
final MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer player) {
player.release();
// Safety start Speech Recognizer
mSpeechRecognizer.startListening(getSpeechRecognizerIntent());
}
});
mediaPlayer.start();
However, this solution has a problem... If may receive an RecognitionListener.onError(int error) before RecognitionListener.onReadyForSpeech being called and, in that case, you are still playing a beep sound every time (this will happen, for example, if you are not connected to the Internet and Speech Recognition is configured to work online)!
Besides, you should manage the case of cancelling the speech recognition process during audio (doublebeep) play.
Play the audio in the onReadyForSpeech callback (read original question) but use RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS with an appropriate value. In my case, my beep sound is really short (1 second max) and I set RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS to 4/5 seconds.
Also note that, as Google doc says:
Note also that certain values may cause undesired or unexpected results - use judiciously! Additionally, depending on the recognizer implementation, these values may have no effect.