Search code examples
androidsd-cardandroid-sdcardnook

Accessing Storage on the Nook


The closest thing to documentation I can find having to do with file storage is this post (see below if you can't access it), but it leaves me with several questions.

I would really, really, really like a knowledgeable explanation of what paths map to what storage here, seeing as how we're supposed to hard-code them, and how precisely we're expected to access them. An actual code sample would be superlative. My best guess from messing around with this is that:

  • /sdcard-> maps to the internal eMMC slot, and access is restricted. Environment.getExternalStorageDirectory(); ... still returns this.
  • /media -> maps to the internal 8GB memory (I can write to this)
  • /data -> ?
  • ? -> maps to the optional microSD card

How can we access the external (optional, additional, the one you can pop out) sdcard, if /sdcard maps to restricted storage instead?

Now to quote the Nook developer docs:

Background There are two different partition schemes for the NOOK Color devices in market today, one with only 250MB available to applications on the /data partition and one with 4GB available to applications on the /data partition. As a result, it is imperative that applications are designed and developed in such a way as to manage space effectively. Applications which fail to do so will not be accepted for distribution via the Shop.

Area Associated Technical Recommendation or Solution if your application requires large amount of data (including but not limited to images, audio or video content), you should download those resources at runtime and store them in the larger partition of the device. If your application is going to request and store more than 100MB of data or resource you MUST abide by the the following restrictions:

Your application must clearly and explicitly state in the description provided that a large amount of data is used/delivered by the application. You MUST write your resources and data onto appropriate partition. You can detect if the device has an enlarged /data partition as follows :

StatFs stat = new StatFs("/data"); 
long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount(); 
long megAvailable = bytesAvailable / 1048576; 
if (megAvailable > 1000){   
... write your resources in /data
} else {  
... write your resources on /mnt/media ... 
} 

To write data into your application's private space on /data

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_WORLD_READABLE); 

Your application should NOT assume the presence of an sdcard on device, but you can test for one via a call to

Environment.getExternalStorageState(); If an SD Card is not found, your application MUST exit gracefully with a notification to the user as to the reason for the exit.

Remember, that to access the /media partition, as well as ExternalStorage you need to declare in your manifest:

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

Solution

  • First of all try the following methods:

    If neither of those return you a directory where you can write to, check the following google-groups thread, and use the code provided in the last answer, which enumerates all current mount-points:

    I have the same issue with Galaxy S. Until now all Android devices I
    got have "mount" command available. I build a list of available volume parsing "mount" response. This is not perfect but cleaver than Android storage API.

    String cmd = "/system/bin/mount"; 
    try { 
       Runtime rt = Runtime.getRuntime(); 
       Process ps = rt.exec(cmd); 
    
       BufferedReader rd = new BufferedReader( new InputStreamReader(ps.getInputStream()) ); 
       String rs; 
       while ((rs = rd.readLine()) != null) 
       { 
           //check what you need! 
           Log.i("MOUNT_CMD", rs); 
       } 
       rd.close(); 
       ps.waitFor(); 
    } catch(Exception e) { 
    //...
    }
    

    If it is possible to insert the microSD card in the Nook device, while it is running, you could also try the following:

    mVolumeManagerReceiver = new BroadcastReceiver() { 
      public void onReceive(Context context, Intent intent) { 
        Log.i("MediaMounter", "Storage: " + intent.getData()); 
      } 
    }; 
    
    IntentFilter filter = new IntentFilter(); 
    filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
    filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); 
    filter.addAction(Intent.ACTION_MEDIA_REMOVED); 
    filter.addDataScheme("file"); 
    context.registerReceiver(mVolumeManagerReceiver, filter);