简体   繁体   中英

Lollipop and sd-card

I am trying to create a file on sd-card on lollipop device. I am aware of ACTION_OPEN_DOCUMENT_TREE, and how to get permission for root of sd card.

What I want to achieve is this:

  • in my own folder browser, user picks a folder (on sdcard) where he wants file to be created (for example "/storage/emulated/0/a/b/c/d")
  • first time this happens, I use ACTION_OPEN_DOCUMENT_TREE , and then in onActivityResult I use findFile to create file in correct location:
  • next time user picks a folder on sd-card, he does not need to use ACTION_OPEN_DOCUMENT_TREE

code:

public void test()
{
  Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
  startActivityForResult(intent, 1);
}


public void onActivityResult(int requestCode, int resultCode, Intent resultData) 
{
  if (resultCode == RESULT_OK) 
  {
    Uri treeUri = resultData.getData();

    final int takeFlags = resultData.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;
    getContentResolver().takePersistableUriPermission(treeUri, takeFlags);


    //assuming he picked "/storage/emulated/0/a/b/c/d"
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
    DocumentFile a = pickedDir.findFile("a");
    DocumentFile b = a.findFile("b");
    DocumentFile c = b.findFile("c");
    DocumentFile d = c.findFile("d");

    DocumentFile newFile = d.createFile("text/plain", "somefile.txt");
    OutputStream out;
    try
    {
      out = getContentResolver().openOutputStream(newFile.getUri());
      out.write("A long time ago...".getBytes());
      out.close();
    }
    catch (FileNotFoundException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (IOException e)
    {
      // TODO Auto-generated catch block
        e.printStackTrace();
    }
  }
}

The question is how do I know in onActivityResult that user actually picked root of sdcard? He could have picked /storage/emulated/0/a1/a2 , and if that folder has subfolders a/b/c/d , I would create file in wrong folder (because findFile("a");findFile("b"); etc.. would also succeed).

Also, next time user picks a folder (with my own folder picker), I get path , not Uri , how do I translate that path to Uri which can be used with DocumentFile ?

You still have read access to the removable external storage using File . So you can create a temporary file with a unique name in the directory of the Uri that came back from ACTION_OPEN_DOCUMENT_TREE , using DocumentFile . and Uri . Then check if it is where you think it should be using File and the path. The following code returns true if myPath matches treeUri .

String myPath = "/storage/sdcard1/Podcasts";
Uri treeUri = resultIntent.getData();
int i = 0;
File f;
String s;
while ((f = new File(myPath + (s = "/tmp" + i + ".mp3"))).exists()) ++i;
final DocumentFile d = treeDir.createFile("audio/mp3", s);
if (d == null) return false;
try {
OutputStream str = getContentResolver().openOutputStream(d.getUri());
    str.write(new byte[10]);
    str.close();
} catch (IOException e) {
    return false;
}
final boolean fExists = f.exists();
d.delete();
return fExists;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM