file-uploadandroid-camerawebview-flutter

How to open file picker from gallery or camera android in webview_flutter?


I´m currently working on a project based on php and javascript where, within its functions, it requires uploading an image through an input, which works perfectly from the browser. Encapsulating the web application in an android app, I use flutter as a framework, through the webview_flutter plugin in version 3.0.0. It does not allow to open the camera or the android image gallery.

At the end, i need your valuable support, what kind of method is required or recommend for javascript to open the intent and display the camera or gallery?

Thanks to all!!!

Here´re my dependencies on my pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  camera:
  path_provider:
  path:
  image_picker: ^0.8.2
  flutter_webview_plugin: ^0.3.10+1

this´s my default config Android in build.gradle:

defaultConfig {
    // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
    applicationId "com.jlcornejo.iaconlink"
    minSdkVersion 21
    targetSdkVersion 30
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName

here´re my imports too:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:myapp/service/audio_service_mp3.dart';
import 'package:record_mp3/record_mp3.dart';
import 'webview/webview_channel_controller.dart';

my methods in main.dart:

/// selecciona la imagen desde la galería
Future<void> _pickImage(ImageSource source) async {
  File selected = await ImagePicker.pickImage(source: source);

  setState(() {
    _imageFile = selected;
  });

  print("close");
  if (_imageFile == null) {
    print("close in");
    flutterWebViewPlugin.show();
  }
}

/// Remueve la imagen
void _clear() {
  setState(() => _imageFile = null);
}
/// Sube la imagen
void _startUpload() {
  File file = _imageFile;
  if (file == null) return;
  String base64Image = base64Encode(file.readAsBytesSync());
  String fileName = file.path.split("/").last;

  http.post(phpEndPoint, body: {
    "image": base64Image,
    "name": fileName,
  }).then((res) {
    print(res.statusCode);
    print(fileName);
    Navigator.of(context).pop(null);
    flutterWebViewPlugin.show();
  }).catchError((err) {
    print(err);
  });
}

Solution

  • I've managed to get the HTML ordinary file upload (input type=file) to work with the plugin webview_flutter_pro - https://pub.dev/packages/flutter_webview_pro. (According to the documentation the ordinary webview_flutter do not currently support the file upload in HTML).

    First follow the basic instructions to get the webview in place.

    Then I had to do the following changes:

    In my App/src/main/androidManifest.xlm I added the following:

     <application>
             <provider
                        android:name="androidx.core.content.FileProvider"
                        android:authorities="${applicationId}.fileprovider"
                        android:exported="false"
                        android:grantUriPermissions="true"
                        tools:replace="android:authorities">
                        <meta-data
                            android:name="android.support.FILE_PROVIDER_PATHS"
                            android:resource="@xml/provider_paths"
                            tools:replace="android:resource" />
                    </provider>             
         </application>
    
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.CAMERA"/>
    

    IMPORTANT NOTE: Add xmlns:tools="http://schemas.android.com/tools" to the manifest to make it work.

    Then I added the file app/src/main/res/xml/provider_paths.xml with the following content:

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

    After these changes both the choose from gallery and take photo worked when the file input was used.