Reputation: 73
so here is my problem, i need to get a file in phone and then upload it to my parse-server. I've made a file chooser for document, download, external, media folder but android file chooser also propose GoogleDrive option. So i got te Uri but i can't find a way to access that "local copy?".
Do i need to use GoogleDrive SDK to access it? Or can't android just be smart enough and give me methods to handle that Uri ?
I did success getting file name.
content://com.google.android.apps.docs.storage/document/
Here is my file chooser and handler:
public static void pick(final Controller controller) {
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooseFileIntent.setType("application/pdf");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(controller.getContext().getPackageManager()) != null) {
controller.startActivityForResult(chooseFileIntent, Configuration.Request.Code.Pdf.Pdf);
}
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private static boolean isGoogleDriveUri(Uri uri) {
return "com.google.android.apps.docs.storage".equals(uri.getAuthority());
}
private 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;
}
private static String getPath(Context context, Uri uri) {
if (DocumentsContract.isDocumentUri(context, uri)) {
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 (isGoogleDriveUri(uri)) {
// Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
// if (cursor != null) {
// int fileNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
// cursor.moveToFirst();
// Log.d("=== TAG ===", cursor.getString(fileNameIndex));
// Log.d("=== TAG ===", uri.getPath());
// cursor.close();
// }
} 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);
} 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 ("content".equalsIgnoreCase(uri.getScheme())) {
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static void upload(final Context context, final String name, final ParseObject dataSource, final String field, final Uri uri, final Handler handler) {
if (context != null && name != null && dataSource != null && field != null && uri != null) {
String path = getPath(context, uri);
if (path != null) {
final File file = new File(path);
dataSource.put(field, new ParseFile(file));
dataSource.getParseFile(field).saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if (e == null) {
if (handler != null) {
handler.success();
}
}
}
}, new ProgressCallback() {
@Override
public void done(Integer percentDone) {
if (handler != null) {
handler.progress(percentDone);
}
}
});
}
}
}
EDIT :
I've made some try but i got a problem when deleting the temporary file Here is my code:
public static void copyFile(final Context context, final Uri uri, final ParseObject dataSource, final String field, final String name, final Data.Source target, final Handler handler) {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
if (inputStream != null) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length;
while ((length = inputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, length);
}
dataSource.put(field, new ParseFile(name, byteArrayOutputStream.toByteArray()));
byteArrayOutputStream.close();
inputStream.close();
return true;
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@Override
protected void onPostExecute(final Boolean success) {
dataSource.getParseFile(field).saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if (e == null) {
if (handler != null) {
handler.success();
}
}
}
}, new ProgressCallback() {
@Override
public void done(Integer percentDone) {
if (handler != null) {
handler.progress(percentDone);
}
}
});
}
}.execute();
}
Final Edit:
Here my code is correct, temporary file are created and put in cache by Parse himself, so its out of my range. Hope he can help.
Upvotes: 3
Views: 1186
Reputation: 1007359
So i got te Uri but i can't find a way to access that "local copy?".
There is no "local copy", at least one that you can access.
Or can't android just be smart enough and give me methods to handle that Uri ?
Use ContentResolver
and openInputStream()
to get an InputStream
on the content identified by the Uri
. Either use that directly with your "parse-server", or use it to create a temporary "local copy" to a file that you control. Upload that local copy, deleting it when you are done.
Here is my file chooser and handler:
pick()
is fine. upload()
might be fine; I have not used Parse. The rest of that code is junk, copied from prior junk. It makes many unfounded, unreliable assumptions, and it will not work for Uri
values from arbitrary apps (e.g., served via FileProvider
).
Upvotes: 3