Search code examples
javaandroidandroid-webview

Image Upload Using Web View


Getting an error while trying to upload an image from camera (ACTION_IMAGE_CAPTURE) using a webview. But it's working when I select the image from Files (ACTION_GET_CONTENT).

URL of File trying to upload from ACTION_GET_CONTENT: content://com.android.providers.media.documents/document/image%3A451

URL of File trying to upload from ACTION_IMAGE_CAPTURE: file:/storage/emulated/0/Pictures/JPEG_20220719_162050_5643059705926048051.jpg

For some reason the web view couldn't access the file generated for ACTION_IMAGE_CAPTURE. Should I convert this to a Content URI to make it work?

Here is the code for creating the file for ACTION_IMAGE_CAPTURE:

String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File imageFile = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );
    return imageFile;

Solution

  • By "Getting an error while trying to upload an image from camera (ACTION_IMAGE_CAPTURE) using a webview." might you be asking how to get a photo taken by the device's Camera and then use it on the WebView? If that is the case, find the code below.

    XML Code

     <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    Java Code

    I am making use of View Binding to set my View.

       public class ImageUploadUsingWebView extends AppCompatActivity {
    
        ImageUploadUsingWebviewBinding imageUploadUsingWebviewBinding; //ViewBinder
        String[] PERMISSIONS = {Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA,
        };
        private ValueCallback<Uri[]> fileCallback;
        int IMG_CAPTURE_REQUEST = 1000;
        int FILE_REQUEST = 2000;
        String CAMERA_FILE_PATH, INTENT_PHOTO = "intent_photo";
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            imageUploadUsingWebviewBinding = ImageUploadUsingWebviewBinding.inflate(getLayoutInflater());
            setContentView(imageUploadUsingWebviewBinding.getRoot());
    
            if (!hasPermissions(this, PERMISSIONS)) {
                ActivityCompat.requestPermissions(this, PERMISSIONS, 1);
            }
    
            initWebView(imageUploadUsingWebviewBinding.webView);
    
            imageUploadUsingWebviewBinding.webView.setWebChromeClient(new WebChromeClient() {
                public boolean onShowFileChooser(
                        WebView webView, ValueCallback<Uri[]> valueCallback,
                        WebChromeClient.FileChooserParams fileChooserParams) {
                    if (fileCallback != null) {
                        fileCallback.onReceiveValue(null);
                    }
                    fileCallback = valueCallback;
    
                    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    if (takePhotoIntent.resolveActivity(getPackageManager()) != null) {
                        File photoPath = null;
                        try {
                            photoPath = createImg();
                            takePhotoIntent.putExtra(INTENT_PHOTO, CAMERA_FILE_PATH);
                        } catch (IOException e) {
                            Toast.makeText(ImageUploadUsingWebView.this, e.getMessage(), Toast.LENGTH_LONG).show();
                        }
    
                        if (photoPath != null) {
                            CAMERA_FILE_PATH = "file:" + photoPath.getAbsolutePath();
                            takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                                    Uri.fromFile(photoPath));
                        } else {
                            takePhotoIntent = null;
                        }
                    }
    
                    Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                    contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                    contentSelectionIntent.setType("image/*");
    
                    Intent[] _arryIntent;
                    if (takePhotoIntent != null) {
                        _arryIntent = new Intent[]{takePhotoIntent};
                    } else {
                        _arryIntent = new Intent[0];
                    }
                    Intent makeChoiceIntent = new Intent(Intent.ACTION_CHOOSER);
                    makeChoiceIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                    makeChoiceIntent.putExtra(Intent.EXTRA_TITLE, "Choose Camera");
                    makeChoiceIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, _arryIntent);
                    startActivityForResult(makeChoiceIntent, FILE_REQUEST);
    
                    return true;
                }
            });
            if (imageUploadUsingWebviewBinding.webView.getUrl() == null) {
                imageUploadUsingWebviewBinding.webView.loadUrl("file:///android_asset/test.html");
            }
    
        }
    
        private void initWebView(WebView webView) {
            WebSettings webSettings = webView.getSettings();
            webSettings.setUseWideViewPort(true);
            webSettings.setJavaScriptEnabled(true);
            webSettings.setBuiltInZoomControls(true);
            webSettings.setLoadWithOverviewMode(true);
            webView.setWebViewClient(new WebViewClient());
        }
    
    
    
        private File createImg() throws IOException {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_mmss").format(new Date());
            String imageFileName = "TEST_PHOTO" + timeStamp + "-";
            File storageDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES);
            File imageFile = File.createTempFile(
                    imageFileName,
                    ".jpg",
                    storageDir
            );
            return imageFile;
        }
    
        public static boolean hasPermissions(Context context, String... permissions) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
                for (String permission : permissions) {
                    if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                        return false;
                    }
                }
            }
            return true;
        }
    
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                Uri[] onActivityResult = null;
                onActivityResult = new Uri[]{Uri.parse(CAMERA_FILE_PATH)};
                fileCallback.onReceiveValue(onActivityResult);
                fileCallback = null;
                Toast.makeText(ImageUploadUsingWebView.this, "Image picked from camera sucessfully", Toast.LENGTH_LONG).show();
            }
        }
    }
    

    HTML Code

        <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Test</title>
    </head>
    
    <body>
    <input type="file" id="files" class="hidden"/>
    <label for="files">Get photo from camera</label>
    </body>
    </html>
    

    The html file is in the assets folder

    enter image description here

    Regards