Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 有没有办法让FlitterWebView使用android摄像头上传文件_Php_Android_Flutter_File Upload - Fatal编程技术网

Php 有没有办法让FlitterWebView使用android摄像头上传文件

Php 有没有办法让FlitterWebView使用android摄像头上传文件,php,android,flutter,file-upload,Php,Android,Flutter,File Upload,我有一个带有webview的flatterweb应用程序,它从服务器加载我的PHP项目。在我的PHP项目中,我有一个注册表单,要求用户使用相机拍摄照片,然后将其上传到MySQL数据库。问题是,当我点击上传文件按钮使用相机时,它什么也不做。但在浏览器中,文件选择器可以工作,但在我的android上,从webview它什么也没做 我试过了,但效果不太好 <div class="col-sm-4"> Image 1 <span style="color:red">*</s

我有一个带有
webview
的flatterweb应用程序,它从服务器加载我的PHP项目。在我的PHP项目中,我有一个注册表单,要求用户使用相机拍摄照片,然后将其上传到MySQL数据库。问题是,当我点击上传文件按钮使用相机时,它什么也不做。但在浏览器中,文件选择器可以工作,但在我的android上,从
webview
它什么也没做

我试过了,但效果不太好

<div class="col-sm-4">
Image 1 <span style="color:red">*</span><input type="file" name="img1" accept"image/*" capture="camera"  required>
</div>
这是我的书信

cupertino_icons: ^0.1.2
webview_flutter:
simple_animations: ^1.1.3
page_transition: ^1.1.4
carousel_pro: ^0.0.13
url_launcher: ^5.1.1
sliding_up_panel: ^0.3.4
font_awesome_flutter: ^8.5.0
flutter_swiper: ^1.1.6
connectivity:
uni_links:

我认为这是一个使用“webview_颤振”的替代解决方案:


必须编辑“flutrawebview.java”和“AndroidManifest”。

@Bruno的链接答案对我不起作用。 因此,我找到了许多解决方案,并将它们结合起来使用,最终它对我起了作用。
webview\u flatter:^2.0.8
(此解决方案也应适用于较低版本)

先决条件:-在实施此解决方案之前,应先实施权限处理,然后再实施摄像头和存储权限

  • 转到您的颤振的外部库

  • 导航到webview_颤振插件项目文件夹

  • 导航到android文件夹

  • 转到src>main

  • 打开清单文件,它应该是空的,其中只有包名,然后复制粘贴此文件

     <paths xmlns:android="http://schemas.android.com/apk/res/android">
         <external-files-path name="safetyapp_images" path="images" />
     </paths>
    

  • 创建FileChooserActivity.java并复制此文件

    包io.flatter.plugins.webviewflatter

        public class Constants {
            static final String ACTION_REQUEST_CAMERA_PERMISSION_FINISHED =
                    "action_request_camera_permission_denied";
            static final String ACTION_FILE_CHOOSER_FINISHED = "action_file_chooser_completed";
        
            static final String EXTRA_TITLE = "extra_title";
            static final String EXTRA_ACCEPT_TYPES = "extra_types";
            static final String EXTRA_SHOW_VIDEO_OPTION = "extra_show_video_option";
            static final String EXTRA_SHOW_IMAGE_OPTION = "extra_show_image_option";
            static final String EXTRA_FILE_URIS = "extra_file_uris";
            static final String EXTRA_ALLOW_MULTIPLE_FILES = "extra_allow_multiple_files";
        
        
            static final String WEBVIEW_STORAGE_DIRECTORY = "images";
        }
    
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_FILE_CHOOSER_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ACCEPT_TYPES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ALLOW_MULTIPLE_FILES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_FILE_URIS;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_IMAGE_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_VIDEO_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_TITLE;
    import static io.flutter.plugins.webviewflutter.Constants.WEBVIEW_STORAGE_DIRECTORY;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.provider.OpenableColumns;
    import android.util.Log;
    import androidx.annotation.Nullable;
    import androidx.core.content.FileProvider;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    
    public class FileChooserActivity extends Activity {
    
    private static final int FILE_CHOOSER_REQUEST_CODE = 12322;
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
    
    // List of Uris that point to files where there MIGHT be the output of the capture. At most one of these can be valid
    private final ArrayList<Uri> potentialCaptureOutputUris = new ArrayList<>();
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        showFileChooser(
                getIntent().getBooleanExtra(EXTRA_SHOW_IMAGE_OPTION, false),
                getIntent().getBooleanExtra(EXTRA_SHOW_VIDEO_OPTION, false));
    }
    
    private void showFileChooser(boolean showImageIntent, boolean showVideoIntent) {
        Intent getContentIntent = createGetContentIntent();
        Intent captureImageIntent =
                showImageIntent ? createCaptureIntent(MediaStore.ACTION_IMAGE_CAPTURE, "jpg") : null;
        Intent captureVideoIntent =
                showVideoIntent ? createCaptureIntent(MediaStore.ACTION_VIDEO_CAPTURE, "mp4") : null;
    
        if (getContentIntent == null && captureImageIntent == null && captureVideoIntent == null) {
            // cannot open anything: cancel file chooser
            sendBroadcast(new Intent(ACTION_FILE_CHOOSER_FINISHED));
            finish();
        } else {
            ArrayList<Intent> intentList = new ArrayList<>();
    
            if (getContentIntent != null) {
                intentList.add(getContentIntent);
            }
    
            if (captureImageIntent != null) {
                intentList.add(captureImageIntent);
            }
            if (captureVideoIntent != null) {
                intentList.add(captureVideoIntent);
            }
    
            Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
            chooserIntent.putExtra(Intent.EXTRA_TITLE, getIntent().getStringExtra(EXTRA_TITLE));
    
            chooserIntent.putExtra(Intent.EXTRA_INTENT, intentList.get(0));
            intentList.remove(0);
            if (intentList.size() > 0) {
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Intent[0]));
            }
    
            startActivityForResult(chooserIntent, FILE_CHOOSER_REQUEST_CODE);
        }
    }
    
    private Intent createGetContentIntent() {
        Intent filesIntent = new Intent(Intent.ACTION_GET_CONTENT);
    
        if (getIntent().getBooleanExtra(EXTRA_ALLOW_MULTIPLE_FILES, false)) {
            filesIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        }
    
        String[] acceptTypes = getIntent().getStringArrayExtra(EXTRA_ACCEPT_TYPES);
    
        if (acceptTypes.length == 0 || (acceptTypes.length == 1 && acceptTypes[0].length() == 0)) {
            // empty array or only 1 empty string? -> accept all types
            filesIntent.setType("*/*");
        } else if (acceptTypes.length == 1) {
            filesIntent.setType(acceptTypes[0]);
        } else {
            // acceptTypes.length > 1
            filesIntent.setType("*/*");
            filesIntent.putExtra(Intent.EXTRA_MIME_TYPES, acceptTypes);
        }
    
        return (filesIntent.resolveActivity(getPackageManager()) != null) ? filesIntent : null;
    }
    
    private Intent createCaptureIntent(String type, String fileFormat) {
        Intent captureIntent = new Intent(type);
        if (captureIntent.resolveActivity(getPackageManager()) == null) {
            return null;
        }
    
        // Create the File where the output should go
        Uri captureOutputUri = getTempUri(fileFormat);
        potentialCaptureOutputUris.add(captureOutputUri);
    
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, captureOutputUri);
    
        return captureIntent;
    }
    private File getStorageDirectory() {
        File imageDirectory = new File(this.getExternalFilesDir(null), WEBVIEW_STORAGE_DIRECTORY);
        if (!imageDirectory.isDirectory()) {
            imageDirectory.mkdir();
        }
        return imageDirectory;
    }
    
    
    private Uri getTempUri(String format) {
        String fileName = "CAPTURE-" + simpleDateFormat.format(new Date()) + "." + format;
        File file = new File(getStorageDirectory(), fileName);
        return FileProvider.getUriForFile(
                this, getApplicationContext().getPackageName() + ".generic.provider", file);
    }
    
    private String getFileNameFromUri(Uri uri) {
        Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
        assert returnCursor != null;
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        returnCursor.moveToFirst();
        String name = returnCursor.getString(nameIndex);
        returnCursor.close();
        return name;
    }
    
    private Uri copyToLocalUri(Uri uri) {
        File destination = new File(getStorageDirectory(), getFileNameFromUri(uri));
    
        try (InputStream in = getContentResolver().openInputStream(uri);
             OutputStream out = new FileOutputStream(destination)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return FileProvider.getUriForFile(
                    this, getApplicationContext().getPackageName() + ".generic.provider", destination);
        } catch (IOException e) {
            Log.e("WEBVIEW", "Unable to copy selected image", e);
            e.printStackTrace();
            return null;
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
            Intent fileChooserFinishedIntent = new Intent(ACTION_FILE_CHOOSER_FINISHED);
            if (resultCode == Activity.RESULT_OK) {
                if (data != null && (data.getDataString() != null || data.getClipData() != null)) {
                    if (data.getDataString() != null) {
                        // single result from file browser OR video from camera
                        Uri localUri = copyToLocalUri(data.getData());
                        if (localUri != null) {
                            fileChooserFinishedIntent.putExtra(
                                    EXTRA_FILE_URIS, new String[] {localUri.toString()});
                        }
                    } else if (data.getClipData() != null) {
                        // multiple results from file browser
                        int uriCount = data.getClipData().getItemCount();
                        String[] uriStrings = new String[uriCount];
    
                        for (int i = 0; i < uriCount; i++) {
                            Uri localUri = copyToLocalUri(data.getClipData().getItemAt(i).getUri());
                            if (localUri != null) {
                                uriStrings[i] = localUri.toString();
                            }
                        }
                        fileChooserFinishedIntent.putExtra(EXTRA_FILE_URIS, uriStrings);
                    }
                } else {
                    // image result from camera (videos from the camera are handled above, but this if-branch could handle them too if this varies from device to device)
                    for (Uri captureOutputUri : potentialCaptureOutputUris) {
                        try {
                            // just opening an input stream (and closing immediately) to test if the Uri points to a valid file
                            // if it's not a real file, the below catch-clause gets executed and we continue with the next Uri in the loop.
                            getContentResolver().openInputStream(captureOutputUri).close();
                            fileChooserFinishedIntent.putExtra(
                                    EXTRA_FILE_URIS, new String[] {captureOutputUri.toString()});
                            // leave the loop, as only one of the potentialCaptureOutputUris is valid and we just found it
                            break;
                        } catch (IOException ignored) {
                        }
                    }
                }
            }
            sendBroadcast(fileChooserFinishedIntent);
            finish();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
       }
     }
    
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_FILE_CHOOSER_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_REQUEST_CAMERA_PERMISSION_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ACCEPT_TYPES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ALLOW_MULTIPLE_FILES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_FILE_URIS;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_IMAGE_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_VIDEO_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_TITLE;
    
    import android.Manifest;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.webkit.ValueCallback;
    import androidx.core.content.ContextCompat;
    
    public class FileChooserLauncher extends BroadcastReceiver {
    
    private Context context;
    private String title;
    private boolean allowMultipleFiles;
    private boolean videoAcceptable;
    private boolean imageAcceptable;
    private ValueCallback<Uri[]> filePathCallback;
    private String[] acceptTypes;
    
    public FileChooserLauncher(
            Context context,
            boolean allowMultipleFiles,
            ValueCallback<Uri[]> filePathCallback,
            String[] acceptTypes) {
        this.context = context;
        this.allowMultipleFiles = allowMultipleFiles;
        this.filePathCallback = filePathCallback;
        this.acceptTypes = acceptTypes;
    
        if (acceptTypes.length == 0 || (acceptTypes.length == 1 && acceptTypes[0].length() == 0)) {
            // acceptTypes empty -> accept anything
            imageAcceptable = true;
            videoAcceptable = true;
        } else {
            for (String acceptType : acceptTypes) {
                if (acceptType.startsWith("image/")) {
                    imageAcceptable = true;
                } else if (acceptType.startsWith("video/")) {
                    videoAcceptable = true;
                }
            }
        }
    
        if (imageAcceptable && !videoAcceptable) {
            title = context.getResources().getString(R.string.webview_image_chooser_title);
        } else if (videoAcceptable && !imageAcceptable) {
            title = context.getResources().getString(R.string.webview_video_chooser_title);
        } else {
            title = context.getResources().getString(R.string.webview_file_chooser_title);
        }
    }
    
    private boolean canCameraProduceAcceptableType() {
        return imageAcceptable || videoAcceptable;
    }
    
    private boolean hasCameraPermission() {
        return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED;
    }
    
    public void start() {
        if (!canCameraProduceAcceptableType() || hasCameraPermission()) {
            showFileChooser();
        } else {
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED);
            context.registerReceiver(this, intentFilter);
    
            Intent intent = new Intent(context, RequestCameraPermissionActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }
    
    private void showFileChooser() {
        IntentFilter intentFilter = new IntentFilter(ACTION_FILE_CHOOSER_FINISHED);
        context.registerReceiver(this, intentFilter);
    
        Intent intent = new Intent(context, FileChooserActivity.class);
        intent.putExtra(EXTRA_TITLE, title);
        intent.putExtra(EXTRA_ACCEPT_TYPES, acceptTypes);
        intent.putExtra(EXTRA_SHOW_IMAGE_OPTION, imageAcceptable && hasCameraPermission());
        intent.putExtra(EXTRA_SHOW_VIDEO_OPTION, videoAcceptable && hasCameraPermission());
        intent.putExtra(EXTRA_ALLOW_MULTIPLE_FILES, allowMultipleFiles);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED)) {
            context.unregisterReceiver(this);
            showFileChooser();
        } else if (intent.getAction().equals(ACTION_FILE_CHOOSER_FINISHED)) {
            String[] uriStrings = intent.getStringArrayExtra(EXTRA_FILE_URIS);
            Uri[] result = null;
    
            if (uriStrings != null) {
                int uriStringCount = uriStrings.length;
                result = new Uri[uriStringCount];
    
                for (int i = 0; i < uriStringCount; i++) {
                    result[i] = Uri.parse(uriStrings[i]);
                }
            }
    
            filePathCallback.onReceiveValue(result);
            context.unregisterReceiver(this);
            filePathCallback = null;
        }
      }
     }
    
  • 创建一个类
    RequestCameraPermissionActivity.java
    ,并将此代码粘贴到那里

  • 导入android.Manifest; 导入android.app.Activity; 导入android.content.Intent; 导入android.os.Bundle; 导入androidx.annotation.NonNull; 导入androidx.annotation.Nullable; 导入androidx.core.app.ActivityCompat

        public class RequestCameraPermissionActivity extends Activity {
    
        private static final int CAMERA_PERMISSION_REQUEST_CODE = 12321;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            ActivityCompat.requestPermissions(
                    this, new String[] {Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
        }
    
        @Override
        public void onRequestPermissionsResult(
                int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
                sendBroadcast(new Intent(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED));
                finish();
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }
    
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_FILE_CHOOSER_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ACCEPT_TYPES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ALLOW_MULTIPLE_FILES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_FILE_URIS;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_IMAGE_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_VIDEO_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_TITLE;
    import static io.flutter.plugins.webviewflutter.Constants.WEBVIEW_STORAGE_DIRECTORY;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.provider.OpenableColumns;
    import android.util.Log;
    import androidx.annotation.Nullable;
    import androidx.core.content.FileProvider;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    
    public class FileChooserActivity extends Activity {
    
    private static final int FILE_CHOOSER_REQUEST_CODE = 12322;
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
    
    // List of Uris that point to files where there MIGHT be the output of the capture. At most one of these can be valid
    private final ArrayList<Uri> potentialCaptureOutputUris = new ArrayList<>();
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        showFileChooser(
                getIntent().getBooleanExtra(EXTRA_SHOW_IMAGE_OPTION, false),
                getIntent().getBooleanExtra(EXTRA_SHOW_VIDEO_OPTION, false));
    }
    
    private void showFileChooser(boolean showImageIntent, boolean showVideoIntent) {
        Intent getContentIntent = createGetContentIntent();
        Intent captureImageIntent =
                showImageIntent ? createCaptureIntent(MediaStore.ACTION_IMAGE_CAPTURE, "jpg") : null;
        Intent captureVideoIntent =
                showVideoIntent ? createCaptureIntent(MediaStore.ACTION_VIDEO_CAPTURE, "mp4") : null;
    
        if (getContentIntent == null && captureImageIntent == null && captureVideoIntent == null) {
            // cannot open anything: cancel file chooser
            sendBroadcast(new Intent(ACTION_FILE_CHOOSER_FINISHED));
            finish();
        } else {
            ArrayList<Intent> intentList = new ArrayList<>();
    
            if (getContentIntent != null) {
                intentList.add(getContentIntent);
            }
    
            if (captureImageIntent != null) {
                intentList.add(captureImageIntent);
            }
            if (captureVideoIntent != null) {
                intentList.add(captureVideoIntent);
            }
    
            Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
            chooserIntent.putExtra(Intent.EXTRA_TITLE, getIntent().getStringExtra(EXTRA_TITLE));
    
            chooserIntent.putExtra(Intent.EXTRA_INTENT, intentList.get(0));
            intentList.remove(0);
            if (intentList.size() > 0) {
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Intent[0]));
            }
    
            startActivityForResult(chooserIntent, FILE_CHOOSER_REQUEST_CODE);
        }
    }
    
    private Intent createGetContentIntent() {
        Intent filesIntent = new Intent(Intent.ACTION_GET_CONTENT);
    
        if (getIntent().getBooleanExtra(EXTRA_ALLOW_MULTIPLE_FILES, false)) {
            filesIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        }
    
        String[] acceptTypes = getIntent().getStringArrayExtra(EXTRA_ACCEPT_TYPES);
    
        if (acceptTypes.length == 0 || (acceptTypes.length == 1 && acceptTypes[0].length() == 0)) {
            // empty array or only 1 empty string? -> accept all types
            filesIntent.setType("*/*");
        } else if (acceptTypes.length == 1) {
            filesIntent.setType(acceptTypes[0]);
        } else {
            // acceptTypes.length > 1
            filesIntent.setType("*/*");
            filesIntent.putExtra(Intent.EXTRA_MIME_TYPES, acceptTypes);
        }
    
        return (filesIntent.resolveActivity(getPackageManager()) != null) ? filesIntent : null;
    }
    
    private Intent createCaptureIntent(String type, String fileFormat) {
        Intent captureIntent = new Intent(type);
        if (captureIntent.resolveActivity(getPackageManager()) == null) {
            return null;
        }
    
        // Create the File where the output should go
        Uri captureOutputUri = getTempUri(fileFormat);
        potentialCaptureOutputUris.add(captureOutputUri);
    
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, captureOutputUri);
    
        return captureIntent;
    }
    private File getStorageDirectory() {
        File imageDirectory = new File(this.getExternalFilesDir(null), WEBVIEW_STORAGE_DIRECTORY);
        if (!imageDirectory.isDirectory()) {
            imageDirectory.mkdir();
        }
        return imageDirectory;
    }
    
    
    private Uri getTempUri(String format) {
        String fileName = "CAPTURE-" + simpleDateFormat.format(new Date()) + "." + format;
        File file = new File(getStorageDirectory(), fileName);
        return FileProvider.getUriForFile(
                this, getApplicationContext().getPackageName() + ".generic.provider", file);
    }
    
    private String getFileNameFromUri(Uri uri) {
        Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
        assert returnCursor != null;
        int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        returnCursor.moveToFirst();
        String name = returnCursor.getString(nameIndex);
        returnCursor.close();
        return name;
    }
    
    private Uri copyToLocalUri(Uri uri) {
        File destination = new File(getStorageDirectory(), getFileNameFromUri(uri));
    
        try (InputStream in = getContentResolver().openInputStream(uri);
             OutputStream out = new FileOutputStream(destination)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return FileProvider.getUriForFile(
                    this, getApplicationContext().getPackageName() + ".generic.provider", destination);
        } catch (IOException e) {
            Log.e("WEBVIEW", "Unable to copy selected image", e);
            e.printStackTrace();
            return null;
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
            Intent fileChooserFinishedIntent = new Intent(ACTION_FILE_CHOOSER_FINISHED);
            if (resultCode == Activity.RESULT_OK) {
                if (data != null && (data.getDataString() != null || data.getClipData() != null)) {
                    if (data.getDataString() != null) {
                        // single result from file browser OR video from camera
                        Uri localUri = copyToLocalUri(data.getData());
                        if (localUri != null) {
                            fileChooserFinishedIntent.putExtra(
                                    EXTRA_FILE_URIS, new String[] {localUri.toString()});
                        }
                    } else if (data.getClipData() != null) {
                        // multiple results from file browser
                        int uriCount = data.getClipData().getItemCount();
                        String[] uriStrings = new String[uriCount];
    
                        for (int i = 0; i < uriCount; i++) {
                            Uri localUri = copyToLocalUri(data.getClipData().getItemAt(i).getUri());
                            if (localUri != null) {
                                uriStrings[i] = localUri.toString();
                            }
                        }
                        fileChooserFinishedIntent.putExtra(EXTRA_FILE_URIS, uriStrings);
                    }
                } else {
                    // image result from camera (videos from the camera are handled above, but this if-branch could handle them too if this varies from device to device)
                    for (Uri captureOutputUri : potentialCaptureOutputUris) {
                        try {
                            // just opening an input stream (and closing immediately) to test if the Uri points to a valid file
                            // if it's not a real file, the below catch-clause gets executed and we continue with the next Uri in the loop.
                            getContentResolver().openInputStream(captureOutputUri).close();
                            fileChooserFinishedIntent.putExtra(
                                    EXTRA_FILE_URIS, new String[] {captureOutputUri.toString()});
                            // leave the loop, as only one of the potentialCaptureOutputUris is valid and we just found it
                            break;
                        } catch (IOException ignored) {
                        }
                    }
                }
            }
            sendBroadcast(fileChooserFinishedIntent);
            finish();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
       }
     }
    
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_FILE_CHOOSER_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.ACTION_REQUEST_CAMERA_PERMISSION_FINISHED;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ACCEPT_TYPES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_ALLOW_MULTIPLE_FILES;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_FILE_URIS;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_IMAGE_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_SHOW_VIDEO_OPTION;
    import static io.flutter.plugins.webviewflutter.Constants.EXTRA_TITLE;
    
    import android.Manifest;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.webkit.ValueCallback;
    import androidx.core.content.ContextCompat;
    
    public class FileChooserLauncher extends BroadcastReceiver {
    
    private Context context;
    private String title;
    private boolean allowMultipleFiles;
    private boolean videoAcceptable;
    private boolean imageAcceptable;
    private ValueCallback<Uri[]> filePathCallback;
    private String[] acceptTypes;
    
    public FileChooserLauncher(
            Context context,
            boolean allowMultipleFiles,
            ValueCallback<Uri[]> filePathCallback,
            String[] acceptTypes) {
        this.context = context;
        this.allowMultipleFiles = allowMultipleFiles;
        this.filePathCallback = filePathCallback;
        this.acceptTypes = acceptTypes;
    
        if (acceptTypes.length == 0 || (acceptTypes.length == 1 && acceptTypes[0].length() == 0)) {
            // acceptTypes empty -> accept anything
            imageAcceptable = true;
            videoAcceptable = true;
        } else {
            for (String acceptType : acceptTypes) {
                if (acceptType.startsWith("image/")) {
                    imageAcceptable = true;
                } else if (acceptType.startsWith("video/")) {
                    videoAcceptable = true;
                }
            }
        }
    
        if (imageAcceptable && !videoAcceptable) {
            title = context.getResources().getString(R.string.webview_image_chooser_title);
        } else if (videoAcceptable && !imageAcceptable) {
            title = context.getResources().getString(R.string.webview_video_chooser_title);
        } else {
            title = context.getResources().getString(R.string.webview_file_chooser_title);
        }
    }
    
    private boolean canCameraProduceAcceptableType() {
        return imageAcceptable || videoAcceptable;
    }
    
    private boolean hasCameraPermission() {
        return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED;
    }
    
    public void start() {
        if (!canCameraProduceAcceptableType() || hasCameraPermission()) {
            showFileChooser();
        } else {
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED);
            context.registerReceiver(this, intentFilter);
    
            Intent intent = new Intent(context, RequestCameraPermissionActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }
    
    private void showFileChooser() {
        IntentFilter intentFilter = new IntentFilter(ACTION_FILE_CHOOSER_FINISHED);
        context.registerReceiver(this, intentFilter);
    
        Intent intent = new Intent(context, FileChooserActivity.class);
        intent.putExtra(EXTRA_TITLE, title);
        intent.putExtra(EXTRA_ACCEPT_TYPES, acceptTypes);
        intent.putExtra(EXTRA_SHOW_IMAGE_OPTION, imageAcceptable && hasCameraPermission());
        intent.putExtra(EXTRA_SHOW_VIDEO_OPTION, videoAcceptable && hasCameraPermission());
        intent.putExtra(EXTRA_ALLOW_MULTIPLE_FILES, allowMultipleFiles);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED)) {
            context.unregisterReceiver(this);
            showFileChooser();
        } else if (intent.getAction().equals(ACTION_FILE_CHOOSER_FINISHED)) {
            String[] uriStrings = intent.getStringArrayExtra(EXTRA_FILE_URIS);
            Uri[] result = null;
    
            if (uriStrings != null) {
                int uriStringCount = uriStrings.length;
                result = new Uri[uriStringCount];
    
                for (int i = 0; i < uriStringCount; i++) {
                    result[i] = Uri.parse(uriStrings[i]);
                }
            }
    
            filePathCallback.onReceiveValue(result);
            context.unregisterReceiver(this);
            filePathCallback = null;
        }
      }
     }
    
    @Override
    public boolean onShowFileChooser(
            WebView webView,
            ValueCallback<Uri[]> filePathCallback,
            FileChooserParams fileChooserParams) {
      // info as of 2021-03-08:
      // don't use fileChooserParams.getTitle() as it is (always? on                Mi 9T Pro Android 10 at least) null
      // don't use fileChooserParams.isCaptureEnabled() as it is (always? on Mi 9T Pro Android 10 at least) false, even when the file upload allows images or any file
      final Context context = webView.getContext();
      final boolean allowMultipleFiles = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
              && fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE;
      final String[] acceptTypes = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
              ? fileChooserParams.getAcceptTypes() : new String[0];
      new FileChooserLauncher(context, allowMultipleFiles, filePathCallback, acceptTypes)
              .start();
      return true;
    } }
    
        public class RequestCameraPermissionActivity extends Activity {
    
        private static final int CAMERA_PERMISSION_REQUEST_CODE = 12321;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            ActivityCompat.requestPermissions(
                    this, new String[] {Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
        }
    
        @Override
        public void onRequestPermissionsResult(
                int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
                sendBroadcast(new Intent(ACTION_REQUEST_CAMERA_PERMISSION_FINISHED));
                finish();
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }