1、首先说下 我现在从事的是一家p2p公司,在日常的开发以及接入存管的过程中发现的一些问题,然后归总写了一个通用类。
前提大概是这样的,接下来也不多说什么,先上代码,后面再慢慢解释。
public class WebViewActivity extends HeadMenuActivity {
private static final String TAG = WebViewActivity.class.getSimpleName();
private Context context = WebViewActivity.this;
private ProgressWebView wv;
private String serviceName = "";
private boolean isFlag = false;
private MyWebchromeClient webchromeClient;
public static final int REQUEST_SELECT_FILE_CODE = 100;
private static final int REQUEST_FILE_CHOOSER_CODE = 101;
private static final int REQUEST_FILE_CAMERA_CODE = 102;
// 默认图片压缩大小(单位:K)
public static final int IMAGE_COMPRESS_SIZE_DEFAULT = 400;
// 压缩图片最小高度
public static final int COMPRESS_MIN_HEIGHT = 900;
// 压缩图片最小宽度
public static final int COMPRESS_MIN_WIDTH = 675;
private ValueCallback<Uri> mUploadMsg;
private ValueCallback<Uri[]> mUploadMsgs;
// 相机拍照返回的图片文件
private File mFileFromCamera;
private File mTakePhotoFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.web_view_new_layout);
setHeadTitleName(getIntent().getStringExtra("title"));
String url = null;
url = getIntent().getStringExtra("url");
wv = (ProgressWebView) findViewById(R.id.wb);
wv.getSettings().setDefaultTextEncodingName("UTF-8");
// wv.loadData(url == null ? "" : url, "text/html", "UTF-8");
wv.loadUrl(url);
wv.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
// 返回值是true的时候控pri
// 制去WebView打开,为false调用系统浏览器或第三方浏览器
if (url.startsWith("http:") || url.startsWith("https:")) {
view.loadUrl(url);
return false;
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed(); // 接受所有网站的证书
}
@Override
public void onLoadResource(WebView view, String url) {//判断是否成功
super.onLoadResource(view, url);
if (url.contains("serviceName=")) {
serviceName = ......;
}
if (url.contains("status=0")) {
isFlag = true;
}
}
});
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setSupportZoom(true);
// 设置出现缩放工具
settings.setDisplayZoomControls(false);
settings.setBuiltInZoomControls(true);
//扩大比例的缩放
settings.setUseWideViewPort(true);
//自适应屏幕
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
settings.setLoadWithOverviewMode(true);
wv.addJavascriptInterface(new Back(), "Android");
findViewById(R.id.headBackBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isFlag) {
//TODO 需要加上授权操作
callbackOperation();
}
finish();
}
});
webchromeClient = new MyWebchromeClient();
wv.setWebChromeClient(webchromeClient);
setOpenFileChooserCallBack(new MyWebchromeClient.OpenFileChooserCallBack() {
@Override
public void openFileChooserCallBack(ValueCallback<Uri> uploadMsg, String acceptType) {
mUploadMsg = uploadMsg;
featureSelection(0, null);
}
@Override
public void showFileChooserCallBack(ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (mUploadMsgs != null) {
mUploadMsgs.onReceiveValue(null);
}
mUploadMsgs = filePathCallback;
}
});
}
private void callbackOperation() {
if (serviceName.equals("***")) {
EventBus.getDefault().post(new EventObject(EventConstant.Account, null));
}
}
//h5调用原生关闭界面方法
class Back {
@JavascriptInterface
public void back(String msg) {
if (serviceName.equals("")) {
serviceName = msg;
}
callbackOperation();
finish();
}
}
public void onResume() {
super.onResume();
}
public void onPause() {
super.onPause();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
// if (keyCode == KeyEvent.KEYCODE_BACK) {
// if (wv.canGoBack()) {
// wv.goBack();// 返回上一页面
// return true;
// } else {
// finish();
// }
// }
if (isFlag) {
callbackOperation();
}
return super.onKeyDown(keyCode, event);
}
public void setOpenFileChooserCallBack(MyWebchromeClient.OpenFileChooserCallBack callBack) {
webchromeClient.setOpenFileChooserCallBack(callBack);
}
//选择拍照还是系统相册
private void featureSelection(final int tag, final WebChromeClient.FileChooserParams fileChooserParams) {
View inflate = View.inflate(this, R.layout.photo_to_choose, null);
final PopupWindow window = new PopupWindow(inflate, RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
window.setBackgroundDrawable(new BitmapDrawable());
window.setOutsideTouchable(true);
window.setFocusable(true);
window.setAnimationStyle(R.style.popupAnimationLong);
window.showAtLocation(inflate, Gravity.BOTTOM, 0, 0);
MyUtils.backgroundAlpha(WebViewLoadDataActivity.this, 0.5f);
TextView cancle = (TextView) inflate.findViewById(R.id.tv_cancle);
TextView photoAlbumChoose = (TextView) inflate.findViewById(R.id.photo_album_choose);
TextView takingPictures = (TextView) inflate.findViewById(R.id.taking_pictures);
photoAlbumChoose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(WebViewLoadDataActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(WebViewLoadDataActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
} else {
//调用相册
if (tag == 0) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
startActivityForResult(Intent.createChooser(i, "File Browser"), REQUEST_FILE_CHOOSER_CODE);
} else {
try {
Intent intent = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
intent = fileChooserParams.createIntent();
}
startActivityForResult(intent, REQUEST_SELECT_FILE_CODE);
} catch (ActivityNotFoundException e) {
mUploadMsgs = null;
}
}
}
window.dismiss();
}
});
takingPictures.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(WebViewLoadDataActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(WebViewLoadDataActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 100);
} else {
//调用相机
takeCameraPhoto();
}
window.dismiss();
}
});
cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
window.dismiss();
}
});
window.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
MyUtils.backgroundAlpha(WebViewLoadDataActivity.this, 1f);
}
});
}
public void takeCameraPhoto() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
Toast.makeText(this, "设备无摄像头", Toast.LENGTH_SHORT).show();
return;
}
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mFileFromCamera = new File(filePath, System.nanoTime() + ".jpg");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTakePhotoFile));
startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE);
} else {
try {
mTakePhotoFile = File.createTempFile("Zp" + System.nanoTime(), ".jpg", new File(filePath));
Uri contentUri = FileProvider.getUriForFile(this,
"your package name.FileProvider", mTakePhotoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE);
} catch (IOException e) {
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_SELECT_FILE_CODE:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mUploadMsgs == null) {
return;
}
mUploadMsgs.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
mUploadMsgs = null;
}
break;
case REQUEST_FILE_CHOOSER_CODE:
if (mUploadMsg == null) {
return;
}
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
mUploadMsg.onReceiveValue(result);
mUploadMsg = null;
break;
case REQUEST_FILE_CAMERA_CODE:
takePictureFromCamera();
break;
}
}
/**
* 处理相机返回的图片
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void takePictureFromCamera() {
if (mFileFromCamera != null && mFileFromCamera.exists()) {
String filePath = mFileFromCamera.getAbsolutePath();
// 压缩图片到指定大小
File imgFile = CameraUtils.compressImage(this, filePath, COMPRESS_MIN_WIDTH, COMPRESS_MIN_HEIGHT, IMAGE_COMPRESS_SIZE_DEFAULT);
Uri localUri = Uri.fromFile(imgFile);
Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri);
this.sendBroadcast(localIntent);
Uri result = Uri.fromFile(imgFile);
if (mUploadMsg != null) {
mUploadMsg.onReceiveValue(Uri.parse(filePath));
mUploadMsg = null;
}
if (mUploadMsgs != null) {
mUploadMsgs.onReceiveValue(new Uri[]{result});
mUploadMsgs = null;
}
} else {
if (mUploadMsg != null) {
mUploadMsg.onReceiveValue(null);
mUploadMsg = null;
}
if (mUploadMsgs != null) {
mUploadMsgs.onReceiveValue(null);
mUploadMsgs = null;
}
}
}
}
这就是完整的代码了,后面逐个解释一下。
2、我开始慢慢解释了,当然注释部分已经标明每一块的用途了,能看懂了完全不需要看下面解释。
为了应对不同的场景 列出两种不同的加载方式
1)加载表单:wv.loadData(url == null ? "" : url, "text/html", "UTF-8");
2)加载Url:wv.loadUrl(url);
我当时碰到的需求中需要我对回调的url进行字段的截取,于是就用到了以下方法
@Override
public void onLoadResource(WebView view, String url) {//判断是否成功
super.onLoadResource(view, url);
if (url.contains("serviceName=")) {
serviceName = ... ...;
}
if (url.contains("status=0")) {
isFlag = true;
}
}
onLoadResource这是对url的监听方法,可以获取h5中所用到的url。
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
// 是否读取缓存
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setSupportZoom(true);
// 设置出现缩放工具
settings.setDisplayZoomControls(false);
settings.setBuiltInZoomControls(true);
//扩大比例的缩放
settings.setUseWideViewPort(true);
//自适应屏幕
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
settings.setLoadWithOverviewMode(true);
一些webview的配置,不清楚的可以百度一下。
在完整的代码中也许大家可以看到有一些对相机或者相册的代码段。
在调用别人的h5页面时,可能会碰到需要你上传图片但是这个h5又不是你自己公司写的,外部提供的 你也无法让其进行配置,只能自己去提供适用他们的功能。
设置setWebChromeClient ,setOpenFileChooserCallBack对其做监听 判断其到底是调用相机还是相册,这里再加上我设置的WebChromeClient部分代码,以供大家参考
public class MyWebchromeClient extends WebChromeClient {
private OpenFileChooserCallBack mOpenFileChooserCallBack;
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
//For Android 3.0 - 4.0
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
if (mOpenFileChooserCallBack != null) {
mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType);
}
}
// For Android 4.0 - 5.0
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
// For Android > 5.0
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (mOpenFileChooserCallBack != null) {
mOpenFileChooserCallBack.showFileChooserCallBack(filePathCallback, fileChooserParams);
}
return true;
}
public void setOpenFileChooserCallBack(OpenFileChooserCallBack callBack) {
mOpenFileChooserCallBack = callBack;
}
public interface OpenFileChooserCallBack {
void openFileChooserCallBack(ValueCallback<Uri> uploadMsg, String acceptType);
void showFileChooserCallBack(ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams);
}
后续的是调用系统相册与相机的代码,以及回调和对图片进行压缩,不能直接采用系统图片或者照片,一般我们拍照或者相册中所存储的照片比较大,不适用于app 需要进行压缩才行,这里我只贴出方法名 ,代码请上翻
featureSelection() takeCameraPhoto() takePictureFromCamera()
onActivityResult()根据requestCode做出不同的操作判断
正常的按键返回一般是如此
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (wv.canGoBack()) {
wv.goBack();// 返回上一页面
return true;
} else {
finish();
}
}
不过我这里因为不想要返回上一页,直接采用的是finish,而且我这里还要调用直接的一些方法
EventBus.getDefault().post(new EventObject(EventConstant.Account, null));
我采用的是eventbus去进行通知,当然也可以采用别的方法,方法很多,可以根据自己的需求来。
在我的需求里还需要跟h5做一些交互,点击h5的按钮调用原生方法
wv.addJavascriptInterface(new Back(), "Android");//Back为自定义类名
class Back {
@JavascriptInterface
public void back(String msg) {
//写你所想要的一些操作
}
}
最后再提一个点
Uri contentUri = FileProvider.getUriForFile(this, "***.FileProvider", mTakePhotoFile);
这里的FileProvider是你在AndroidManifest中定义的,一般是包名.FileProvider
别写错了
基本上我认为所有要注意的地方都提供了,代码可以直接copy来用
3、博客新生 写的可能有点乱,还望包含,如果能帮助到你,很开心。
如果有什么问题的话,可以在下面留言
本文详细介绍了一个通用的WebViewActivity类的实现,包括加载网页、处理URL回调、与H5交互、图片上传、相机与相册调用及图片压缩等功能。通过代码示例和详细解释,帮助开发者快速理解和应用。

4323

被折叠的 条评论
为什么被折叠?



