Android Gallery on Android 4.4 (KitKat) returns different URI for Intent.ACTION_GET_CONTENT

192,913

Solution 1

Try this:

if (Build.VERSION.SDK_INT <19){
    Intent intent = new Intent(); 
    intent.setType("image/jpeg");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.select_picture)),GALLERY_INTENT_CALLED);
} else {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/jpeg");
    startActivityForResult(intent, GALLERY_KITKAT_INTENT_CALLED);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != Activity.RESULT_OK) return;
    if (null == data) return;
    Uri originalUri = null;
    if (requestCode == GALLERY_INTENT_CALLED) {
        originalUri = data.getData();
    } else if (requestCode == GALLERY_KITKAT_INTENT_CALLED) {
        originalUri = data.getData();
        final int takeFlags = data.getFlags()
                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        // Check for the freshest data.
        getContentResolver().takePersistableUriPermission(originalUri, takeFlags);
    }

    loadSomeStreamAsynkTask(originalUri);

}

Probably need

@SuppressLint("NewApi")

for

takePersistableUriPermission

Solution 2

This requires no special permissions, and works with the Storage Access Framework, as well as the unofficial ContentProvider pattern (file path in _data field).

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @author paulburke
 */
public static String getPath(final Context context, final Uri uri) {

    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];
            }

            // TODO handle non-primary volumes
        }
        // 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);
        }
    }
    // 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 null;
}

/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @param selection (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 */
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;
}


/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}

See an up-to-date version of this method here.

Solution 3

Had the same problem, tried the solution above but though it worked generally, for some reason I was getting permission denial on Uri content provider for some images although I had the android.permission.MANAGE_DOCUMENTS permission added properly.

Anyway found other solution which is to force opening image gallery instead of KITKAT documents view with :

// KITKAT

i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, CHOOSE_IMAGE_REQUEST);

and then load the image:

Uri selectedImageURI = data.getData();
input = c.getContentResolver().openInputStream(selectedImageURI);
                BitmapFactory.decodeStream(input , null, opts);

EDIT

ACTION_OPEN_DOCUMENT might require you to persist permissions flags etc and generally often results in Security Exceptions...

Other solution is to use the ACTION_GET_CONTENT combined with c.getContentResolver().openInputStream(selectedImageURI) which will work both on pre-KK and KK. Kitkat will use new documents view then and this solution will work with all apps like Photos, Gallery, File Explorer, Dropbox, Google Drive etc...) but remember that when using this solution you have to create image in your onActivityResult() and store it on SD Card for example. Recreating this image from saved uri on next app launch would throw Security Exception on content resolver even when you add permission flags as described in Google API docs (that's what happened when I did some testing)

Additionally the Android Developer API Guidelines suggest:

ACTION_OPEN_DOCUMENT is not intended to be a replacement for ACTION_GET_CONTENT. The one you should use depends on the needs of your app:

Use ACTION_GET_CONTENT if you want your app to simply read/import data. With this approach, the app imports a copy of the data, such as an image file.

Use ACTION_OPEN_DOCUMENT if you want your app to have long term, persistent access to documents owned by a document provider. An example would be a photo-editing app that lets users edit images stored in a document provider.

Solution 4

Just as Commonsware mentioned, you shouldn't assume, that the stream you get via ContentResolver is convertable into file.

What you really should do is to open the InputStream from the ContentProvider, then create a Bitmap out of it. And it works on 4.4 and earlier versions as well, no need for reflection.

    //cxt -> current context

    InputStream input;
    Bitmap bmp;
    try {
        input = cxt.getContentResolver().openInputStream(fileUri);
        bmp = BitmapFactory.decodeStream(input);
    } catch (FileNotFoundException e1) {

    }

Of course if you handle big images, you should load them with appropriate inSampleSize: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. But that's another topic.

Solution 5

I believe the responses already posted should get people going in the right direction. However here is what I did that made sense for the legacy code I was updating. The legacy code was using the URI from the gallery to change and then save the images.

Prior to 4.4 (and google drive), the URIs would look like this: content://media/external/images/media/41

As stated in the question, they more often look like this: content://com.android.providers.media.documents/document/image:3951

Since I needed the ability to save images and not disturb the already existing code, I just copied the URI from the gallery into the data folder of the app. Then originated a new URI from the saved image file in the data folder.

Here's the idea:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent), CHOOSE_IMAGE_REQUEST);

public void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    File tempFile = new File(this.getFilesDir().getAbsolutePath(), "temp_image");

    //Copy URI contents into temporary file.
    try {
        tempFile.createNewFile();
        copyAndClose(this.getContentResolver().openInputStream(data.getData()),new FileOutputStream(tempFile));
    }
    catch (IOException e) {
        //Log Error
    }

    //Now fetch the new URI
    Uri newUri = Uri.fromFile(tempFile);

    /* Use new URI object just like you used to */
 }

Note - copyAndClose() just does file I/O to copy InputStream into a FileOutputStream. The code is not posted.

Share:
192,913

Related videos on Youtube

Michael Greifeneder
Author by

Michael Greifeneder

Updated on June 20, 2021

Comments

  • Michael Greifeneder
    Michael Greifeneder about 3 years

    Before KitKat (or before the new Gallery) the Intent.ACTION_GET_CONTENT returned a URI like this

    content://media/external/images/media/3951.

    Using the ContentResolver and quering for MediaStore.Images.Media.DATA returned the file URL.

    In KitKat however the Gallery returns a URI (via "Last") like this:

    content://com.android.providers.media.documents/document/image:3951

    How do I handle this?

    • CommonsWare
      CommonsWare over 10 years
      Off the cuff, I would find ways of using the content that does not require direct access to the file. For example, that Uri should be openable as a stream via ContentResolver. I have long been nervous about apps that assume that a content:// Uri that represents a file can always be converted into a File.
    • Michael Greifeneder
      Michael Greifeneder over 10 years
      I think a valid answer is to change to the ContentResolver and work with Uri instead of File-URLs. I will do that. It also enables better handling of non-Gallery Uris.
    • Snake
      Snake over 10 years
      @CommonsWare,If I want to save an image path in sqlite db so I can open it later, should I save the URI or absolute file path?
    • darrenp
      darrenp over 10 years
      @CommonsWare I agree with your nervousness. :-) However, I need to be able to pass a filename (for an image) to native code. A solution is to copy the data obtained using an InputStream on the ContentResolver to a pre-designated place so it has a known filename. However, this sounds wasteful to me. Any other suggestions?
    • CommonsWare
      CommonsWare over 10 years
      @darrenp: Ummm..., rewrite the native code to work with an InputStream over JNI? There aren't all that many options for you, unfortunately.
    • darrenp
      darrenp over 10 years
      That's useful to know. Thanks for your response. I've since found out that we are now passing the image to C++ in memory rather than via a file so it we can now use an InputStream instead of a file (which is great). Only EXIF tag reading is slightly tricky and requires Drew Noakes' library. Many thanks for your comments.
    • Spry Techies
      Spry Techies almost 10 years
      @Exception there is a bug reported in cordova over this issue so try finder answer it is working
    • Exception
      Exception almost 10 years
      @SpryTechies But that works only for images, what about other media types.
    • Spry Techies
      Spry Techies almost 10 years
      @Exception Which media you wants please specify
    • Exception
      Exception almost 10 years
      @SpryTechies I mean to say video file.
    • DeltaCap019
      DeltaCap019 about 9 years
    • surhidamatya
      surhidamatya over 8 years
      better answer is here stackoverflow.com/questions/20067508/… from Paul Burke
    • aslamhossin
      aslamhossin over 3 years
      MediaStore.Images.Media.DATA is depricated now and MediaStore.Images.Media._ID with contentWrapperUri always return relative uri not absolute Uri. That is the main problem for getting valid Uri and this Uri not return a valid file path and occurred FileNotFoundException.
  • Michael Greifeneder
    Michael Greifeneder over 10 years
    Would you mind to elaborate what the KitKat code is doing? Does this require any new permission? The pre KitKat code works for me on KitKat, too. So why would I choose to use a different code for KitKat? Thanks.
  • finder
    finder over 10 years
    My old code refused to work on KitKat. I had to read the manual. Well, that new permissions are not required.
  • user65721
    user65721 over 10 years
    it seems we can't get path from new sdks uri. Also it is a shame google made this kind of change without proper documantation and announcement.
  • Álvaro
    Álvaro over 10 years
    Could you explain how to get the file URL? I would like to obtain the real path in sdcard. For example, if it is a picture, I would like to obtain this path /storage/sdcard0/DCIM/Camera/IMG_20131118_153817_119.jpg instead of the document Uri.
  • fattire
    fattire over 10 years
    To reply to myself with an even crazier thought-- if your app is already handling file:// intents from an external file picker, you could also check the authority, as in the example above to make sure it's from your custom provider, and if so you could also use the path to "forge" a new file:// intent using the path you extracted, then StartActivity() and let your app pick it up. I know, terrible.
  • Colin M.
    Colin M. over 10 years
    Based on KitKat docs (developer.android.com/about/versions/…) this may not be what the OP needs unless he does intent to use/edit documents that are owned by the other application(s). If the OP wants a copy or to do things in a way consistent with older versions, the answer by @voytez would be more appropriate.
  • Colin M.
    Colin M. over 10 years
    This answer contained the right information for my purposes. Conditionally using the ACTION_PICK and EXTERNAL_CONTENT_URI on KitKat provided the same ability to get meta-data about Images in the gallery via ContentResolver like is possible on older versions using simply ACTION_GET_CONTENT.
  • Dan2552
    Dan2552 over 10 years
    This isn't working for me with a Nexus 4 running Kitkat but it is with a Galaxy S3 running 4.1.2
  • Josh
    Josh over 10 years
    This worked fantastically on a 4.4 Nexus 5 Documents UI and some other pref KitKat devices using the standard gallery apps, thanks Paul!
  • RuAware
    RuAware over 10 years
    Thanks for this, it's taken me ages to get this far with sdk 19!! My problem is that my device is using Google drive as file browser. If the file is on the device image path is got fine but if the file is on the drive it does not open. Maybe I just need to look at dealing with opening images from google drive. Thing is my app is written to use file path and get image using insampling...
  • Michał Klimczak
    Michał Klimczak over 10 years
    @Dan2552 which part is not working? Do you get any exception?
  • Dan2552
    Dan2552 over 10 years
    Turned out I was using the wrong intent call to the gallery. I was using one that was for any kind of documents, but with a file extension filter.
  • Paul Burke
    Paul Burke over 10 years
    @RuAware When you select a Drive file, it gives back Authority: com.google.android.apps.docs.storage and Segments: [document, acc=1;doc=667]. I'm not sure, but assume that the doc value is the Uri ID that you can query against. You'll likely need permissions to be set up as detailed in "Authorize your app on Android" here: developers.google.com/drive/integrate-android-ui. Please update here if you figure it out.
  • RuAware
    RuAware over 10 years
    Thanks, I thought if they chose to use the Drive it would do all the downloading etc. and just give me the file. As I wan't using it to upload. Seems a but odd to have to program for it. Thanks again
  • Snake
    Snake over 10 years
    @voytez, Can this URI returned through your message converted to the full real path of the image?
  • voytez
    voytez over 10 years
    I believe so, it should work just like before KitKat as this code forces opening image gallery instead of KK documents view. But if you intend to use it to create image then this solution is better as converting to real path is an extra unneccessary step.
  • MBillau
    MBillau over 10 years
    Hey, this so far has been working really well, thanks a lot! Did the Google Drive issue ever get sorted out?
  • nagoya0
    nagoya0 over 10 years
    This is not an answer to new Gallery app (strictly "Media Documents Provider" app) on KitKat.
  • nagoya0
    nagoya0 over 10 years
    The app that questioner calls "Gallery" is probably new file picker on kitkat. FYI: addictivetips.com/android/…
  • Russell Stewart
    Russell Stewart over 10 years
    This isn't working for me. I get the following exception (on stock 4.4.2): E/AndroidRuntime(29204): Caused by: java.lang.SecurityException: Requested flags 0x1, but only 0x0 are allowed
  • Abou-Emish
    Abou-Emish over 10 years
    i'm facing the same problem using File plugin the value is the id not the actual path, can i use the same solution? and tell me please how to call this method from file plugin class, it's urgent matter for me :(
  • greaterKing
    greaterKing over 10 years
    pretty clever. i too needed the actual file uri
  • treejanitor
    treejanitor over 10 years
    I like that your code is checkstyle compliant other than missing @return in the initial method javadoc (and a few other minor tidbits). Kudos, sir! Note that it appeared to require 4.4 also, so I marked it with the annotation @TargetApi(Build.VERSION_CODES.KITKAT) - oh and lastly, it is pleasing to note that someone other than myself uses "final" heavily. :-)
  • lorenzo-s
    lorenzo-s about 10 years
    Worked for me too, instead of Intent.ACTION_GET_CONTENT. Anyway I kept the Intent.createChooser() wrapper on the new Intent, to let user choose the app for browsing, and worked as expected. Can someone see drawbacks for this solution?
  • Dennis Anderson
    Dennis Anderson almost 10 years
    This solution works wonderfull ! thanks for that. @RuAware i'm wondering if the Google Drive problem has been fixed! I needed myself too :)
  • j__m
    j__m over 9 years
    this is absolutely horrible! you should not continue to propagate code that "cheats" like this. it only supports the source apps that you know the pattern for, and the whole point of the document provider model is to support arbitrary sources
  • Skywalker
    Skywalker over 9 years
    if data.getData() is null, use: bitmap = (Bitmap)data.getExtras().get("data");
  • thomasforth
    thomasforth over 9 years
    What a beautifully simple answer, thank you! For others following this answer 'cxt' refers to the current context and will usually be 'this'.
  • Michał Klimczak
    Michał Klimczak over 9 years
    Thanks, I'll edit my answer so it's clear what cxt is
  • Quantum_VC
    Quantum_VC about 9 years
    Where are you displaying the image in second case?
  • saranya
    saranya about 9 years
    sorry i failed to add this line of code in else if mImgCropping.startCropImage(photoFile,AppConstants.REQUEST_I‌​MAGE_CROP); again need to call the imagecropping function as per my project need
  • izac89
    izac89 about 9 years
    By using if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) are you assuming that if isKitKatis false, than DocumentsContract.isDocumentUri(context, uri) won't be checked (reasonable thinking) ? if so, then how can you be sure about that? if not, then shouldn't the if (isKitKat) be checked first, then if (DocumentsContract.isDocumentUri(context, uri)) ? @Paul Burke
  • weiy
    weiy about 9 years
    Could you clarify if the ACTION_PICK / EXTERNAL_CONTENT_URI intent call works in pre-KitKat, such as 4.3 (API 18)?
  • mishkin
    mishkin about 9 years
    you are my hero, this is exactly what I needed! works great for Google Drive files as well
  • rocknow
    rocknow about 9 years
    Workaround for new Google Photos app gist.github.com/alexzaitsev/75c9b36dfcffd545c676
  • Philip Herbert
    Philip Herbert about 9 years
    What file type is photoFile and mImgCropping?
  • Carlo Moretti
    Carlo Moretti almost 9 years
    what if I need to pick an audio file?
  • Anand Savjani
    Anand Savjani almost 9 years
    @PaulBurke : How to get pdf or text file from google drive using this code ?Please help me as soon as possible
  • Rafa
    Rafa over 8 years
    forget the dumpImageMetaData(uri); it is unnecessary
  • Alex Black
    Alex Black over 8 years
    This doesn't work for me, I get FileNotFoundException calling openInputStream on a LG Nexus 5 with Android 4.4.4 on a uri like this: content://com.android.providers.downloads.documents/document‌​/532
  • Michał Klimczak
    Michał Klimczak over 8 years
    This probably means that the file just isn't there. The URI seems OK.
  • Neerkoli
    Neerkoli over 8 years
    Think out of the box, right? :D This code works exactly like I was expecting.
  • Code
    Code over 8 years
    For a few of my users I am getting the path as null if the uri.getScheme() is content using this code. Any idea how to fix this @PaulBurke as it is a major bug in app?
  • Yaroslav Mytkalyk
    Yaroslav Mytkalyk over 8 years
    @user2162550 consider if (a() && b()). In this case, if a is false, b will not be checked by JVM since there is no point checking for b -- result is already false.
  • Lumii
    Lumii over 8 years
    Hi, if I use the above code, together with a 3rd party file explorer, null will returned eventually. I was wondering, is this is shortcoming of the above code, or incorrect implementation of 3rd party file explorer app? Thanks - stackoverflow.com/q/34465905/72437
  • YoungDinosaur
    YoungDinosaur over 8 years
    I receive java.lang.IllegalArgumentException: None of the requested columns can be provided when selecting a Google Doc image
  • Henry
    Henry over 8 years
    @dirkoneill I am getting the same Exception. Did you find a fix?
  • jcromanu
    jcromanu about 8 years
    May 2016 and still working on marshmallow with a min target of api 15 .Great job
  • Shruti
    Shruti almost 8 years
    Thank you so much, its working, you just made my day .
  • Sudhir Singh Khanger
    Sudhir Singh Khanger almost 8 years
    >Get the value of the data column for this Uri. This is useful for MediaStore Uris, and other file-based ContentProviders. What is the purpose of getDataColumn? What does it do?
  • Sudhir Singh Khanger
    Sudhir Singh Khanger almost 8 years
    >// TODO handle non-primary volumes. Does it work with external storage like external sd cards?
  • Sudhir Singh Khanger
    Sudhir Singh Khanger almost 8 years
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentRe‌​solver(), uri). What is wrong with this?
  • jacksonakj
    jacksonakj almost 8 years
    Thank you. Using the Uri and ContentResolver this way simplified my application significantly when dealing with files.
  • Osify
    Osify over 7 years
    I do similar and got IndexOutOfBound on Nexus 5X, Android 6 on this line: cursor.getString(idx);
  • soshial
    soshial over 7 years
    The _data wouldn't work when ContentProvider doesn't support it. It is recommended to follow @CommonsWare instructions and not use full file path anymore, because it could be a file in Dropbox cloud instead of a real file.
  • FaisalAhmed
    FaisalAhmed about 7 years
    i was facing issue .... uri.getPath() was returning uri with /external and it was not returning path. i added this else if ("content".equalsIgnoreCase(uri.getScheme())) block and this works good now .. can u explain what does it do
  • Marian Klühspies
    Marian Klühspies about 7 years
    I had this in my app and now it breaks on Android 7+ nougat devices
  • Thracian
    Thracian over 6 years
    How can use this input to write EXIF data to image versions before Android 7.1. ? In Android 7.1 ExifInterface can use inputStream but in versions before that ExifInterface only takes String as an argument
  • murt
    murt over 6 years
    I got on Samsung s7, nougat. SecurityException: No persistable permission grants found for UID 10206 and Uri 0 @ content://com.android.providers.media.documents/document/ima‌​ge:958
  • snark
    snark over 6 years
    For anyone who's wondering the quote comes from developer.android.com/guide/topics/providers/…
  • mikemike396
    mikemike396 almost 6 years
    Works perfect! Thank You
  • karanatwal.github.io
    karanatwal.github.io over 5 years
    For those who are getting Error Unknown URI: content://downloads/public_downloads stackoverflow.com/a/53021624/5996106
  • Bhavesh Moradiya
    Bhavesh Moradiya over 5 years
    filePath is getting null.. In uri: content://com.android.externalstorage.documents/document/799‌​B-1419%3AScreenshot%‌​2FScreenshot_2018111‌​7_162826.png
  • Harvi Sirja
    Harvi Sirja over 5 years
    I just want a working code of kotlin. It's work for me. thanks
  • Bartek Pacia
    Bartek Pacia over 4 years
    post the code for copyAndClose, the answer is not complete
  • Ravi Vaniya
    Ravi Vaniya over 3 years
    Perfecto, Thx @Bringoff
  • jagadishlakkurcom jagadishlakk
    jagadishlakkurcom jagadishlakk about 3 years
    Perefect Working
  • KJEjava48
    KJEjava48 over 2 years
    @RuAware did u find any way to pick file from drive and upload it to server??
  • KJEjava48
    KJEjava48 over 2 years
    @Paul Burke did u find any way to pick file from drive and upload it to server??
  • KJEjava48
    KJEjava48 over 2 years
    @Dennis Anderson did u find any way to pick file from drive and upload it to server??