1

I have read several questions and answers about this (including this one), but most appear to be about older versions of Android and th file system is very different in Android 10. I have also tried to follow the 'App Links Assistant' in Android Studio (4.0.1) but that appers to be only for links from websites, and I wish to open my app from a file explorer. From what I have read, it looks as though my intent filter is correct:

    <activity android:name=".OpenKMZ">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />

            <action android:name="android.intent.action.VIEW" />

            <data android:scheme="file" />
            <data android:scheme="content" />
            <data android:host="*" />
            <!-- <data android:mimeType="application/vnd.google-earth.kmz" /> -->
            <data android:pathPattern=".*\\.kmz" />
        </intent-filter>
    </activity>

I have tried this intent filter with and without the mime type definition.

This is the code I have used to deal with the file when it is opened (so far it would just tell me it has found the file - I will add the rest later).

public class OpenKMZ extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    associateFile();
}
private void associateFile() {
    Intent intent = getIntent();
    String action = intent.getAction();

    assert action != null;
    if (action.compareTo(Intent.ACTION_VIEW) == 0) {
        Toast.makeText(this,
                "from file explorer ! ********************",
                Toast.LENGTH_LONG).show();
        String scheme = intent.getScheme();
        ContentResolver resolver = getContentResolver();
        assert scheme != null;
        if (scheme.compareTo(ContentResolver.SCHEME_FILE) == 0) {
            Uri uri = intent.getData();
            assert uri != null;
            Toast.makeText(this,
                    uri.toString(),
                    Toast.LENGTH_LONG).show();
            String name = uri.getLastPathSegment();
        }
    }
}
}

but after installing the app, file explorers refuse to know what do do with .kmz files. I have tried ES file explorer on Android 8, and the built-in file explorer in Android 10. I have tried the intent filter included in MainActivity, as well as in a separate activity as shown here. Am I missing something fundamental, or is there a mistake with my code?

quilkin
  • 874
  • 11
  • 31
  • 2
    "Am I missing something fundamental" -- custom file extensions have never been supported well in Android, and they are all but useless in modern versions of Android. It is possible that Android will know about that MIME type, so your best bet is to restore that element and remove the `pathPattern` element. – CommonsWare Dec 13 '20 at 00:06
  • Perfect, thanks. Mime type works, pathPattern does not and must not be there. `scheme="content"` must also be used. Now I just have to find out how to use the resulting file string `content://com.google.android.apps.ndu.files.provider/2/12` - I will post a full answer when I can open teh file as I need to – quilkin Dec 13 '20 at 09:06

1 Answers1

0

Thanks to @CommonsWare and also this question, I now have it working. Altogether a lot of work, simply to get round the fact that Android 10 does not allow access to the common downlload folder! My manifest now includes this, as part of the main activity:

        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="file" />
            <data android:scheme="content" />
            <data android:host="*" />
            <data android:mimeType="application/vnd.google-earth.kmz" />
        </intent-filter>

It needs the Mime type but NOT the pathPattern.

The code to get the file is as follows: called from MainActivity onCreate():

private void associateFile()
{
    Intent intent = getIntent();
    if (intent == null)
    {
       return;
    }
    Uri uri = intent.getData();
    if (uri == null)
    {
        Toast.makeText(MainActivity.this, "null URI", Toast.LENGTH_LONG).show();
        return;
    }
//    Debug.waitForDebugger();
    kmz.getFileFromURL( this,  uri);
}

Note that the 'waitForDebugger' line allows you to attach the debugger when the app is started from the link, rather than from Android Studio. And 'getFileFromURL()' looks like this (I copy the file to the app's folder for future use):

public static void getFileFromURL(final Context context, final Uri uri) {
    ContentResolver contentResolver = context.getContentResolver();
    try {
        String mimeType = contentResolver.getType(uri);
        Cursor returnCursor =
                contentResolver.query(uri, null, null, null, null);
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        returnCursor.moveToFirst();
        String fileName = returnCursor.getString(nameIndex);
        InputStream inputStream =  contentResolver.openInputStream(uri);
        // get private downlaoad dir for Android 10
        File downloadDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
        File f = new File(downloadDir +  "/" + fileName);

        FileOutputStream out = new FileOutputStream(f);
        IOUtils.copyStream(inputStream,out);
         .....
         // then whatever you need with the file f
       

    }catch (Exception e){
        e.printStackTrace();

    }

I hope that all this helps others with the same problem.

quilkin
  • 874
  • 11
  • 31