apache / cordova-plugin-file

Apache Cordova File Plugin
https://cordova.apache.org/
Apache License 2.0
740 stars 757 forks source link

fix(android): missing content uri handler in WebViewAssetLoader.PathHandler #582

Open lovelyelfpop opened 10 months ago

lovelyelfpop commented 10 months ago

Bug Report

Problem

Android webview cannot display <img> with src="https://localhost/__cdvfile_content__/..."

What is expected to happen?

Android webview should display <img> with src="https://localhost/__cdvfile_content__/..."

What does actually happen?

ERR_CONNECTION_REFUSED in console,img not displaying

Information

<img> with src like https://localhost/__cdvfile_asstes__/... or https://localhost/__cdvfile_files__/... can display in webview, but not https://localhost/__cdvfile_content__/...,

Environment, Platform, Device

Redmi K30 pro, Android 11

Version information

Cordova@11.0.0 Cordova-Android@10.1.2 cordova-plugin-file@8.0.1-dev

Checklist

Reason

WebViewAssetLoader.PathHandler in cordova-plugin-file\src\android\FileUtils.java missing content uri handler.

The right code is

    public CordovaPluginPathHandler getPathHandler() {
        WebViewAssetLoader.PathHandler pathHandler = path -> {
            String targetFileSystem = null;

            if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("persistent"))) {
                targetFileSystem = "persistent";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("temporary"))) {
                targetFileSystem = "temporary";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("files"))) {
                targetFileSystem = "files";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("documents"))) {
                targetFileSystem = "documents";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("cache"))) {
                targetFileSystem = "cache";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("root"))) {
                targetFileSystem = "root";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("files-external"))) {
                targetFileSystem = "files-external";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("sdcard"))) {
                targetFileSystem = "sdcard";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("cache-external"))) {
                targetFileSystem = "cache-external";
            } else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("assets"))) {
                targetFileSystem = "assets";
            }
            // --------------------added start--------------------
            else if (path.startsWith(LocalFilesystemURL.fsNameToCdvKeyword("content"))) {
                targetFileSystem = "content";
            }
            // --------------------added end--------------------

            boolean isAssetsFS = targetFileSystem == "assets";

            if (targetFileSystem != null) {
                // Loop the registered file systems to find the target.
                for (Filesystem fileSystem : filesystems) {
                    /*
                     * When target is discovered:
                     * 1. Transform the url path to the native path
                     * 2. Load the file contents
                     * 3. Get the file mime type
                     * 4. Return the file & mime information back we Web Resources
                     */
                    if (fileSystem.name.equals(targetFileSystem)) {
                        // E.g. replace __cdvfile_persistent__ with native path "/data/user/0/com.example.file/files/files/"
                        String fileSystemNativeUri = fileSystem.rootUri.toString().replace("file://", "");
                        String fileTarget = path.replace(LocalFilesystemURL.fsNameToCdvKeyword(targetFileSystem) + "/", fileSystemNativeUri);
                        File file = null;

                        if (isAssetsFS) {
                            fileTarget = fileTarget.replace("/android_asset/", "");
                        } else {
                            file = new File(fileTarget);
                        }

                        try {
                            // --------------------added start--------------------
                            if(targetFileSystem == "content") {
                                ContentResolver cr = webView.getContext().getContentResolver();
                                Uri uri = Uri.parse(fileTarget);
                                InputStream fileIS = new FileInputStream(cr.openFileDescriptor(uri, "r").getFileDescriptor());
                                String fileMimeType = cr.getType(uri);

                                return new WebResourceResponse(fileMimeType, null, fileIS);
                            }
                            // --------------------added end--------------------

                            InputStream fileIS = !isAssetsFS ?
                                    new FileInputStream(file) :
                                    webView.getContext().getAssets().open(fileTarget);

                            String filePath = !isAssetsFS ? file.toString() : fileTarget;
                            Uri fileUri = Uri.parse(filePath);
                            String fileMimeType = getMimeType(fileUri);

                            return new WebResourceResponse(fileMimeType, null, fileIS);
                        } catch (FileNotFoundException e) {
                            Log.e(LOG_TAG, e.getMessage());
                        } catch (IOException e) {
                            Log.e(LOG_TAG, e.getMessage());
                        }
                    }
                }
            }

            return null;
        };

        return new CordovaPluginPathHandler(pathHandler);
    }
}