mendhak / gpslogger

:satellite: Lightweight GPS Logging Application For Android.
https://gpslogger.app
Other
1.99k stars 609 forks source link

Enhancement - Open gpx data folder directly #1056

Closed locuturus closed 1 year ago

locuturus commented 1 year ago

Hello I have a suggestion for an enhancement. The following intent:

ACTION android.intent.action.VIEW DATA content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fdata%2Fcom.mendhak.gpslogger%2Ffiles TYPE vnd.android.document/directory FLAGS 0x10000000

Will offer to open your gpx folder directly in DocumentsUI Files app which always has access to Android/data. I picked a single flag that I find useful when testing intents (activity_new_task) but you can set the flags many different ways or clear them entirely. This could be like a folder icon button beside the file path or something like that.

mendhak commented 1 year ago

Yanno... I actually used to have that path to the file as a link. And I removed it one day... I can't remember exactly why, it was causing crashes on some devices? I'm going to have to dig that out and find out what was wrong, but bringing it back ought to be simple I hope, and I'll see if I can wrap its code in some try catch (and why didn't I do that in the first place!!)

locuturus commented 1 year ago

I can only speculate that most file browsers can't open Android/data paths in modern Android and you maybe had used file:/// or other slash delimited intent structure which would only invoke different non-aosp file managers. The intent I provided above should open the Android/data path in the AOSP Files app which can open those paths.

mendhak commented 1 year ago

That's exactly it, I found what I used and it matched what you said:

        final Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(Uri.parse("file://" + pathToLinkTo), "resource/folder");
        intent.setAction(Intent.ACTION_VIEW);

OK nice. I'll try the new way when I can find a little time, I'm a bit slow.

mendhak commented 1 year ago

This is as far as I got today, not much success but not sure what I'm missing.

                if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    Uri folderUri = DocumentsContract.buildDocumentUriUsingTree(
                            Uri.parse("content://com.android.externalstorage.documents/tree/primary"),
                            DocumentsContract.getTreeDocumentId(Uri.fromFile(file)));
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    //intent.setDataAndType(folderUri, "resource/folder");
                    intent.setDataAndType(folderUri, "vnd.android.document/directory");
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, folderUri);
                    startActivity(intent);
                }

Which results in

java.lang.IllegalArgumentException: Invalid URI: file:///storage/emulated/0/Android/data/com.mendhak.gpslogger/files
at android.provider.DocumentsContract.getTreeDocumentId(DocumentsContract.java:1289)
at com.mendhak.gpslogger.ui.fragments.display.GpsSimpleViewFragment$2.onClick(GpsSimpleViewFragment.java:210)
...
locuturus commented 1 year ago

I haven't tried to code an intent before, I use other apps to send custom intents. From the look of your code I guess you're dynamically getting the file path of your apps directory, which is probably wise, but the result is still a file:/// intent which cannot be used to reach into Android/data. I guess, and it is only a guess, that you need a method to return the URI, and not parse it into a file path. DocumentsUI will only open directories when given URI format.

On Fri, Mar 31, 2023, 14:29 mendhak @.***> wrote:

This is as far as I got today, not much success but not sure what I'm missing.

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Uri folderUri = DocumentsContract.buildDocumentUriUsingTree(
                        Uri.parse("content://com.android.externalstorage.documents/tree/primary"),
                        DocumentsContract.getTreeDocumentId(Uri.fromFile(file)));
                Intent intent = new Intent(Intent.ACTION_VIEW);
                //intent.setDataAndType(folderUri, "resource/folder");
                intent.setDataAndType(folderUri, "vnd.android.document/directory");
                intent.addCategory(Intent.CATEGORY_DEFAULT);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, folderUri);
                startActivity(intent);
            }

Which results in

java.lang.IllegalArgumentException: Invalid URI: file:///storage/emulated/0/Android/data/com.mendhak.gpslogger/files at android.provider.DocumentsContract.getTreeDocumentId(DocumentsContract.java:1289) at com.mendhak.gpslogger.ui.fragments.display.GpsSimpleViewFragment$2.onClick(GpsSimpleViewFragment.java:210) ...

— Reply to this email directly, view it on GitHub https://github.com/mendhak/gpslogger/issues/1056#issuecomment-1492631524, or unsubscribe https://github.com/notifications/unsubscribe-auth/AET72VL6TTOYPNY2X4YDSQLW65ECPANCNFSM6AAAAAAVHHV5H4 . You are receiving this because you authored the thread.Message ID: @.***>

mendhak commented 1 year ago

Some progress at last. The big problem is that the DocumentsUI app only accepts content:// URIs as you know, but building those URIs is very difficult. I found many unreliable examples that were sort of hacking the URI together but I did manage to figure out a way that uses the framework methods and shouldn't necessarily break that easily.

https://github.com/mendhak/gpslogger/compare/issue-1056-open-folder#diff-7c5b4e0090ce6a46602b6970328f2e9b895a301048523bbb2b99af27880001f1R202-R242

Of course there's a catch. Although the DocumentsContract.buildDocumentUri exists, figuring out the initial part path makes use of [StorageVolume.getDirectory](https://developer.android.com/reference/android/os/storage/StorageVolume#getDirectory()), which is Android API level 30, which is Android R.

mendhak commented 1 year ago

v127 is on F-Droid and the Releases section.