我有以下问题:
我们的 Android 应用使用LevelDB将文件写入设备的外部存储。LevelDB内部使用mmap
写入。到目前为止,我们的问题只发生在三星 Galaxy S4上。文件被写入和读取存储没有任何问题。但重启设备后,文件已损坏。
有没有人经历过类似的事情?
我编写了一个小型演示应用程序来检查mmap
问题是否存在,实际上似乎是。演示应用程序显示应用程序附带的图像和图像下方的按钮。
如果按下按钮
FileChannel.map()
使用(相当于mmap
)将图像写入外部存储- 图像从外部存储中读取并显示在按钮下方。
按下按钮一次并将图像写入外部存储后,应用程序会显示图像的两个副本。即使在重新启动应用程序后也可以使用。然而,在 Galaxy S4 重新启动后,外部存储上的文件已损坏,仅显示第一张图像。
注意:此问题在使用写入文件时不会发生,FileOutputStream
并且仅在Galaxy S4上发生。
如果有人知道如何使用LevelDB来规避这个问题,那就太好了。
为了让您更容易重现问题,这里是演示应用程序的一些代码:
主要的.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:text="Original image as included in the app:" />
<ImageView
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_margin="10dp"
android:src="@drawable/test_image"
android:layout_gravity="center_horizontal" />
<Button
android:layout_width="300dp"
android:layout_height="44dp"
android:layout_gravity="center_horizontal"
android:text="Write image file to storage"
android:onClick="writeFile" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:text="Image as read from storage:" />
<ImageView
android:id="@+id/storageImage"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal" />
</LinearLayout>
开始活动.java
package net.skoobe.StorageWrite;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class StartActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
retrieveImage();
}
public void writeFile(View v) {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// we can read and write the media
try {
// convert resource to Bitmap
BitmapDrawable bm = ((BitmapDrawable)getResources().getDrawable(R.drawable.test_image));
Bitmap b = bm.getBitmap();
// store bitmap data in byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
bos.close();
File dir = getApplicationContext().getExternalCacheDir();
// write bytes to external storage
FileChannel readWriteChannel = new RandomAccessFile(dir.getPath() + "/test_image_s.png", "rw").getChannel();
ByteBuffer readWriteBuf = readWriteChannel.map(FileChannel.MapMode.READ_WRITE, 0, bitmapdata.length);
readWriteBuf.put(bitmapdata);
readWriteChannel.close();
} catch (Exception e) {
Log.e("StorageWrite", e.toString());
}
retrieveImage();
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.e("StorageWrite", "storage not writable");
} else {
Log.e("StorageWrite", "storage neither writable nor readable");
}
}
private void retrieveImage() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// we can read and write the media
try {
// create Drawable from PNG file on external storage
File dir = getApplicationContext().getExternalCacheDir();
String pathName = dir.getPath() + "/test_image_s.png";
Drawable d = Drawable.createFromPath(pathName);
// display the image
((ImageView)findViewById(R.id.storageImage)).setImageDrawable(d);
} catch (Exception e) {
Log.e("StorageWrite", e.toString());
}
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.e("StorageWrite", "storage not writable");
} else {
Log.e("StorageWrite", "storage neither writable nor readable");
}
}
}