Wandering Sovereign
Wandering Sovereign

Reputation: 99

java.io.FileNotFoundException: open failed: EACCES (Permission denied) while trying to record using JobIntentService

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

Answers (1)

Wandering Sovereign
Wandering Sovereign

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

Related Questions