我有以下問題:重啓破壞()寫入銀河S4的外部存儲與FileChannel.map文件
我們的Android應用程序使用性LevelDB將文件寫入到設備的外部存儲。 LevelDB內部使用mmap
來編寫。到目前爲止,我們的問題只發生在三星Galaxy S4的上。文件可以毫無問題地寫入和讀取存儲。但是在設備重新啓動後,該文件已損壞。
有沒有人體驗過類似的東西?
我寫了一個小的演示應用程序來檢查mmap
是否是問題,實際上它似乎是。演示應用程序會顯示隨應用程序附帶的圖像和圖像下方的按鈕。
如果按鈕被按壓
- 該圖像是使用
FileChannel.map()
(等同於mmap
) - 圖像被從外部存儲器讀取,並且按鈕下方顯示寫入到外部存儲設備。
將按鈕按下一次並將圖像寫入外部存儲器後,該應用程序會顯示圖像的兩個副本。即使在重新啓動應用程序後,這也可以工作然而,Galaxy S4重新啓動後,外部存儲器上的文件已損壞,只顯示第一張圖像。
注意:當使用FileOutputStream
寫入文件並且僅在Galaxy S4上發生此問題時,不會發生此問題。
如果有人知道如何使用LevelDB來解決這個問題,那將會很棒。
爲了讓您更輕鬆地重現該問題,這裏是演示應用程序的一些代碼:
main.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>
StartActivity.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");
}
}
}