Android 10的H5获取文件找不到路径

在Android 10版本中,由于系统的安全限制,H5页面无法直接访问本地文件系统的路径。这个限制主要是为了保护用户的隐私和防止恶意应用滥用文件访问权限。但是,如果我们需要在H5页面中获取文件的路径,该怎么办呢?本文将介绍一种方法,通过Android原生代码来实现H5页面获取文件路径的功能。

Android 10文件路径限制

在Android 10之前的版本中,我们可以通过JavaScript的input元素的files属性来获取用户选择的文件。例如,我们可以通过以下代码来获取用户选择的图片文件路径:

var fileInput = document.getElementById('fileInput');
var filePath = fileInput.files[0].path;
console.log(filePath);

然而,在Android 10中,由于系统对文件系统的限制,上述代码将无法正常工作。如果我们尝试运行这段代码,将会得到fileInput.files[0].pathundefined的结果。

解决方案

为了解决Android 10中H5获取文件路径的问题,我们需要通过Android原生代码来获取文件路径,并将其传递给H5页面。下面是一种解决方案的示例:

  1. 首先,在Android项目的android/app/src/main/java目录下创建一个新的Java类,例如FileUtils.java。在该类中,我们将实现获取文件路径的方法。
package com.example.myapplication;

import android.content.Context;
import android.net.Uri;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileUtils {

    public static String getFilePath(Context context, Uri uri) throws IOException {
        String filePath = null;
        if (uri.getScheme().equals("content")) {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            File file = new File(context.getCacheDir(), "temp");
            FileOutputStream outputStream = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }
            outputStream.close();
            inputStream.close();
            filePath = file.getAbsolutePath();
        } else if (uri.getScheme().equals("file")) {
            filePath = uri.getPath();
        }
        return filePath;
    }
}

在上述代码中,我们定义了一个getFilePath方法,用于根据Uri获取文件的路径。如果Uri的scheme为content,则我们将通过ContentResolver将文件内容写入临时文件中,并返回临时文件的路径。如果Uri的scheme为file,则直接返回文件的路径。

  1. android/app/src/main/java目录下找到MainActivity.java文件,并修改其内容如下:
package com.example.myapplication;

import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        webView.addJavascriptInterface(new JSInterface(this), "Android");

        webView.loadUrl("file:///android_asset/index.html");
    }
}

在上述代码中,我们首先启用了WebView的JavaScript支持,并通过addJavascriptInterface方法将JSInterface类注入到H5页面中。然后,我们加载了一个位于android_asset目录下的index.html文件。

  1. 创建一个名为JSInterface的Java类,用于在H5页面中调用Android原生方法:
package com.example.myapplication;

import android.content.Context;
import android.webkit.JavascriptInterface;

import java.io.IOException;

public class JSInterface {

    private Context context;

    public JSInterface(Context context) {
        this.context = context;
    }

    @JavascriptInterface
    public String getFilePath(String uriString) {
        try {
            Uri uri = Uri.parse(uriString);
            return FileUtils.getFilePath(context, uri);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

在上述代码中,我们定义了一个getFilePath方法,并添加了@JavascriptInterface注解,该方法将在H5页面中被调用。该方法接收一个字符串参数uriString,并将其转换为Uri对象。然后,我们调用FileUtils.getFilePath方法来获取文件的