Comportement attend
Lorsque je sélectionne le fichier qui est stocké dans "Télécharger", il devrait pouvoir récupérer son nom de fichier et son chemin
Comportement réel
Lorsque je sélectionne le fichier qui est stocké dans "Télécharger", il renvoie null.
étapes pour reproduire le problème
Voici le code que j'ai implémenté
public static String getPath(final Context context, final Uri uri) {
String id = DocumentsContract.getDocumentId(uri);
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
try {
final boolean isOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
String stringContentURI;
Uri contentUri;
if(isOreo){
stringContentURI = "content://downloads/my_downloads";
}else{
stringContentURI = "content://downloads/public_downloads";
}
contentUri = ContentUris.withAppendedId(
Uri.parse(stringContentURI), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
} catch (NumberFormatException e) {
return null;
}
}
}
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
Cependant, cela fonctionne lors de la sélection de fichiers dans d'autres dossiers dans Android
S'il vous plaît donnez votre avis. Merci tout le monde :)
Pour l'instant, la meilleure approche pour obtenir le chemin est:
Obtenir un fichier physique depuis l'URI en tant que InputStream, ContentResolver.openInputStream()
vous permet d'accéder au contenu d'un fichier sans connaître son vrai chemin
String id = DocumentsContract.getDocumentId(uri);
InputStream inputStream = getContentResolver().openInputStream(uri);
puis l'écrire en tant que fichier temporaire dans le stockage mis en cache
File file = new File(getCacheDir().getAbsolutePath()+"/"+id);
writeFile(inputStream, file);
String filePath = file.getAbsolutePath();
Voici la méthode pour écrire un fichier temporaire dans le stockage mis en cache
void writeFile(InputStream in, File file) {
OutputStream out = null;
try {
out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while((len=in.read(buf))>0){
out.write(buf,0,len);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if ( out != null ) {
out.close();
}
in.close();
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
Je ne sais pas si c'est la meilleure façon de le faire, mais le code fonctionne correctement: D
Voici une autre solution que j'ai trouvée à partir de ce Gist. FileUtils.Java
Voici comment l'utiliser.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri uri = data.getData();
File originalFile = new File(FileUtils.getRealPath(this,uri));
}
Voici ce que je viens de proposer (il est testé sur Android Pie & suppose une carte SD):
private String getParentDirectory(@NonNull Uri uri) {
String uriPath = uri.getPath();
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
if(uriPath != null) {filePath = new File(filePath.concat("/" + uriPath.split(":")[1])).getParent();}
return filePath;
}
private String getAbsolutePath(@NonNull Uri uri) {
String uriPath = uri.getPath();
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
if(uriPath != null) {filePath = filePath.concat("/" + uriPath.split(":")[1]);}
return filePath;
}