Search code examples
androidandroid-intentandroid-file

Why would an Android Open File intent hang while opening an image?


My Problem: When openFile() intent attempts StartActivityForResult, the application hangs with a blank screen and circular cursor. The file(s) are stored to app.

What I have done: Before and after this issue I researched how to open files by use of Intents. I found a number of similar but different approaches and either used the literal example or a combination of various examples to see if I could find and resolve the issue (see some below). I'm not receiving any type of error message that I have found, and I had the FileUriExposedException previously but resolved it. These files are stored to the app and it may be a permissions issue and have tried what I know, including updating the manifest with for External Read and Write and added a flag setting on the intent for access.

What I'm trying to do: I'm trying to learn how to open files through intents with simple JPG images, then eventually expand to opening various file types after I understand how to do so.

Below is the current code I'm using and it included a MimeTypeMap that I tried in place of "image/jpeg" in case my syntax was not correct on the MIME Type, which did not seem to have an impact.

private void openFile(Uri uri, String fName) {

        MimeTypeMap myMime = MimeTypeMap.getSingleton();
        String mimeType = myMime.getMimeTypeFromExtension(getUpperBound(fName));

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("content://" + uri), "image/jpeg");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivityForResult(intent, 2);
    }

An image of the resulting issue hanging and never opening below:

Hanging Image

Some of the referenced links I tried:

https://developer.android.com/guide/components/intents-common

ACTION_VIEW intent for a file with unknown MimeType

Open File With Intent (Android)

http://www.androidsnippets.com/open-any-type-of-file-with-default-intent.html


Solution

  • I was able to resolve my issue combined with S-Sh's second suggestion of considering the use of FileProvider. I had to perform some refinements and ended up with the following to work. I also provided links to the sources in which I used.

    Context of the solution:

    As a note to future readers as to the context of this solution within my Android app, the code below is launched by clicking a "clickable" TableRow in a TableLayout. The TableLayout lists each filename and file ID as a TableRow. Once a row is clicked, the onClick method of the selected TableRow the filename is acquired and the File class and FileProvider are used and filename passed to create an Uri. This Uri is then passed to an openFile(Uri uri) method I created encapsulating (so-to-speak) the Intent used to open the file.

    Code

    Adding of the FileProvider to the AndroidManifest.xml' within the` tag:

    <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.mistywillow.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
        <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
    </provider>
    

    Creating within res directory the file_paths.xml and xml directory (res/xml/):

    <?xml version="1.0" encoding="utf-8"?>
       <paths xmlns:android="http://schemas.android.com/apk/res/android">
          <files-path name="myFiles" path="." />
       </paths>
    

    The onClick capturing the filename and preparing the Uri to be passed to the openFile():

        row.setOnClickListener(v -> {
    
            TableRow tablerow = (TableRow) v;
            TextView sample = (TextView) tablerow.getChildAt(1);
            String result = sample.getText().toString();
    
            File filePaths = new File(getFilesDir().toString());
            File newFile = new File(filePaths, result);
            Uri contentUri = getUriForFile(getApplicationContext(), "com.mydomain.fileprovider", newFile);
            openFile(contentUri);
    
        });
    

    The openFile(Uri uri) method containing the Intent to open a file:

    private void openFile(Uri uri){
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(uri);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivityForResult(intent, 2);
    }
    

    Links referenced:

    https://developer.android.com/reference/androidx/core/content/FileProvider

    FileProvider - IllegalArgumentException: Failed to find configured root