4

I'm trying to read files from a USB storage device connected to my Google Pixel. I'm currently using this method to select the path of the drive so I can query it for its contents

private static final String TAG = "MainActivity";
private static final int REQUEST_CHOOSE_DRIVE = 1;
private TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tv = (TextView) findViewById(R.id.text);

    Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);

    startActivityForResult(i, REQUEST_CHOOSE_DRIVE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CHOOSE_DRIVE) {

        Uri uri = data.getData();

    }
}

However, the Uri looks something like /tree/... which doesn't seem to be a real path in the Android file system (verified via adb shell). How can I use this uri to query the contents of a portable storage device? I tried using the answer given here but the linked function returns null.

Carpetfizz
  • 8,707
  • 22
  • 85
  • 146

1 Answers1

10

You are getting tree Uri. So you need to Add below code to get files from Tree Uri.

        DocumentFile documentFile = DocumentFile.fromTreeUri(this, uri);
        for (DocumentFile file : documentFile.listFiles()) {

            if(file.isDirectory()){ // if it is sub directory
                // Do stuff with sub directory
            }else{
                // Do stuff with normal file
            }

           Log.d("Uri->",file.getUri() + "\n");

        }

For the query the contents, you can use below code.

ContentResolver contentResolver = getActivity().getContentResolver();
    Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
            DocumentsContract.getTreeDocumentId(uri));
    Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
            DocumentsContract.getTreeDocumentId(uri));
Cursor docCursor = contentResolver.query(docUri, new String[]{
            Document.COLUMN_DISPLAY_NAME, Document.COLUMN_MIME_TYPE}, null, null, null);
    try {
        while (docCursor.moveToNext()) {
            Log.d(TAG, "found doc =" + docCursor.getString(0) + ", mime=" + docCursor
                    .getString(1));

        }
    } finally {
        // close cursor
    }

You can check Google sample code: https://github.com/googlesamples/android-DirectorySelection/blob/master/Application/src/main/java/com/example/android/directoryselection/DirectorySelectionFragment.java#L150

pRaNaY
  • 24,642
  • 24
  • 96
  • 146
  • Thanks, so I'm trying to do `Bitmap bitmap = BitmapFactory.decodeFile(filePath);` but I don't know what the file path is. I tried doing `file.getUri().getPath()` but it says no such file or directory – Carpetfizz May 25 '17 at 16:55
  • 1
    @Carpetfizz: Use `ContentResolver` and `openInputStream()` to get an `InputStream` on the content identified by the `Uri`. Then, use `decodeStream()` instead of `decodeFile()`. Also, `DocumentFile` makes it a bit simpler to traverse the document tree. – CommonsWare May 25 '17 at 16:58
  • Yes sir it is better way to do instead of decodefile(). @Carpetfizz: You can use `contentResolver.openInputStream(uri)` to get an `InputStream` of content. Make sure your Uri is valid source for Bitmap. – pRaNaY May 25 '17 at 17:22
  • Thanks again for both your answers, they do what I expected them to do! Is there a way to read the files in a queue? I want to be able to dequeue files one after the other instead of reading them into memory – Carpetfizz May 25 '17 at 17:27
  • okay I have `File` (on SD Card) how to get `DocumentFile` for this file so I could delete it? https://stackoverflow.com/questions/50550913/convert-file-to-documentfile – user25 May 27 '18 at 10:33