#java #android #android-studio #android-service #mediarecorder
#java #Android #android-studio #android-service #mediarecorder
Вопрос:
Я пытаюсь настроить Android call recorder с использованием широковещательного приемника и JobIntentService. Однако всякий раз, когда я запускаю JobIntentService, метод Mediarecorder.prepare() выдает ошибку следующего содержания:
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)
Код для моего JobIntentService выглядит следующим образом:
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");
}
}
Намерение для этой службы передается с широковещательного приемника, и все работает нормально, я пытаюсь проверить, удалив часть media recorder. По какой-то причине он выдает ошибки всякий раз, когда я пытаюсь запустить медиарегистратор, сообщая, что в разрешении отказано.
Я предоставил разрешения на запись в WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, RECORD_AUDIO, READ_PHONE_STATE, PROCESS_OUTGOING_CALLS в файле манифеста Android.
Служба заданий и получатель также были зарегистрированы.
Комментарии:
1. Похоже, вы находитесь на Android Q.
2. Да, это устройство Android Q, на котором я тестирую.
3. Так вот почему это больше не работает.
Ответ №1:
Начиная с Android 10, вам требуется устаревшее разрешение для доступа к хранилищу старым способом или переключения на использование новых методов. Добавьте это в раздел приложения в манифесте для устаревшего хранилища.
android:requestLegacyExternalStorage="true"
Функция записи вызовов также была остановлена с Android 10, поэтому вы больше не можете записывать вызовы на нем без специальных возможностей.