1

I have a webkit in the app that opens a webpage where the user is able to upload a picture from his phone or take a photo and upload it.

This code was working well until Android 10, 11 or new one, Android 12.

HTML CODE:

<form id="form1" enctype="multipart/form-data" action="/index.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="20000000">
<input type="file" id="img1" name="img1" accept=".jpeg,.jpg,.png">
<input type="submit" name="config-update" id="btn-update" value="Update">

In Android side:

Manifest:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

WebkitActivity.java:

public void onActivityResult(int requestCode, int resultCode, Intent data) {

    disablegoBackWeb=false;

    if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
        super.onActivityResult(requestCode, resultCode, data);
        return;
    }
    Uri[] results = null;
    // Check that the response is a good one
    //if (resultCode == Activity.RESULT_OK) {

    //------------------------------------------
    //para camara fotografica
    if (data==null){ //&& data.getExtras() == null ) {
        // If there is not data, then we may have taken a photo
        if (mCameraPhotoPath != null) {
            results = new Uri[]{Uri.parse(mCameraPhotoPath)};

        }
        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;

        return;
    }
    
    else {
        String dataString = data.getDataString();
        if (dataString != null) {
            results = new Uri[]{Uri.parse(dataString)};
        }
        else{
            results = new Uri[]{fileUri};
        }
    }
    //}
    mFilePathCallback.onReceiveValue(results);
    mFilePathCallback = null;

    return;
}

public File createImageFile(){
    try {
        File file = createImage();
        fileUri = FileProvider.getUriForFile(WebActivity.this, getPackageName() + ".provider", file);

        return file;
    }
    catch (Exception e){
        return null;
    }
}

public File createImage() throws IOException {

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "xxxx_" + timeStamp + "_";
    //File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    File storageDirectory = getExternalFilesDir(Environment.DIRECTORY_PICTURES);

    File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
    return image;
}









public class ChromeClient extends WebChromeClient {

    //https://developer.android.com/training/data-storage/shared/media
    // For Android 5.0
    public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {

        //para que no cierre al aparecer fotos..
        disablegoBackWeb=true;

        // Double check that we don't have any existing callbacks
        if (mFilePathCallback != null) {
            mFilePathCallback.onReceiveValue(null);
        }

        mFilePathCallback = filePath;
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
                takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
            } catch (Exception ex) {
                // Error occurred while creating the File
                Log.e(TAG, "Unable to create Image File", ex);
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(photoFile));
            } else {
                takePictureIntent = null;
            }
        }
        Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
        contentSelectionIntent.setType("image/*");
        Intent[] intentArray;
        if (takePictureIntent != null) {
            intentArray = new Intent[]{takePictureIntent};
        } else {
            intentArray = new Intent[0];
        }
        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
        chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
        startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
        return true;
    }
    // openFileChooser for Android 3.0+
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
        //para que no cierre al aparecer fotos..
        disablegoBackWeb=true;

        mUploadMessage = uploadMsg;
        // Create AndroidExampleFolder at sdcard
        // Create AndroidExampleFolder at sdcard
        File imageStorageDir = new File(
                Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_PICTURES)
                , "AndroidExampleFolder");
        if (!imageStorageDir.exists()) {
            // Create AndroidExampleFolder at sdcard
            imageStorageDir.mkdirs();
        }
        // Create camera captured image file path and name
        File file = new File(
                imageStorageDir + File.separator + "IMG_"
                        + String.valueOf(System.currentTimeMillis())
                        + ".jpg");
        mCapturedImageURI = Uri.fromFile(file);
        // Camera capture image intent
        final Intent captureIntent = new Intent(
                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        // Create file chooser intent
        Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
        // Set camera intent to file chooser
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
                , new Parcelable[] { captureIntent });
        // On select image call onActivityResult method of activity
        startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
    }
    // openFileChooser for Android < 3.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        openFileChooser(uploadMsg, "");
    }
    //openFileChooser for other Android versions
    public void openFileChooser(ValueCallback<Uri> uploadMsg,
                                String acceptType,
                                String capture) {
        openFileChooser(uploadMsg, acceptType);
    }


}

As I read, for Android 10 and above, there is no solution to access to READ_EXTERNAL_STORAGE, so how I can save the picture taken from the camera and send it?

If I debug the code, no errors are shown, also, the path to the file created seems correct, and no Exception is raised, but it seems that the OS prevents to write from the file created. (With a real Android phone I can see the file created with 0b)

Is there a solution?

Thanks.

Kotik_o
  • 295
  • 6
  • 19
  • This answers your question? https://stackoverflow.com/questions/57116335/environment-getexternalstoragedirectory-deprecated-in-api-level-29-java – Sujal Kumar Jan 22 '22 at 12:09
  • Also, I strongly using the new way instead of the deprecated startActivityForResult(). Although, it's not related to the question. – Sujal Kumar Jan 22 '22 at 12:12
  • I tried but with API 30 it doesn't work.. I don't know how to deal with targetSdkVersion 31, webview and upload a live picture. – Kotik_o Jan 25 '22 at 08:21
  • you may try this https://stackoverflow.com/a/42067744/5794116 – Umar Ata Jan 25 '22 at 13:19
  • if (! imageStorageDir.mkdirs()) return; You blindly continue without checking. – blackapps Jan 26 '22 at 20:00
  • `mCapturedImageURI = Uri.fromFile(file);` You should use FileProvider to create an uri for your file. – blackapps Jan 26 '22 at 20:01
  • `(With a real Android phone I can see the file created with 0b)` Yes. 0B you mean. But that has nothing to do with using a camera intent. Your app creates the file already with `photoFile = createImageFile();`. You should not create a file already. You only need a File instance with that path. – blackapps Jan 26 '22 at 20:04
  • `new Intent(MediaStore.ACTION_IMAGE_CAPTURE)` You have that twice in your code. Confusing. To which one go the complaints? – blackapps Jan 26 '22 at 20:07
  • Facing the same issue, @Kotik_o do you find any way to solve this? – WoAiNii Dec 12 '22 at 21:52

0 Answers0