写入外部存储空间时,Android screenrecorder崩溃

时间:2016-09-24 00:23:24

标签: android

我正在使用此代码作为我的应用的基础:https://github.com/commonsguy/cw-omnibus/tree/master/MediaProjection/andcorder

现在我改变了输出文件的路径。我想将它保存在外部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 me.bleuzen.android.screenrecorder.RecorderService@1febce5 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) 

我的宣言:

<?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是设置show touches。

最有趣的一行应该是: 引起:java.io.FileNotFoundException:/storage/3E0D-1BF9/20160924_013750.mp4:打开失败:EACCES(权限被拒绝) ,其中/ storage / 3E0D-1BF9 /是我的外部SD卡。但为什么“Permission denied”?我添加了WRITE_EXTERNAL_STORAGE。有什么想法吗?

编辑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(内部)上创建文件,在/ storage / 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卡(这次是另一个要测试的)。 结果:

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

1 个答案:

答案 0 :(得分:2)

由于您在Android 6.0上运行应用程序,因此WRITE_EXTERNAL_STORAGE必须实施运行时权限。这就是崩溃的原因。

以下几个链接可帮助您开始实施运行时权限https://developer.android.com/training/permissions/index.html https://github.com/googlesamples/android-RuntimePermissions http://www.androidwarriors.com/2016/05/runtime-permissions-android-m-example.html

相关问题