android - Reboot corrupts files written to external storage of Galaxy S4 with FileChannel.map() -


i have following problem:

our android app uses leveldb write files device's external storage. leveldb internally uses mmap write. our problem far occurs on samsung galaxy s4. files written , read storage without problem. after restart of device, file corrupted.

did experience similar?

i wrote small demo app check if mmap problem , in fact seems be. demo app displays image ships app , button below image.
if button pressed

  • the image written external storage using filechannel.map() (as equivalent mmap)
  • the image read external storage , displayed below button.

after button pushed once , image written external storage, app shows 2 copies of image. works after restarting app. after reboot of galaxy s4 however, file on external storage corrupted , first image shown.

note: problem doesn't occur when file gets written using fileoutputstream , occurs on galaxy s4.

it great if knows how circumvent problem using leveldb.
make easier reproduce problem, here code of demo app:

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 included in 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 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 read 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)) {             // can read , write media              try {                  // convert resource 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 png*/, bos);                 byte[] bitmapdata = bos.tobytearray();                 bos.close();                  file dir = getapplicationcontext().getexternalcachedir();                  // write bytes 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)) {             // can read , write media              try {                  // create drawable png file on external storage                 file dir = getapplicationcontext().getexternalcachedir();                 string pathname = dir.getpath() + "/test_image_s.png";                 drawable d = drawable.createfrompath(pathname);                  // display 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");         }     } } 

one of collegues found solution circumvent problem on s4. realized external storage on device emulated. internally, uses internal storage. can use internal storage directly.

fortunately - starting api level 11 - there sdk call find out whether or not storage emulated: isexternalstorageemulated()

i think it's clean solution not targeted single device only. whenever external storage emulated, use internal storage.

however still think there galaxy s4 specific problem emulated external storage if data written via mmap(2).


Comments