title: Android Webview image upload from gallery and camera, camera not working
body: <p>I have been searching all related posts here regarding this problem, but I cannot figure out, why the image upload does not work (testing on device with Android 8), when taking a picture from my camera. Gallery upload works fine as expected.</p>
  <p>In the activity result i get a path to the image in the cache directory (variable mCameraPhotoPath), but it seems that the result or the website cannot access this file or maybe there is an empty image file in there.</p>
  <p>Taking and uploading the image via google chrome directly on the device works, so I think the problem is not on the website side.</p>
  <p>Here are my permissions</p>
  <pre><code>&lt;uses-feature android:name=&quot;android.hardware.camera&quot;/&gt;
  &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;
  &lt;uses-permission android:name=&quot;android.permission.CAMERA&quot;/&gt;
  &lt;!-- for new versions api 21+--&gt;
  &lt;uses-permission
      android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;
      android:maxSdkVersion=&quot;18&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.WRITE_INTERNAL_STORAGE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.READ_INTERNAL_STORAGE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.CAMERA&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.CAMERA2&quot; /&gt;
  &lt;uses-permission android:name=&quot;android.permission.RECORD_AUDIO&quot; /&gt;
  </code></pre>
  <p>this is my application definition</p>
  <pre><code> &lt;application
      android:name=&quot;***&quot;
      android:allowBackup=&quot;true&quot;
      android:icon=&quot;@mipmap/ic_launcher&quot;
      android:label=&quot;@string/app_name&quot;
      android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
      android:supportsRtl=&quot;true&quot;
      android:requestLegacyExternalStorage=&quot;true&quot;
      android:hardwareAccelerated=&quot;true&quot;
      android:theme=&quot;@style/Theme.Android&quot;&gt;
  
      &lt;!-- added fileprovider support --&gt;
      &lt;provider
          android:name=&quot;androidx.core.content.FileProvider&quot;
          android:authorities=&quot;${applicationId}.provider&quot;
          android:exported=&quot;false&quot;
          android:grantUriPermissions=&quot;true&quot;&gt;
          &lt;meta-data
              android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
              android:resource=&quot;@xml/file_paths&quot; /&gt;
      &lt;/provider&gt;
  </code></pre>
  <p>Then I added an xml folder in the res directory with a file called file_path.xml and added the content</p>
  <pre><code>&lt;paths&gt;
    &lt;cache-path
      name=&quot;mediaimages&quot;
      path=&quot;./&quot;&gt;
    &lt;/cache-path&gt;
  &lt;/paths&gt;
  </code></pre>
  <p>And this is my activity code</p>
  <pre><code>private var mUploadCallbackAboveL: ValueCallback&lt;Array&lt;Uri&gt;&gt;? = null
  private var mUploadCallbackBelow: ValueCallback&lt;Uri?&gt;? = null
  private var imageUri: Uri? = null
  
  override fun onCreate(savedInstanceState: Bundle?) {   
    super.onCreate(savedInstanceState)
    // webview definition 
    myWebView.webChromeClient = initChromeWebViewClient()
    myWebView.webViewClient = initWebViewClient()
    myWebView.settings.javaScriptEnabled = true
    myWebView.settings.domStorageEnabled = true
    myWebView.settings.allowFileAccess = true
    myWebView.settings.allowContentAccess = true
    myWebView.settings.supportZoom()
    myWebView.visibility = View.INVISIBLE
    myWebView.settings.userAgentString = &quot;android&quot;
    myWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
  
    if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP) {
        myWebView.settings.mixedContentMode = 0
    }
  }
  
  private fun initChromeWebViewClient() : WebChromeClient {
      webChromeViewClient = object : WebChromeClient() {
          /**
           * API &gt; = 21 (Android 5.0.1) calls back this method
           */
          override fun onShowFileChooser(
              webView: WebView?,
              valueCallback: ValueCallback&lt;Array&lt;Uri&gt;&gt;,
              fileChooserParams: FileChooserParams?
          ): Boolean {
              //(1) when the method calls back, it indicates that the version API &gt; = 21. In this case, assign the result to muploadcallbackabovel to make it! = null
              mUploadCallbackAboveL = valueCallback
              takePhoto()
              return true
          }
      }
      return webChromeViewClient
  }
  
  @Override
  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
      super.onActivityResult(requestCode, resultCode, data)
      if (requestCode == REQUEST_CODE) {
          val file: File = File(imageUri!!.toString())
          val file_size = (file.length() / 1024).toString().toInt()
          //After the above two assignment operations (1) and (2), we can decide which processing method to adopt according to whether its value is empty
          if (mUploadCallbackBelow != null) {
              chooseBelow(resultCode, data);
          } else if (mUploadCallbackAboveL != null) {
              chooseAbove(resultCode, data);
          } else {
              Toast.makeText (this, &quot;an error occurred.&quot;, Toast.LENGTH_SHORT).show();
          }
      }
  }
  </code></pre>
  <p>Method which creates and starts the chooser Intent</p>
  <pre><code>private fun takePhoto() {
      //Adjust the camera in a way that specifies the storage location for taking pictures
      var photoFile : File? = null
      val authorities : String = applicationContext.packageName + &quot;.provider&quot;
      try {
          photoFile = createImageFile()
          imageUri = FileProvider.getUriForFile(this, authorities, photoFile)
      } catch(e: IOException) {
          e.printStackTrace()
      }
  
      val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
      captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
      val Photo = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
      val chooserIntent = Intent.createChooser(Photo, &quot;Image Chooser&quot;)
      chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf&lt;Parcelable&gt;(captureIntent))
      startActivityForResult(chooserIntent, REQUEST_CODE)
  }
  
  @Throws(IOException::class)
    private fun createImageFile(): File {
      val imageFileName = &quot;JPEG_&quot; + SimpleDateFormat(&quot;yyyyMMdd_HHmmss&quot;).format(Date())
      return File(applicationContext.cacheDir.toString() + File.separator + imageFileName + &quot;.jpg&quot;)
  }
  </code></pre>
  <p>method to handle Android L+ results</p>
  <pre><code>private fun chooseAbove(resultCode : Int, data : Intent?) {
      if (RESULT_OK == resultCode) {
          updatePhotos()
  
          if (data != null) {
              //Here is the processing of selecting pictures from a file
              val results : Array&lt;Uri&gt;
              val uriData : Uri? = data.data
              if (uriData != null) {
                  results = arrayOf(uriData)
                  mUploadCallbackAboveL!!.onReceiveValue(results)
              } else {
                  mUploadCallbackAboveL!!.onReceiveValue(null)
              }
          } else {
              if (imageUri != null) {
                  mUploadCallbackAboveL!!.onReceiveValue(arrayOf(imageUri!!))
              }
          }
      } else {
          mUploadCallbackAboveL!!.onReceiveValue(null)
      }
      mUploadCallbackAboveL = null
  }
  </code></pre>
  <p>Edit:
  Updated code to working code up until Android 10, Android 11 does not work. Picture is taken, but not shown in Webviews Input.
  It seems the Fileprovider approach does not work or something is misconfigured for Android 11.</p>