Android 无法将图像文件保存到 SD 卡

Android unable to save image file to SD card

我正在使用 OpenGL 在 Android phone 中绘制框架,我想将图像保存到存储器中,但出现错误:找不到目录,也没有这样的文件目录,我确实像这样在 Android 清单中放置了权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.etoff.appsopengl">
    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<application android:allowBackup="true" android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher" android:theme="@style/AppTheme">

    <activity
        android:name="com.etoff.appsopengl.MainActivity"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

这是我在class阶段的编码:

if(SC==true){
            int screenshotSize = screenWidth * screenHeight;
            ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
            bb.order(ByteOrder.nativeOrder());
            gl.glReadPixels(0, 0, screenWidth, screenHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
            int pixelsBuffer[] = new int[screenshotSize];
            bb.asIntBuffer().get(pixelsBuffer);
            bb = null;
            Bitmap bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.RGB_565);
            bitmap.setPixels(pixelsBuffer, screenshotSize-screenWidth, -screenWidth, 0, 0, screenWidth, screenHeight);
            pixelsBuffer = null;
            short sBuffer[] = new short[screenshotSize];
            ShortBuffer sb = ShortBuffer.wrap(sBuffer);
            bitmap.copyPixelsToBuffer(sb);
            for (int i = 0; i < screenshotSize; ++i) {
                short v = sBuffer[i];
                sBuffer[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11));
            }
            sb.rewind();
            bitmap.copyPixelsFromBuffer(sb);
            screen = bitmap;

            String file_path = Environment.getExternalStorageDirectory().toString() + "/OpenGL";
            File dir = new File(file_path);
            if(!dir.exists()){
                dir.mkdirs();
            }
            String format = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date());
            File file = new File(file_path, format + ".png");
            OutputStream fOut;
            try {
                fOut = new FileOutputStream(file);
                screen.compress(Bitmap.CompressFormat.PNG, 85, fOut);
                fOut.flush();
                fOut.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

            SC = false;
        }

这是我在控制台中得到的错误:

W/System.err﹕ java.io.FileNotFoundException: /storage/emulated/0/OpenGL/20151001152329.png: open failed: ENOENT (No such file or directory)
W/System.err﹕ at libcore.io.IoBridge.open(IoBridge.java:409)
W/System.err﹕ at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err﹕ at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
W/System.err﹕ at com.etoff.appsopengl.Stage$MyRenderer.onDrawFrame(Stage.java:167)
W/System.err﹕ at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1531)
W/System.err﹕ at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
W/System.err﹕ Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err﹕ at libcore.io.Posix.open(Native Method)
W/System.err﹕ at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err﹕ at libcore.io.IoBridge.open(IoBridge.java:393)
W/System.err﹕ ... 5 more

错误:

Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory) at libcore.io.Posix.open(Native Method)

基本上找不到你的图片文件,因为你给的文件路径有误。

使用Environment.getExternalStorageDirectory()获取SD卡路径

.getAbsolutePath()去掉就好了。 Environment.getExternalStoreDirectory() 将为您提供制造商设置其外部存储的路径。

尝试

String file_path = Environment.getExternalStorageDirectory().toString()+"/OpenGL"

而不是

String file_path = Environment.getExternalStorageDirectory()+ "/OpenGL";

编辑 1:

您需要添加此权限才能将文件写入内部存储。

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

我建议您将图像保存在内部存储而不是 SD 卡中,因为不同的制造商使用不同的 SD 卡名称,因此不同设备的 SD 卡路径不同。

编辑2:

试试这个代码

 String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/OpenGL";
 File dir = new File(file_path);
 if(!dir.exists()){
     dir.mkdirs();
 }
 String format = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date());
 File file = new File(file_path, format + ".png");

而不是

String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/OpenGL";
File dir = new File(file_path);
if(!dir.exists()){
    dir.mkdirs();
}
String format = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date());
File file = new File(dir, format + ".png");

编辑 3: 在清单文件中同时授予权限:

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

并尝试同时使用 dir.mkdir();dir.mkdirs(); 具有以上 2 个权限。

您可以使用此方法将图像位图保存到SD卡中

public static Uri saveBitmap(Bitmap bitmap) {

    File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        Log.e("GREC", e.getMessage(), e);
    } catch (IOException e) {
        Log.e("GREC", e.getMessage(), e);
    }
    Uri parse = Uri.parse(new File(Environment.getExternalStorageDirectory() + "/screenshot.png").toString());
    return parse;
}

注意-在清单中添加权限:

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

享受你的代码时间:)