Я использую этот код в качестве базы для моего приложения: https://github.com/commonsguy/cw-omnibus/tree/master/MediaProjection/andcorderAndroid аварии screenrecorder при записи на внешнее устройство хранения
Теперь я изменил путь для выходного файла. Я хочу, чтобы сохранить его на внешней SD-карте, но если я начало записи, я получаю эту ошибку:
09-24 01:37:50.225 4428-4428/me.bleuzen.android.screenrecorder E/AndroidRuntime: FATAL EXCEPTION: main
Process: me.bleuzen.android.screenrecorder, PID: 4428
java.lang.RuntimeException: Unable to start service [email protected] with Intent { act=me.bleuzen.android.screenrecorder.RECORD flg=0x10000000 cmp=me.bleuzen.android.screenrecorder/.RecorderService bnds=[257,1321][832,1513] }: java.lang.RuntimeException: Exception preparing recorder
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3045)
at android.app.ActivityThread.access$2200(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1454)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by: java.lang.RuntimeException: Exception preparing recorder
at me.bleuzen.android.screenrecorder.RecordingSession.start(RecordingSession.java:98)
at me.bleuzen.android.screenrecorder.RecorderService.startRecorder(RecorderService.java:169)
at me.bleuzen.android.screenrecorder.RecorderService.onStartCommand(RecorderService.java:76)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3028)
at android.app.ActivityThread.access$2200(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1454)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by: java.io.FileNotFoundException: /storage/3E0D-1BF9/20160924_013750.mp4: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:117)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:149)
at android.media.MediaRecorder.prepare(MediaRecorder.java:780)
at me.bleuzen.android.screenrecorder.RecordingSession.start(RecordingSession.java:89)
at me.bleuzen.android.screenrecorder.RecorderService.startRecorder(RecorderService.java:169)
at me.bleuzen.android.screenrecorder.RecorderService.onStartCommand(RecorderService.java:76)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3028)
at android.app.ActivityThread.access$2200(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1454)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:117)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:149)
at android.media.MediaRecorder.prepare(MediaRecorder.java:780)
at me.bleuzen.android.screenrecorder.RecordingSession.start(RecordingSession.java:89)
at me.bleuzen.android.screenrecorder.RecorderService.startRecorder(RecorderService.java:169)
at me.bleuzen.android.screenrecorder.RecorderService.onStartCommand(RecorderService.java:76)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3028)
at android.app.ActivityThread.access$2200(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1454)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Моего Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.bleuzen.android.screenrecorder">
<application
android:icon="@drawable/ic_videocam_white_24dp"
android:label="@string/app_name">
<activity
android:name="me.bleuzen.android.screenrecorder.MainActivity"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="me.bleuzen.android.screenrecorder.RecorderService"
android:exported="true" />
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
Я уже поставил в разрешении WRITE_EXTERNAL_STORAGE , WRITE_SETTINGS - установить шоу.
Самая интересная линия должна быть: Вызванный: java.io.FileNotFoundException: /storage/3E0D-1BF9/20160924_013750.mp4: открыть не удалось: EACCES (Отказано в) , где/хранение/3E0D-1BF9/это моя внешняя SD-карта. Но почему «Разрешение лишено»? Я добавил WRITE_EXTERNAL_STORAGE. Есть идеи?
Edit 1: Я добавил это OnCreate в моих Главная/Настройки и только активность:
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_SETTINGS, Manifest.permission.RECORD_AUDIO}, RecorderService.NOTIFY_ID);
где RecorderService.NOTIFY_ID это просто INT
и проверили его с:
showToast(String.valueOf(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) + " " +
String.valueOf(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED) + " " +
String.valueOf(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED));
static void showToast(String msg) {
Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).show();
}
Выход был: «true false true»
WRITE_SETTINGS остается ложным :( ... но если я могу сохранить видео на внешнюю SD-карту, это нормально. Возможно, мы найдем исправление для этого тоже;)
Теперь разрешено WRITE_EXTERNAL_STORAGE, проблема СЛЕДУЕТ быть разрешена, но она по-прежнему не работает. Если я могу догадаться, почему: Чтобы запросить разрешение, метод нуждается в активности. Означает ли это, что каждое действие должно запрашивать разрешение? Проблема заключается в следующем: рекордер является сервисом. Я не могу запрашивать разрешение без активности.
Изменить 2: Пример: В AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="me.bleuzen.android.screenrecorder.MainActivity"
android:background="@android:color/background_light">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="@+id/textView"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
MainActivity:
package me.bleuzen.android.screenrecorder;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.TextView;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class MainActivity extends Activity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
boolean canWrite = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
textView.append("WRITE_EXTERNAL_STORAGE: " + canWrite + "\n");
if(canWrite) {
textView.append("Befor: " + new File("/storage/emulated/0/z.txt").exists() + " " + new File("/storage/6301-17FC/z.txt").exists() + "\n");
writeToFile("Unglaublich wichtig", "/storage/emulated/0/z.txt");
writeToFile("Unglaublich wichtig", "/storage/6301-17FC/z.txt");
textView.append("After: " + new File("/storage/emulated/0/z.txt").exists() + " " + new File("/storage/6301-17FC/z.txt").exists() + "\n");
} else {
textView.append("Please restart this app after granting permission.");
}
}
private static void writeToFile(String s, String f) {
File file = new File(f);
try {
file.createNewFile();
FileOutputStream outputStream = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
writer.append(s);
writer.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Результат данного примера кода: На/storage/emulated/0 (внутренний) файл создается, на/st orage/6301-17FC (моя внешняя SD-карта) нет.
Редактировать 3: я судимое это:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
try {
new File("/storage/6391-A617/test").createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
, где 6391-A617 мой внешний SD Card (на этот раз еще один, чтобы проверить). Результат:
09-27 15:39:16.624 4965-4965/me.bleuzen.android.screenrecorder W/System.err: java.io.IOException: open failed: EACCES (Permission denied)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at java.io.File.createNewFile(File.java:939)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at me.bleuzen.android.screenrecorder.MainActivity.onRequestPermissionsResult(MainActivity.java:226)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6588)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.Activity.dispatchActivityResult(Activity.java:6467)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.ActivityThread.deliverResults(ActivityThread.java:3738)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.ActivityThread.handleSendResult(ActivityThread.java:3785)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.ActivityThread.access$1400(ActivityThread.java:157)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.os.Looper.loop(Looper.java:148)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5525)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at java.lang.reflect.Method.invoke(Native Method)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
09-27 15:39:16.633 4965-4965/me.bleuzen.android.screenrecorder W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
09-27 15:39:16.634 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at libcore.io.Posix.open(Native Method)
09-27 15:39:16.634 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
09-27 15:39:16.634 4965-4965/me.bleuzen.android.screenrecorder W/System.err: at java.io.File.createNewFile(File.java:932)
09-27 15:39:16.634 4965-4965/me.bleuzen.android.screenrecorder W/System.err: ... 13 more
Пожалуйста отправьте соответствующий код здесь непосредственно. Включите строку 98 записи RecordingSession.java. –
Замечательно, что вы добавили 'WRITE_EXTERNAL_STORAGE' в ваш манифест. Вы внедрили Runtime Permission? В какой версии ОС работает устройство ?. –
@SrikarReddy Мое тестовое устройство: LG G4 (Android 6.0) Если я внедрил Runtime Permission? Вы хотите спросить у пользователя о разрешениях при запуске приложения? Если да, я не знаю, как это реализовать. – Bleuzen