Reputation: 99
I'm trying to set up an android call recorder using a Broadcast Receiver and a JobIntentService. However, whenever I launch the JobIntentService, the Mediarecorder.prepare() method throws an error as follows:
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Music/filename.3gp: open failed: EACCES (Permission denied)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:496)
W/System.err: at java.io.RandomAccessFile.<init>(RandomAccessFile.java:289)
W/System.err: at java.io.RandomAccessFile.<init>(RandomAccessFile.java:152)
W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:1046)
W/System.err: at com.example.callrecorder.Job.recordCall(Job.java:77)
W/System.err: at com.example.callrecorder.Job.onHandleWork(Job.java:38)
W/System.err: at androidx.core.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:392)
W/System.err: at androidx.core.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:383)
W/System.err: at android.os.AsyncTask$3.call(AsyncTask.java:378)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err: at java.lang.Thread.run(Thread.java:919)
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
W/System.err: at libcore.io.Linux.open(Native Method)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
W/System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:482)
W/System.err: ... 12 more
I/Try: java.io.FileNotFoundException: /storage/emulated/0/Music/filename.3gp: open failed: EACCES (Permission denied)
E/MediaRecorder: start called in an invalid state: 4
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.callrecorder, PID: 10311
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.IllegalStateException
at android.media.MediaRecorder.start(Native Method)
at com.example.callrecorder.Job.recordCall(Job.java:82)
at com.example.callrecorder.Job.onHandleWork(Job.java:38)
at androidx.core.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:392)
at androidx.core.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:383)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
The code for my JobIntentService is as follows:
public class Job extends JobIntentService {
static final int JOB_ID = 1000;
String state;
MediaRecorder mediaRecorder;
static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, Job.class, JOB_ID, intent);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
Log.i("Job", "Triggered");
state = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
switch (state) {
case "OFFHOOK": {
recordCall();
}
break;
case "IDLE": {
stopRecording();
}
break;
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
private void stopRecording() {
Log.i("Stato", "Stopped");
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
}
private void recordCall() {
String recordPath = null;
String path = Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC).getAbsolutePath();
File dir = new File(path);
if(!dir.exists()) {
dir.mkdirs();
}
String myFile = "filename.3gp";
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(dir + "/" + myFile);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
Log.i("Try", String.valueOf(e));
}
mediaRecorder.start();
Log.i("Stato", "Started");
}
}
The intent for this service is passed from a Broadcast Receiver and it all runs fine is I try to check by removing the media recorder part. For some reason, it throws errors whenever I try to start the media recorder saying Permission Denied. I have given WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, RECORD_AUDIO, READ_PHONE_STATE, PROCESS_OUTGOING_CALLS permissions in the Android Manifest file. The jobservice and receiver have been registered as well.
Upvotes: 1
Views: 2233
Reputation: 99
From Android 10 onwards, you need legacy permission to access storage the old way or switch to using the new methods. Add this under applications in Manifest for legacy storage.
android:requestLegacyExternalStorage="true"
Recording calls feature has also been stopped from android 10 so you can no longer record calls on it without accessibility options.
Upvotes: 3