[英]Android Webview image upload from gallery and camera, camera not working
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.我一直在此处搜索有关此问题的所有相关帖子,但我无法弄清楚为什么从我的相机拍照时图像上传不起作用(在具有 Android 8 的设备上进行测试)。 Gallery upload works fine as expected.图库上传按预期正常工作。
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.在活动结果中,我得到了缓存目录中图像的路径(变量 mCameraPhotoPath),但似乎结果或网站无法访问此文件,或者可能那里有一个空图像文件。
Taking and uploading the image via google chrome directly on the device works, so I think the problem is not on the website side.直接在设备上通过谷歌浏览器拍摄和上传图像是可行的,所以我认为问题不在网站方面。
Here are my permissions这是我的权限
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<!-- for new versions api 21+-->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAMERA2" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
this is my application definition这是我的应用程序定义
<application
android:name="***"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:requestLegacyExternalStorage="true"
android:hardwareAccelerated="true"
android:theme="@style/Theme.Android">
<!-- added fileprovider support -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Then I added an xml folder in the res directory with a file called file_path.xml and added the content然后我在res目录下添加了一个xml文件夹,里面有一个叫file_path.xml的文件,并添加了内容
<paths>
<cache-path
name="mediaimages"
path="./">
</cache-path>
</paths>
And this is my activity code这是我的活动代码
private var mUploadCallbackAboveL: ValueCallback<Array<Uri>>? = null
private var mUploadCallbackBelow: ValueCallback<Uri?>? = 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 = "android"
myWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
myWebView.settings.mixedContentMode = 0
}
}
private fun initChromeWebViewClient() : WebChromeClient {
webChromeViewClient = object : WebChromeClient() {
/**
* API > = 21 (Android 5.0.1) calls back this method
*/
override fun onShowFileChooser(
webView: WebView?,
valueCallback: ValueCallback<Array<Uri>>,
fileChooserParams: FileChooserParams?
): Boolean {
//(1) when the method calls back, it indicates that the version API > = 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, "an error occurred.", Toast.LENGTH_SHORT).show();
}
}
}
Method which creates and starts the chooser Intent创建和启动选择器 Intent 的方法
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 + ".provider"
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, "Image Chooser")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf<Parcelable>(captureIntent))
startActivityForResult(chooserIntent, REQUEST_CODE)
}
@Throws(IOException::class)
private fun createImageFile(): File {
val imageFileName = "JPEG_" + SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
return File(applicationContext.cacheDir.toString() + File.separator + imageFileName + ".jpg")
}
method to handle Android L+ results处理 Android L+ 结果的方法
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<Uri>
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
}
Edit: Updated code to working code up until Android 10, Android 11 does not work.编辑:将代码更新为工作代码直到 Android 10,Android 11 不起作用。 Picture is taken, but not shown in Webviews Input.图片已拍摄,但未显示在 Webviews 输入中。 It seems the Fileprovider approach does not work or something is misconfigured for Android 11.似乎 Fileprovider 方法不起作用或 Android 11 配置错误。
Question was updated with working code.问题已使用工作代码更新。 Now chooser intent allows to select image from gallery or taken by the camera for Android +5 devices.现在选择器意图允许 select 图片来自画廊或由相机为 Android +5 设备拍摄。
Main issue was, that no FileProvider was used and cache directory was not specified correctly in file_paths.xml file.主要问题是,没有使用 FileProvider,并且在 file_paths.xml 文件中没有正确指定缓存目录。
Thanks to @blackapps for help and guiding into the correct direction!感谢@blackapps 的帮助和指导正确的方向!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.