2017-02-08 17 views
3

の内部ストレージにないのsdcardに存在するファイルを選択してサーバーにアップロードしたいが、サイズを取得するためのパスを取得できません。ユーザは、SDカード(取り外し可能)から任意のファイルを選択しない限り、私はthis answerとその作業を使用していますファイルへのパスを取得するためのsdcardのファイルのURIから実際のパスを取得

intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); 
intent.addCategory(Intent.CATEGORY_OPENABLE); 
intent.setType("*/*"); 
String[] mimetypes = {"application/*"}; 
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes); 
startActivityForResult(
     Intent.createChooser(intent, "Select a File to Upload"), FILE_SELECT_CODE); 

:私は、コードの下に使用してファイルを選ぶための意図を開始しています。私はコードをデバッグし、タイプ主要でないことが判明した場合ので、この条件の内側に行くことはありません。

if("primary".equalsIgnoreCase(type)){ 
    return Environment.getExternalStorageDirectory() + "/" + split[1]; 
} 

だから私の質問はどうなるか、それは他の人のですか?タイプがプライマリでない場合はどうなりますか?その場合、どのようにファイルへのパスを得ることができますか?私は多くの質問とチュートリアルを探していますが、他には何もありません。私はまた、this answerの他の一部を試してみましたが、そのは「SECONDARY_STORAGE」と「EXTERNAL_STORAGE」のSDカードためSystem.getenv()リターンヌルので、動作していません。

if ("primary".equalsIgnoreCase(type)) { 
    return Environment.getExternalStorageDirectory() + "/" + split[1]; 
}else{ 
    return System.getenv("EXTERNAL_STORAGE") + "/" + split[1]; 
} 

ウリとドキュメントIDファイルの一見のためのように:

ウリ:私は、私がしようとすると、見つからない例外ファイル取得コンテンツ://com.android.externalstorage.documents/document/ 0EF9-3110%の3Adevice-2016-12-02-130553.png

DOCID:0EF9-3110:デバイス2016-12-02-130553.pngを

ヘルプがありますか?

+0

問題は何度も報告されています。毎週私が思う最後の月です。だからちょうどこのサイトを読んでください。さらに、ファイルパスが必要な理由を説明する必要があります。あなたはほとんどあなたが持っているコンテンツスキームで同じことをすることができます。 – greenapps

+0

@greenapps私はすでにそれを検索してリンクも投稿しています。あなたの質問に関連するリンクがあれば、それを共有してください –

+0

'私の質問はそれ以外は何ですか? '。あなたは 'タイプ'を意味しますか?さて、あなたは言うことができます! – greenapps

答えて

3

私は解決策を発見したAndroidデバイスマネージャー上で時間を過ごした後、ここにある:

filePath = "/storage/" + type + "/" + split[1]; 

EDIT:をする場合には

ドキュメントタイプIDがプライマリでない場合、私が使用してパスを作成DocumentUriの完全な機能であるここで、ファイルの種類

に基づいてcontentUriを選択:

public static String getRealPathFromURI_API19(Context context, Uri uri) { 
    String filePath = ""; 

    // ExternalStorageProvider 
    if (isExternalStorageDocument(uri)) { 
     final String docId = DocumentsContract.getDocumentId(uri); 
     final String[] split = docId.split(":"); 
     final String type = split[0]; 

     if ("primary".equalsIgnoreCase(type)) { 
      return Environment.getExternalStorageDirectory() + "/" + split[1]; 
     } else { 

      if (Build.VERSION.SDK_INT > 20) { 
        //getExternalMediaDirs() added in API 21 
        File extenal[] = context.getExternalMediaDirs(); 
        if (extenal.length > 1) { 
         filePath = extenal[1].getAbsolutePath(); 
         filePath = filePath.substring(0, filePath.indexOf("Android")) + split[1]; 
        } 
      }else{ 
        filePath = "/storage/" + type + "/" + split[1]; 
      } 
      return filePath; 
     } 

    } else if (isDownloadsDocument(uri)) { 
     // DownloadsProvider 
     final String id = DocumentsContract.getDocumentId(uri); 
     //final Uri contentUri = ContentUris.withAppendedId(
     // Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 

     Cursor cursor = null; 
     final String column = "_data"; 
     final String[] projection = {column}; 

     try { 
      cursor = context.getContentResolver().query(uri, projection, null, null, null); 
      if (cursor != null && cursor.moveToFirst()) { 
       final int index = cursor.getColumnIndexOrThrow(column); 
       String result = cursor.getString(index); 
       cursor.close(); 
       return result; 
      } 
     } finally { 
      if (cursor != null) 
       cursor.close(); 
     } 
    } else if (DocumentsContract.isDocumentUri(context, uri)) { 
     // MediaProvider 
     String wholeID = DocumentsContract.getDocumentId(uri); 

     // Split at colon, use second item in the array 
     String[] ids = wholeID.split(":"); 
     String id; 
     String type; 
     if (ids.length > 1) { 
      id = ids[1]; 
      type = ids[0]; 
     } else { 
      id = ids[0]; 
      type = ids[0]; 
     } 

     Uri contentUri = null; 
     if ("image".equals(type)) { 
      contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
     } else if ("video".equals(type)) { 
      contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 
     } else if ("audio".equals(type)) { 
      contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
     } 

     final String selection = "_id=?"; 
     final String[] selectionArgs = new String[]{id}; 
     final String column = "_data"; 
     final String[] projection = {column}; 
     Cursor cursor = context.getContentResolver().query(contentUri, 
      projection, selection, selectionArgs, null); 

     if (cursor != null) { 
      int columnIndex = cursor.getColumnIndex(column); 

      if (cursor.moveToFirst()) { 
       filePath = cursor.getString(columnIndex); 
      } 
      cursor.close(); 
     } 
     return filePath; 
    } else { 
     String[] proj = {MediaStore.Audio.Media.DATA}; 
     Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null); 
     if (cursor != null) { 
      int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA); 
      if (cursor.moveToFirst()) 
       filePath = cursor.getString(column_index); 
      cursor.close(); 
     } 


     return filePath; 
    } 
    return null; 
} 
+0

"isExternalStorageDocument"と "isDownloadsDocument"メソッドのためにどうすればよいですか? –

+1

ここでこれらの機能を見つけることができます。https://stackoverflow.com/questions/33295300/how-to-get-absolute-path-in-android-for-file/33298265#33298265 –

-1

FileProviderをアプリケーションに実装するのは簡単です。

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    ... 
    <application 
     ... 
     <provider 
      android:name="android.support.v4.content.FileProvider" 
      android:authorities="${applicationId}.provider" 
      android:exported="false" 
      android:grantUriPermissions="true"> 
      <meta-data 
       android:name="android.support.FILE_PROVIDER_PATHS" 
       android:resource="@xml/provider_paths"/> 
     </provider> 
    </application> 
</manifest> 

のAndroidManifest.xmlをそして解像度フォルダの下のxmlフォルダ内のprovider_paths.xmlファイルを作成します。まず、以下のようなタグの下のAndroidManifest.xmlでFileProviderタグを追加する必要があります。フォルダが存在しない場合は作成するためにフォルダが必要な場合があります。

のres/XML/provider_paths.xml完了

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <external-path name="external_files" path="."/> 
</paths> 

! FileProviderが宣言され、使用できるようになりました。

最後のステップは、MainActivity.java

Uri photoURI = Uri.fromFile(createImageFile()); 
to 



Uri photoURI = FileProvider.getUriForFile(MainActivity.this, 
      BuildConfig.APPLICATION_ID + ".provider", 
      createImageFile()); 

そして....行わにおいて以下のコードの行を変更することです!あなたのアプリケーションはAndroid Nougatを含むすべてのAndroidバージョンで完全に正常に動作するはずです。ええ!

+0

あなたはあなたの答えを詳しく説明できますか?なぜ私はこのFileProviderをAndroidManifestに追加する必要があるのですか? –

+1

この回答には注意しないでください。ここでナンセンスです。私は答えがファイルプロバイダをうまく使う方法を教えるために別の投稿に属していると思います。 – greenapps

+0

ヌーガットの私の悪い点 – g7pro

3

アップロードコードを変更してください。どこかであなたが

InputStream is = getContentResolver().openInputStream(uri); 

FileInputStream fis = new FileInputStream(path); 

の変更がありますので、直接URIを使用します。ファイルパスは必要ありません。

関連する問題