Obtenir le chemin réel à partir de L'URI du fichier dans sdcard marshmallow
je veux choisir le fichier qui existe dans sdcard pas dans le stockage interne et télécharger le serveur mais je ne suis pas en mesure d'obtenir son chemin pour obtenir sa taille. J'ai lancé une intention pour choisir un fichier en utilisant le code ci-dessous:
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);
pour obtenir le chemin de dossier j'utilise cette réponse et son fonctionnement à moins que l'utilisateur ne sélectionne n'importe quel dossier de sdcard(amovible). Quand je debug le code et ai trouvé que type est pas primaire de sorte qu'il ne va pas à l'intérieur de cette condition:
if("primary".equalsIgnoreCase(type)){
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
ma question est donc: qu'est-ce que ce sera d'autre? c'est à dire que si le type n'est pas première? comment obtenir le chemin à suivre dans cette affaire? j'ai cherché beaucoup de questions et tutoriel il n'y en a pas d'autre dans aucun d'eux. J'ai également essayé autre partie de cette réponse mais son ne fonctionne pas parce que System.getenv()
retour null pour " SECONDARY_STORAGE " et sdcard pour " EXTERNAL_STORAGE ". J'obtiens un fichier non trouvé exception lorsque j'essaie:
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}else{
return System.getenv("EXTERNAL_STORAGE") + "/" + split[1];
}
Uri et doc Id de fichier ressembler à:
Uri : content: / / com.Android.externalstorage.documents / document / 0EF9-3110%3Adevice-2016-12-02-130553.png
docId : 0EF9-3110: dispositif-2016-12-02-130553.png
de l'aide ??
3 réponses
après avoir passé du temps sur Android Device Manager, j'ai trouvé la solution, voici:
si l'id de type doc n'est pas primaire alors je crée le chemin en utilisant:
filePath = "/storage/" + type + "/" + split[1];
modifier: dans le cas de DocumentUri sélectionner contentUri sur la base du type de fichier
Voici la fonction complète:
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;
}
changez votre code de téléchargement. Quelque part vous aurez
FileInputStream fis = new FileInputStream(path);
changer à
InputStream is = getContentResolver().openInputStream(uri);
utilisez donc l'uri directement. Pas besoin d'un chemin d'accès au fichier.
il est assez facile d'implémenter FileProvider sur votre application. Tout d'abord, vous devez ajouter une étiquette FileProvider dans AndroidManifest.xml sous la balise comme ci-dessous: AndroidManifest.xml
<?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>
et ensuite créer un provider_paths.fichier xml dans le dossier xml sous le dossier res. Dossier peut être nécessaire pour créer si elle n'existe pas.
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>
fait! FileProvider est maintenant déclaré et être prêt utiliser.
la dernière étape consiste à modifier la ligne de code ci-dessous dans MainActivity.java
Uri photoURI = Uri.fromFile(createImageFile());
to
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
createImageFile());
et.... fait ! Votre application doit maintenant fonctionner parfaitement sur N'importe quelle version Android y compris Nougat Android. Yah !