0

So, I have to get GPS data from file MetaData. "No problem", I said, "This will only take an hour or two". Six hour later, here I am searching through all Android Documentation and Stack exchange questions I can yet I still cant get it to work.

My Code is straight forward:

  1. I am using a ACTION_PICK to select a video (ACTION_OPEN_DOCUMENT Doesn't work either).
  2. I Have already requested the following permissions and added to the Manifest:
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />

Below is code from the button listener

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_PICK , MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                //intent.setType("video/*");
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
                startActivityForResult(Intent.createChooser(intent,"Select A Video"),REQUEST_VIDEO_CONTENT);
            }
        });

And From the OnActivityResult:

    protected void onActivityResult(int requestCode, int resultCode, Intent vIntent) {
        super.onActivityResult(requestCode, resultCode, vIntent);

        if ((requestCode == REQUEST_VIDEO_CAPTURE || requestCode == REQUEST_VIDEO_CONTENT) && resultCode == RESULT_OK) {
            //Attempt to get Content Data
            vIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            vIntent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
            Uri vUri = vIntent.getData();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
                vUri = MediaStore.setRequireOriginal(vUri);
            }
            try {
                InputStream vIS = getContentResolver().openInputStream(vUri);
                ExifInterface vExif =  new ExifInterface(vIS);

            } catch (SecurityException | IOException e) {
                e.printStackTrace();
            }

And finally, the lovely SecurityException:

W/System.err: java.lang.SecurityException: Permission Denial: reading com.google.android.apps.photos.contentprovider.impl.MediaContentProvider uri content://com.google.android.apps.photos.contentprovider/0/2/content%3A%2F%2Fmedia%2Fexternal%2Fvideo%2Fmedia%2F198668/ORIGINAL/NONE/video%2Fmp4/328149382?requireOriginal=1 from pid=6190, uid=10146 requires the provider be exported, or grantUriPermission()
W/System.err:     at android.os.Parcel.createException(Parcel.java:2071)
       at android.os.Parcel.readException(Parcel.java:2039)
W/System.err:     at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)
       at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151)
W/System.err:     at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:705)
       at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1710)
W/System.err:     at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1526)
W/System.err:     at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1345)
       at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1293)
W/System.err:     at com.equinox.openeyes.VideoSubmission.onActivityResult(VideoSubmission.java:117)
       at android.app.Activity.dispatchActivityResult(Activity.java:8147)
       at android.app.ActivityThread.deliverResults(ActivityThread.java:4883)
W/System.err:     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4931)
       at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2022)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:235)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7441)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

I get that the Error is saying the provider needs to be exported, or grantUriPermission which sounds like an easy fix, except I cannot find a way to implement what they ask. All the places I have looked have suggested adding flags.. as you can see it didnt work.

Please Help :-(

Ryan M
  • 18,333
  • 31
  • 67
  • 74
Equinox
  • 15
  • 1
  • 6
  • The stack trace does not quite match your code (your code uses `openInputStream()`, the stack trace uses `openFileDescriptor()`). None of your `addFlags()` calls do anything, as permissions are determined by the provider, not you. If you skip the `setRequireOriginal()` call, and you skip the `ExifInterface` bit, does your code successfully work with the `Uri`? IOW, are you running into problems with the basic `ACTION_PICK` result, or is the `setRequireOriginal()` call trigger your problems? – CommonsWare Sep 22 '20 at 23:00
  • Yes, If I remove setRequireOriginal it will run and even give some Exif information, but not the Location Data I am looking for. The error is in this line: ***InputStream vIS = getContentResolver().openInputStream(vUri);*** – Equinox Sep 22 '20 at 23:08
  • OK, and to confirm, you are [requesting `ACCESS_MEDIA_LOCATION` at runtime](https://developer.android.com/training/data-storage/shared/media#media-location-permission) in addition to having it in the manifest? `setRequireOriginal()` was a mess when I tried working with it last year. However, in my experiments, I did not need it for `ACTION_OPEN_DOCUMENT` -- I could get the location data via `ExifInterface` without `setRequireOriginal()`. – CommonsWare Sep 22 '20 at 23:19
  • However, my tests were with images. [`ExifInterface` does not document support for video file formats](https://developer.android.com/reference/androidx/exifinterface/media/ExifInterface). Does your code work on older devices? – CommonsWare Sep 22 '20 at 23:19
  • 1. Yes I am requesting ad runttime ` ActivityCompat.requestPermissions(this,new String[] {Manifest.permission.ACCESS_MEDIA_LOCATION},ACCESS_MEDIA_LOCATION_REQUEST_CODE); ` – Equinox Sep 23 '20 at 01:06
  • 2. Without setRequireOriginal and ACTION_OPEN_DOCUMENT, getLatLong comes back Null. – Equinox Sep 23 '20 at 01:14
  • 3. No I haven't tested on an older phone. Perhaps it never worked. Just trying to get the data from a video. Should be possible, but seems to be a state secret. – Equinox Sep 23 '20 at 01:34
  • "No I haven't tested on an older phone. Perhaps it never worked" -- I recommend giving that a try, along with trying `ACTION_OPEN_DOCUMENT` with a JPEG that you know (e.g., via `exiftool`) has the location data that you seek. "Should be possible" -- perhaps, but it may be that `ExifInterface` does not completely support videos (not to mention that I am uncertain if every video format honored by `video/*` as a MIME type supports EXIF in the first place, which your code assumes). – CommonsWare Sep 23 '20 at 10:42
  • Thanks. I have confirmed through the exif tool that there is no GPS data on videos. My phone is a an Asus Zenfone running Android 10. Using Exif tool I can see that there is GPS Data on image files, but not for videos; However, in the photo gallery my videos have geolocation data. So it would seem that this information is being stashed somewhere, just not in the video content for videos, but is still being store in image content. This is independent of my main issue, which is the permission which I am still not able to resolve. – Equinox Sep 23 '20 at 20:17
  • Did you try asking the media store directly for the GPS position (`MediaStore.Video.Media.LATITUDE` and `MediaStore.Video.Media.LONGITUDE`)? If MediaStore has the data, you might not even need to use ExifInterface. – PHolzwarth Feb 15 '22 at 19:19

0 Answers0