6

Я беру внешнюю Sd-карту PersistableUriPermission и сохраняю ее для дальнейшего использования. Теперь я хочу, чтобы когда пользователь предоставил мне путь к файлу, из списка файлов в моем приложении, я хочу отредактировать документ и переименовать его.Android SAF (Storage Access FrameWork): Получить конкретный файл Uri от TreeUri

У меня есть путь к файлу для редактирования.

Мой вопрос в том, как получить Uri этого файла из моего TreeUri, так как файл редактирования.

ответ

7

Доступ к файлам SD-карты по

диалог Используйте DOCUMENT_TREE, чтобы получить SD-карты Uri.

Сообщите пользователю о том, как выбрать sd-card в диалоговом окне. (С картинками или GIF-анимации)

// call for document tree dialog 
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE); 

На onActivityResult вы будете иметь выбранный каталог Uri. (SdCardUri)

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    switch (requestCode) { 
     case REQUEST_CODE_OPEN_DOCUMENT_TREE: 
      if (resultCode == Activity.RESULT_OK) { 
       sdCardUri = data.getData(); 
      } 
      beak; 
    } 
    } 

Теперь нужно проверить, если пользователь,

а. выбрал SD-карту

b. выбрал SD-карту, в которой находится наш файл (некоторые устройства могут иметь несколько SD-карт).


Мы проверяем как a, так и b путем поиска файла через иерархию, от sd root до нашего файла. Если файл найден, будут получены оба условия a и b.

//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`. 
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri); 

//Then we split file path into array of strings. 
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"} 
// There is a reason for having two similar names "MyFolder" in 
//my exmple file path to show you similarity in names in a path will not 
//distract our hiarchy search that is provided below. 
String[] parts = (file.getPath()).split("\\/"); 

// findFile method will search documentFile for the first file 
// with the expected `DisplayName` 

// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard) 
for (int i = 3; i < parts.length; i++) { 
    if (documentFile != null) { 
     documentFile = documentFile.findFile(parts[i]); 
    } 
    } 

if (documentFile == null) { 

    // File not found on tree search 
    // User selected a wrong directory as the sd-card 
    // Here must inform user about how to get the correct sd-card 
    // and invoke file chooser dialog again. 

} else { 

    // File found on sd-card and it is a correct sd-card directory 
    // save this path as a root for sd-card on your database(SQLite, XML, txt,...) 

    // Now do whatever you like to do with documentFile. 
    // Here I do deletion to provide an example. 


    if (documentFile.delete()) {// if delete file succeed 
     // Remove information related to your media from ContentResolver, 
     // which documentFile.delete() didn't do the trick for me. 
     // Must do it otherwise you will end up with showing an empty 
     // ImageView if you are getting your URLs from MediaStore. 
     // 
     Uri mediaContentUri = ContentUris.withAppendedId(
       MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
       longMediaId); 
     getContentResolver().delete(mediaContentUri , null, null); 
    } 


} 

Примечание:

Вы должны предоставить разрешение на доступ к внешней памяти в манифесте и зева> = Зефир внутри приложения. https://stackoverflow.com/a/32175771/2123400


Редактировать Sd-Карте Файлы

Для редактирования существующего изображения на вашей SD-карты вам не нужны какие-либо из вышеперечисленных шагов, если вы хотите, чтобы вызвать другое приложение, чтобы сделать это для вы.

Здесь мы вызываем все действия (из всех установленных приложений) с возможностью редактирования изображений. (Программисты отмечают свои приложения в манифесте своими возможностями для обеспечения доступности из других приложений (видов деятельности)).

на вашем мероприятии editButton Клик:

String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri); 
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_EDIT).setDataAndType(mediaContentUri, mimeType).putExtra(Intent.EXTRA_STREAM, mediaContentUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), "Edit"), REQUEST_CODE_SHARE_EDIT_SET_AS_INTENT); 

и это, как получить MIMETYPE:

public String getMimeTypeFromMediaContentUri(Uri uri) { 
    String mimeType; 
    if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { 
     ContentResolver cr = getContentResolver(); 
     mimeType = cr.getType(uri); 
    } else { 
     String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri 
       .toString()); 
     mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
       fileExtension.toLowerCase()); 
    } 
    return mimeType; 
} 

Примечание:

На Android KitKat (4.4) не спрашивайте пользователю выбрать sd-карту, поскольку в этой версии Android DocumentProvider не применимо, поэтому у нас нет шансов получить доступ к th e sd-card с таким подходом. Посмотрите на уровень API для DocumentProvider https://developer.android.com/reference/android/provider/DocumentsProvider.html
Я ничего не нашел, что работает на Android KitKat (4.4). Если вы нашли что-нибудь полезное с KitKat, пожалуйста, поделитесь с нами.

В версиях ниже доступ к SD-карте KitKat уже предоставляется ОС.

+0

Я не хочу удалять файл –

+0

Скопировать с внешнего на sd? Копировать из Sd в внешний? – Eftekhari

+0

Я думаю, что код, который вы предоставили, я удаляю всю директорию Sd Card. –

Смежные вопросы