'Android MediaRecorder won't record audio when in the background
I have been trying to get media recorder to work last couple of days. I want when a user accepts a call, it starts recording the call. Right now the recorder stops and starts correctly but theres no audio but the length is correct.
I just can get it to work when I put in for example on main activity or accessibility event directly. Or when I restart the app when a recording is ongoing.
I've tried a lot of things and no one worked. Any ideas? I've checked all permissions and are all OK, it records OK whenever its not being called from a broadcast receiver
public class CallBr extends BroadcastReceiver {
private static final String TAG = "CallBr";
Bundle bundle;
String state;
String inCall, outCall;
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive: ");
try {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
Intent newIntent = new Intent("com.test.audio_recorder.test");
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
}
if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.i(TAG, "EXTRA_STATE_OFFHOOK");
newIntent.putExtra("startRecording", "startRecording");
context.sendBroadcast(newIntent);
}
Log.i(TAG, state);
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
Log.i(TAG, "EXTRA_STATE_IDLE");
newIntent.putExtra("stopRecording", "stopRecording");
context.sendBroadcast(newIntent);
Log.i(TAG, "EXTRA_STATE_IDLE");
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
}
}
}
if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Acessebility Service:
public class TService extends AccessibilityService {
private static final String TAG = "TService";
MediaRecorder audioRecorder;
public boolean registered = false;
@Override
public void onDestroy() {
Log.i(TAG, "destroy");
stopRecording();
super.onDestroy();
}
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
Log.i(TAG, "onAccessibilityEvent classname: " + accessibilityEvent.getClassName());
try {
AccessibilityNodeInfo node = accessibilityEvent.getSource();
Log.i(TAG, "accessibilityEvent.getClassName: " + accessibilityEvent.getEventType() + " " + accessibilityEvent.getClassName() + " " + accessibilityEvent.getEventType());
AccessibilityNodeInfo currentNode = getRootInActiveWindow();
AccessibilityNodeInfo info = accessibilityEvent.getSource();
} catch (Exception e) {
e.getMessage();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getStringExtra("stop") == null) {
createNotification();
startRecording();
return START_NOT_STICKY;
}
if(intent.getStringExtra("stop") != null) {
stopRecording();
stopForeground(STOP_FOREGROUND_REMOVE);
return START_NOT_STICKY;
}
return START_NOT_STICKY;
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
AccessibilityEvent.TYPE_VIEW_FOCUSED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.notificationTimeout = 100;
this.setServiceInfo(info);
IntentFilter filter = new IntentFilter("com.test.audio_recorder.test");
registerReceiver(receiver, filter);
Log.i(TAG, "onServiceConnected: connected");
}
public void stopRecording() {
Log.i(TAG, "stopRecording");
if (audioRecorder != null) {
audioRecorder.stop();
audioRecorder.reset();
audioRecorder.release();
audioRecorder = null;
}
}
public void startRecording() {
if (audioRecorder == null) {
Log.i(TAG, "startRecord");
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
long time = currentTimeMillis();
String str = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/D" + calendar.get(Calendar.DAY_OF_MONTH) + "M" + calendar.get(Calendar.MONTH) + "T" + time + ".3gp";
MediaRecorder recorder = new MediaRecorder();
AudioManager asd = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
Log.i(TAG, "startRecording: " + asd.getMode());
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setOutputFile(str);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
recorder.prepare();
} catch (IOException e) {
Log.e(TAG, "prepare() failed");
}
recorder.start();
audioRecorder = recorder;
}
}
@Override
public void onCreate() {
super.onCreate();
}
private void createNotification() {
String CHANNEL_ID = "my_channel_01";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("dasd")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentText("asdas").build();
startForeground(1336, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
}
private MediaRecorder.OnErrorListener errorListener = (mr, what, extra) -> Log.i("TService",
"Error: " + what + ", " + extra);
@Override
public void onInterrupt() {
Log.i(TAG, "onInterrupt");
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
private static final String TAG = "BRoadcastreceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "test");
AccessibilityManager manager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
event.setClassName(getClass().getName());
event.setPackageName(context.getPackageName());
event.getText().add("asdasdasdasdasd");
manager.sendAccessibilityEvent(event);
if (intent.getStringExtra("startRecording") != null) {
Log.i(TAG, "onStartCommand");
Intent asd = new Intent(getApplicationContext(), TService.class);
asd.putExtra("start", "start");
startForegroundService(asd);
}
if (intent.getStringExtra("stopRecording") != null) {
Log.i(TAG, "onStopCommand");
Intent asd = new Intent(getApplicationContext(), TService.class);
asd.putExtra("stop", "stop");
startForegroundService(asd);
}
}
};
}
MainActivity:
requestPermissions(new String[]{
Manifest.permission.FOREGROUND_SERVICE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CALL_PHONE,
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.CAPTURE_AUDIO_OUTPUT,
Manifest.permission.RECEIVE_BOOT_COMPLETED,
}, 0);
Solution 1:[1]
Changing AudioSource to VOICE_RECOGNITION fixed it. Actually this only records the user microphone.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
