J'utilise Android sélection de fichiers et sélection de fichiers à partir du stockage de l'application (images, vidéos, documents). J'ai une fonction "getPath". Je reçois un chemin depuis uri. Je n'ai aucun problème avec la galerie images ou télécharger des documents. Mais lorsque je sélectionne un fichier sur google drive, je ne peux pas obtenir le chemin d'accès. 3D12 "Pouvez-vous m'aider à ce sujet?
C'est aussi ma fonction "getPath".
public static String getPath(final Context context, final Uri uri) {
// check here to KitKat or new version
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// 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];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[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[] { split[1] };
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
else if(isGoogleDriveUri(uri)){
//Get google drive path here
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return nopath;
}
public static String iStreamToString(InputStream is1)
{
BufferedReader rd = new BufferedReader(new InputStreamReader(is1), 4096);
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String contentOfMyInputStream = sb.toString();
return contentOfMyInputStream;
}
Je n'ai aucun problème avec les images de la galerie ou les documents à télécharger
Vous le ferez sur de nombreux appareils.
Mais quand je sélectionne un fichier de Google Drive, je ne peux pas obtenir de chemin
Il n'y a pas de chemin. ACTION_GET_CONTENT
Ne permet pas à l'utilisateur de choisir un fichier. Il permet à l'utilisateur de choisir un élément de contenu. Ce contenu peut être un fichier local. Ce contenu pourrait également être:
Vous avez deux options principales. Si vous seulement voulez des fichiers , utilisez alors n troisième -party file chooser library pour remplacer tout le code de votre question.
Ou, si vous souhaitez toujours utiliser ACTION_GET_CONTENT
Ou ACTION_OPEN_DOCUMENT
, Vous pouvez prendre le Uri
que vous obtenez de data.getData()
dans onActivityResult()
et faites deux choses avec:
Tout d'abord, utilisez DocumentFile.fromSingleUri()
pour obtenir un objet DocumentFile
pointant vers cet Uri
. Vous pouvez appeler getName()
sur le DocumentFile
pour obtenir un "nom d'affichage" pour le contenu, qui devrait être quelque chose que l'utilisateur reconnaîtra.
Ensuite, utilisez un ContentResolver
et openInputStream()
pour obtenir le contenu lui-même, de la même manière que vous pourriez utiliser un FileInputStream
pour obtenir les octets d'un fichier.
J'étais également coincé avec le même problème et j'ai constaté que lorsque nous choisissons l'image de Google Drive, son uri est comme ci-dessous
com.google.Android.apps.docs.storage
et nous ne pouvons pas obtenir directement le chemin du fichier car il n'est pas dans notre appareil. Nous téléchargeons donc d'abord le fichier vers une certaine destination, puis nous pouvons utiliser ce chemin pour faire notre travail. Voici le code pour le même
FileOutputStream fos = null;
try {
fos = new FileOutputStream(getDestinationFilePath());
try (BufferedOutputStream out = new BufferedOutputStream(fos);
InputStream in = mContext.getContentResolver().openInputStream(uri))
{
byte[] buffer = new byte[8192];
int len = 0;
while ((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
out.flush();
} finally {
fos.getFD().sync();
}
} catch (Exception e) {
e.printStackTrace();
}
}
File file = new File(destinationFilePath);
if (Integer.parseInt(String.valueOf(file.length() / 1024)) > 1024) {
InputStream imageStream = null;
try {
imageStream = mContext.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
maintenant, votre fichier est enregistré sur le chemin de destination souhaité et vous pouvez l'utiliser.
Get file path from Google Drive we can easily access by Using File Provider by using following steps Code is working fine.
1) Add provider path in AndroidManifest file inside Applcation Tag.
<application
Android:allowBackup="true"
Android:icon="@mipmap/ic_launcher"
Android:label="@string/app_name"
Android:roundIcon="@mipmap/ic_launcher_round"
Android:supportsRtl="true"
Android:theme="@style/AppTheme">
<activity Android:name="com.satya.filemangerdemo.activity.MainActivity">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<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>
2) provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<cache-path
name="my_cache"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
3)FileUtils.Java
public class FileUtils {
private static Uri contentUri = null;
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
// check here to KitKat or new version
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
{
/ MediaProvider
if (isMediaDocument(uri)) {
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(uri, context);
}
}
}
4) isGoogleDriveUri method
private static boolean isGoogleDriveUri(Uri uri) {
return "com.google.Android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.Android.apps.docs.storage.legacy".equals(uri.getAuthority());
}
5)getDriveFilePath method
private static String getDriveFilePath(Uri uri, Context context) {
Uri returnUri = uri;
Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
String name = (returnCursor.getString(nameIndex));
String size = (Long.toString(returnCursor.getLong(sizeIndex)));
File file = new File(context.getCacheDir(), name);
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
int maxBufferSize = 1 * 1024 * 1024;
int bytesAvailable = inputStream.available();
//int bufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size", "Size " + file.length());
inputStream.close();
outputStream.close();
Log.e("File Path", "Path " + file.getPath());
Log.e("File Size", "Size " + file.length());
} catch (Exception e) {
Log.e("Exception", e.getMessage());
}
return file.getPath();
}