11

外部 Sd カードの PersistableUriPermission を取得し、さらに使用するために保存しています。ここで、ユーザーがアプリケーションのファイルのリストからファイル パスを提供したときに、ドキュメントを編集して名前を変更したいと考えています。

だから私は編集するファイルのファイルパスを持っています。

私の質問は、そのファイルの Uri を TreeUri から編集ファイルとして取得する方法です。

4

1 に答える 1

22

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();
             }
             break;
     }
  }

ユーザーが、

を。SDカードを選択しました

b. ファイルがあるSDカードを選択しました(一部のデバイスには複数のSDカードがある場合があります)。


sd ルートからファイルまで、階層を介してファイルを見つけることにより、a と b の両方をチェックします。ファイルが見つかった場合、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 the user about how to get the correct sd-card
    // and invoke file chooser dialog again.  

    // If the user selects a wrong path instead of the sd-card itself,  
    // you should ask the user to select a correct path.  
    // I've developed a gallery app with this behavior implemented in it.  
    // https://play.google.com/store/apps/details?id=com.majidpooreftekhari.galleryfarsi
    // After you installed the app, try to delete one image from the  
    // sd-card and when the app requests the sd-card, select a wrong path  
    // to see how the app behaves.  

 } 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);
    }


 }

アプリでの間違った SD カード パス選択動作:

間違った SD カード パス選択の動作を確認するには、アプリをインストールし、SD カードにあるイメージを削除して、SD カード ディレクトリではなく間違ったパスを選択してみてください。
カレンダー ギャラリー: https://play.google.com/store/apps/details?id=com.majidpooreftekhari.galleryfarsi

ノート:

マニフェスト内の外部ストレージへのアクセス許可と、アプリ内の os>=Marshmallow へのアクセス許可を提供する必要があります。 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) では、このバージョンの Android では適用できないため、ユーザーに sd カードを選択するように求めないでくださいDocumentProvider。したがって、このアプローチでは sd カードにアクセスする機会がありません。DocumentProvider https://developer.android.com/reference/android/provider/DocumentsProvider.htmlの API レベルを見てください
。Android KitKat(4.4) で動作するものは見つかりませんでした。KitKat で役に立つものが見つかった場合は、私たちと共有してください。

KitKat より前のバージョンでは、SD カードへのアクセスは OS によってすでに提供されています。

于 2016-08-23T14:35:54.080 に答える