4

我能找到的与文件存储最接近的文档是这篇文章(如果您无法访问它,请参阅下文),但它给我留下了几个问题。

我真的,真的,真的很想知道什么路径映射到这里的存储,看看我们应该如何对它们进行硬编码,以及我们应该如何精确地访问它们。一个实际的代码示例将是最高级的。我最好的猜测是:

  • /sdcard-> 映射到内部 eMMC 插槽,访问受限。Environment.getExternalStorageDirectory(); ...仍然返回这个。
  • /media -> 映射到内部 8GB 内存(我可以写这个)
  • /数据->?
  • ? -> 映射到可选的 microSD 卡

如果/sdcard 映射到受限存储,我们如何访问外部(可选的,附加的,您可以弹出的)sdcard ?

现在引用 Nook 开发者文档:

背景 目前市场上的 NOOK Color 设备有两种不同的分区方案,一种只有 250MB 可用于 /data 分区上的应用程序,另一种是 4GB 可用于 /data 分区上的应用程序。因此,必须以有效管理空间的方式设计和开发应用程序。未能这样做的申请将不被接受通过商店分发。

区域相关技术建议或解决方案如果您的应用程序需要大量数据(包括但不限于图像、音频或视频内容),您应该在运行时下载这些资源并将它们存储在设备的较大分区中。如果您的应用程序要请求和存储超过 100MB 的数据或资源,您必须遵守以下限制:

您的应用程序必须在说明中清楚明确地说明应用程序使用/交付了大量数据。您必须将您的资源和数据写入适当的分区。您可以检测设备是否有扩大的 /data 分区,如下所示:

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 ... 
} 

将数据写入应用程序的 /data 上的私有空间

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

您的应用程序不应假定设备上存在 sdcard,但您可以通过调用

Environment.getExternalStorageState(); 如果未找到 SD 卡,您的应用程序必须正常退出,并通知用户退出原因。

请记住,要访问 /media 分区以及 ExternalStorage,您需要在清单中声明:

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

2 回答 2

4

好的,这就是我在过去几周中学到的东西。

如果要写入内部SD 卡,请使用Context.getFilesDir()。它将返回您的应用程序的私有目录。您不能在内部闪存(又名“/data”)上创建自己的目录。除了分配给您的应用程序的文件夹之外,您无权写入任何位置。假设有两个内部分区,“/data”和“/media”,但我无法进入“/media”来挽救我的生命。

如果可用,您可以使用外部闪存“/sdcard”。这是您可以从设备中弹出的卡。有两种方法可以解决这个问题:

  • 将内容存储在分配给您的应用程序的文件夹中(以便在卸载您的应用程序时将其删除)。您可以使用Context.getExternalFilesDir()找到该文件夹 ​​。
  • 将东西存储在任何地方,无论是在“/sdcard/foo/bar”下的某个硬编码路径中,还是在 Environment.getExternalStorageDirectory() / 中。

B&N 代表的这篇文章(我在我的问题中引用了)结果有点像红鲱鱼,“/sdcard”没有映射到 eMMC 插槽,我不知道“我们映射了 SD 卡”到我们内部的eMMC”的意思。

这篇 B&N 帖子说“/media”是内部的,但即使我拥有适当的清单权限,我也无法写入它......所以去想一想。

这是我的测试设备的屏幕截图,显示了可访问和不可访问的内容: 在此处输入图像描述

代码(注意 FileUtils 默认不包含在 sdk 中,它来自 org.apache.commons.io lib):

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView dataView = (TextView) findViewById(R.id.data);
    dataView.setText(testIt("/data"));

    TextView mediaView = (TextView) findViewById(R.id.media);
    mediaView.setText(testIt("/media"));

    TextView mntMediaView = (TextView) findViewById(R.id.mntMedia);
    mntMediaView.setText(testIt("/mnt/media"));

try {
        File fd = this.getFilesDir();
        if(fd != null) {
            TextView fdView = (TextView) findViewById(R.id.filesDir);
            fdView.setText("getFilesDir(): " + testIt(fd.toString()));
        }
} catch (Exception e) {
    e.printStackTrace();
}

try {
        File efd = this.getExternalFilesDir(null);
        if(efd != null) {
            TextView efdView = (TextView) findViewById(R.id.externalFilesDir);
            efdView.setText("getExternalFilesDir(): " + testIt(efd.toString()));
        }
} catch (Exception e) {
    e.printStackTrace();
}

try {
    File esd = Environment.getExternalStorageDirectory();
        if(esd != null) {
            TextView esdView = (TextView) findViewById(R.id.externalStorageDirectory);
            esdView.setText("getExternalStorageDirectory(): " + testIt(esd.toString()));
        }
} catch (Exception e) {
    e.printStackTrace();
}

try {
    File espd = Environment.getExternalStoragePublicDirectory(null);
        if(espd != null) {
            TextView espdView = (TextView) findViewById(R.id.externalStoragePublicDirectory);
            espdView.setText("getExternalStoragePublicDirectory(): " + testIt(espd.toString()));
        }
} catch (Exception e) {
    e.printStackTrace();
}
}

public String testIt(String dir){
    StatFs stat = new StatFs(dir);
        long bytesAvailable = (long) stat.getBlockSize() * (long) stat.getBlockCount();
        long megAvailable = bytesAvailable / FileUtils.ONE_MB;
        File dirFile = new File(dir + "/test/");
        dirFile.mkdir();

        return dir + "/test \n canRead() " + dirFile.canRead() + ", \n canWrite() " + dirFile.canWrite() + " with " + megAvailable + "MB available";
}
于 2011-10-22T22:39:30.530 回答
0

首先尝试以下方法:

如果这些都没有返回您可以写入的目录,请检查以下google-groups thread,并使用最后一个答案中提供的代码,它枚举了所有当前的挂载点:

我对 Galaxy S 也有同样的问题。到目前为止,我
得到的所有 Android 设备都有可用的“mount”命令。我建立了一个可用卷解析“挂载”响应的列表。这并不完美,但比 Android 存储 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) { 
//...
}

如果可以在 Nook 设备中插入 microSD 卡,则在运行时,您还可以尝试以下操作:

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);
于 2011-10-16T15:33:14.577 回答