Android 无法使用LibGDX对外部存储器进行写入或读取

Android 无法使用LibGDX对外部存储器进行写入或读取,android,file,libgdx,Android,File,Libgdx,我的create方法如下所示: @Override public void create () { batch = new SpriteBatch(); FileHandle file = Gdx.files.external("file.txt"); file.writeString("My god, it's full of stars", false); } 我还包括: <uses-permission android:name="android.perm

我的
create
方法如下所示:

@Override
public void create () {
    batch = new SpriteBatch();

    FileHandle file = Gdx.files.external("file.txt");
    file.writeString("My god, it's full of stars", false);
}
我还包括:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

我得到的例外是:

02-13 14:45:51.858 12439-12466/com.snowdevs.tweetiebirds E/AndroidRuntime: FATAL EXCEPTION: GLThread 1120
Process: com.snowdevs.tweetiebirds, PID: 12439
com.badlogic.gdx.utils.GdxRuntimeException: Error writing file: file.txt (External)
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:353)
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
    at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22)
    at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519)
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
 Caused by: com.badlogic.gdx.utils.GdxRuntimeException: Error writing file: file.txt (External)
    at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:330)
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339) 
    at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22) 
    at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254) 
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519) 
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240) 
 Caused by: java.io.FileNotFoundException: /storage/emulated/0/file.txt: open failed: EACCES (Permission denied)
    at libcore.io.IoBridge.open(IoBridge.java:452)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
    at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322)
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350) 
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339) 
    at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22) 
    at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254) 
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519) 
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240) 
 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.FileOutputStream.<init>(FileOutputStream.java:87) 
    at com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322) 
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350) 
    at com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339) 
    at com.snowdevs.tweetiebirds.TweetieBirdsGame.create(TweetieBirdsGame.java:22) 
    at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254) 
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1519) 
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240) 
02-13 14:45:51.858 12439-12466/com.snowdevs.tweetiebirds E/AndroidRuntime:FATAL EXCEPTION:GLThread 1120
进程:com.snowdevs.tweetiebirds,PID:12439
com.badlogic.gdx.utils.GdxRuntimeException:写入文件时出错:file.txt(外部)
位于com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:353)
位于com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
在com.snowdevs.tweetiebirds.TweetieBirdsGame.create上(TweetieBirdsGame.java:22)
位于com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
位于android.opengl.GLSurfaceView$GLThread.guarderun(GLSurfaceView.java:1519)
位于android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
原因:com.badlogic.gdx.utils.GdxRuntimeException:写入文件时出错:file.txt(外部)
位于com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:330)
在com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
位于com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
在com.snowdevs.tweetiebirds.TweetieBirdsGame.create上(TweetieBirdsGame.java:22)
位于com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
位于android.opengl.GLSurfaceView$GLThread.guarderun(GLSurfaceView.java:1519)
位于android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
原因:java.io.FileNotFoundException:/storage/emulated/0/file.txt:open failed:EACCES(权限被拒绝)
在libcore.io.IoBridge.open中(IoBridge.java:452)
位于java.io.FileOutputStream。(FileOutputStream.java:87)
位于com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322)
在com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
位于com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
在com.snowdevs.tweetiebirds.TweetieBirdsGame.create上(TweetieBirdsGame.java:22)
位于com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
位于android.opengl.GLSurfaceView$GLThread.guarderun(GLSurfaceView.java:1519)
位于android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
原因:android.system.ErrnoException:打开失败:EACCES(权限被拒绝)
在libcore.io.Posix.open中(本机方法)
在libcore.io.BlockGuardOs.open上(BlockGuardOs.java:186)
在libcore.io.IoBridge.open中(IoBridge.java:438)
位于java.io.FileOutputStream。(FileOutputStream.java:87)
位于com.badlogic.gdx.files.FileHandle.writer(FileHandle.java:322)
在com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:350)
位于com.badlogic.gdx.files.FileHandle.writeString(FileHandle.java:339)
在com.snowdevs.tweetiebirds.TweetieBirdsGame.create上(TweetieBirdsGame.java:22)
位于com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:254)
位于android.opengl.GLSurfaceView$GLThread.guarderun(GLSurfaceView.java:1519)
位于android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
我使用Nexus5和安卓6棉花糖进行测试。
我搜索发现安卓6使用运行时权限,但是
LibGDX
开发者说它甚至可以在安卓6上运行。是否有修复程序(有或没有运行时权限)

我认为Nexus5没有外部存储(SD卡)

使用此项进行测试以找出原因-

boolean isExtAvailable = Gdx.files.isExternalStorageAvailable();
您可以找到更多信息。

我也遇到过同样的情况(安卓6、Nexus 4无SD卡、libGDX 1.9.3):
我用电脑检查了外部存储器

Gdx.files.isExternalStorageAvailable() // returns true
然后使用获取文件句柄

FileHandle file = Gdx.files.external("file.txt"); // no exception
然后打电话

file.writeString("text",false); // throws GdxRuntimeException
因此,我在android端检查了以下代码是否真的可以使用外部存储:

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); // returns true
这也是事实。所以这不是libGDX的问题,而是安卓系统的问题


然后我通过捕获异常来解决问题,在这种情况下,我将文件写入本地存储。

我通过检查用户是否已授予外部存储权限来解决问题,如果未授予权限,则使用以下方法请求权限:

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                     this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_REQUEST_CODE);
            }
所有这些都是特定于android的代码,因此驻留在
AndroidLauncher
类中