2016-09-24 46 views
1

,當我使用此代碼作爲基礎我的應用程序:https://github.com/commonsguy/cw-omnibus/tree/master/MediaProjection/andcorder的Android 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)  

我的清單:

<?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。任何想法?

編輯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:我tryed這一點:

@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-617是我的外置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 
+0

請直接在這裏發佈相關的代碼幾個環節。包含RecordingSession.java的第98行。 –

+0

很好,你已經在你的Manifest中添加了'WRITE_EXTERNAL_STORAGE'。你是否實現了運行時權限?設備在哪個操作系統版本上運行? –

+0

@SrikarReddy我的測試設備:LG G4(Android 6.0) 如果我實現了運行時權限?你的意思是在應用程序運行期間詢問用戶的權限?如果是,我不知道如何實現這一點呢。 – Bleuzen

回答

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

+0

因爲它太長的評論:http://pastebin.com/KZzUMM22 代碼中的RecorderService.NOTIFY_ID只是一個int。 – Bleuzen

+0

@Bleuzen如果評論太長,您應該編輯原始問題。 –

+0

@ Code-Apprentice編輯過的問題;) – Bleuzen