权限必须打开 相册,相机 、 文件。
在使用 Android 的 WebView 进行拍照并通过上传功能时,可能会遇到一些问题,特别是涉及到拍照后图片的选取和上传。以下是一些步骤和技巧,可以帮助你解决在 WebView 中拍照无法上传的问题:
- 确保权限
首先,确保你的应用已经请求了必要的权限。在 AndroidManifest.xml 中添加以下权限:
java
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
并创建一个 res/xml/provider_paths.xml 文件:
java
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path
name="root"
path="." />
<files-path
name="files"
path="." />
<cache-path
name="cache"
path="." />
<external-path
name="external"
path="." />
<!-- <external-files-path-->
<!-- name="external_file_path"-->
<!-- path="." />-->
<external-cache-path
name="external_cache_path"
path="." />
<external-files-path
name="download"
path="/Download"
/>
</paths>
java
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class ZhiHuiWebActivity extends AppCompatActivity {
WebView web;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zhihui_web);
Button fanhui_button = findViewById(R.id.fanhui_button);
// GeckoView
fanhui_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
web = findViewById(R.id.web);
WebSettings webSettings = web.getSettings();
webSettings.setJavaScriptEnabled(true); // 支持 JS 交互
webSettings.setDomStorageEnabled(true); // 允许访问本地存储
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//缩放操作
webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDefaultTextEncodingName("UTF-8");
webSettings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true
webSettings.setAllowFileAccess(true); // 是否可访问本地文件,默认值 true
// 是否允许通过file url加载的Javascript读取本地文件,默认值 false
webSettings.setAllowFileAccessFromFileURLs(false);
// 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false
webSettings.setAllowUniversalAccessFromFileURLs(false);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
//开启JavaScript支持
webSettings.setJavaScriptEnabled(true);
// 支持缩放
webSettings.setSupportZoom(true);
web.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
FileChooserParams fileChooserParams1 = fileChooserParams;
mfilePathCallback = filePathCallback;
takePhoto();
return true;
}
}
);
web.loadUrl(ZhiHuiTiYu_phoneActivity.school_url);
web.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 在这里拦截URL,并决定是否在当前WebView中加载
view.loadUrl(url); // 在WebView内部加载URL
return true; // 返回true表示此URL已被处理,不再由默认浏览器打开
}
});
if( (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(ZhiHuiWebActivity.this, new String[]
{
android.Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
}
}
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> mfilePathCallback;
private Uri imageUri; //图片地址
/**
* 调用相机/相册选择窗
*/
private void takePhoto() {
String filePath = Environment.getExternalStorageDirectory()
+ File.separator
+ Environment.DIRECTORY_PICTURES + File.separator;
String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
imageUri = Uri.fromFile(new File(filePath + fileName));
if(Build.VERSION.SDK_INT>=24){
imageUri = FileProvider.getUriForFile(ZhiHuiWebActivity.this,getPackageName()+".fileprovider",new File(filePath + fileName));
}else {
imageUri = Uri.fromFile(new File(filePath + fileName));
}
//相册相机选择窗
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
Intent Photo = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(Photo, "chooseCame_pic");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
startActivityForResult(chooserIntent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
chooseCame_pic(resultCode, data);
}
/**
* Android API >= 21(Android 5.0) 版本的回调处理
*/
public void chooseCame_pic(int resultCode, Intent data) {
Log.e("chooseCame_pic", "调用方法 chooseCame_pic " + data);
if (Activity.RESULT_OK == resultCode) {
//发送广播进行更新相册
// 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(imageUri);
sendBroadcast(intent);
if (data != null) {
// 这里是针对从文件中选图片的处理
Uri[] results;
Uri uriData = data.getData();
if (uriData != null) {
results = new Uri[]{uriData};
for (Uri uri : results) {
Log.e("chooseCame_pic", "系统里取到的图片:" + uri.toString());
}
mfilePathCallback.onReceiveValue(results);
} else {
mfilePathCallback.onReceiveValue(null);
}
} else {
Log.e("chooseCame_pic", "自己命名的图片:" + imageUri.toString());
mfilePathCallback.onReceiveValue(new Uri[]{imageUri});
}
} else {
mfilePathCallback.onReceiveValue(null);
}
mfilePathCallback = null;
}
@Override
protected void onDestroy() {
super.onDestroy();
web.destroy();
}
}
java
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center_horizontal"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@color/colorF2F5F7"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<Button
android:id="@+id/fanhui_button"
android:textAllCaps="false"
android:layout_width="70dp"
android:layout_height="28dp"
android:layout_marginLeft="20dp"
android:background="@android:color/transparent"
android:paddingLeft="2dp"
android:paddingRight="17dp"
android:text="string/return2"
android:textColor="@color/color9AA6B9" />
</RelativeLayout>
<WebView
android:id="@+id/web"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
</LinearLayout>