因项目需要对接第三方提供的页面,使用到webview遇到的一些问题,记录以作查询。
第一个需求是h5调起手机相机拍照,提供的文档资料是
Android: kh.openCamera(index) //kh为类名(建议Android端建一个kh类)
webview要想和h5的js进行交互首先要设置
/** webView相关属性的设置 */ webSettings= webView.getSettings(); webSettings.setJavaScriptEnabled(true);
然后调用addJavascriptInterface方法来回调接口
webView.addJavascriptInterface(new JsInteration (),"kh");//h5网页唤起相机拍照 public class JsInteration { @JavascriptInterface public void openCamera(int i) { photoType=i; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { requestPermissions( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, CODE_FOR_WRITE_PERMISSION); return; } else { openCamare(); } } else { openCamare(); } } @JavascriptInterface public void backApp(boolean isGo){ if (isGo){ finish(); }else{ webView.loadUrl("javascript:history.go(-1)"); } } }图片上传成功后需要再将如偏路径返回给h5String call = "javascript:getImgUrl("+photoType+",\""+url+"\")"; webView.loadUrl(call);这里注意一点是如果是字符串,要加\"括起来;最后完成时 发现页面加载完成后不加载js,试过n种办法后 发现只要加webSettings.setDomStorageEnabled(true);就可以了。。虽然还没明白为啥附录完整代码package shenzhen.com.cn.company; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.util.Base64; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.jph.takephoto.app.TakePhoto; import com.jph.takephoto.app.TakePhotoActivity; import com.jph.takephoto.compress.CompressConfig; import com.jph.takephoto.model.LubanOptions; import com.jph.takephoto.model.TResult; import org.json.JSONObject; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import me.shaohui.advancedluban.Luban; import shenzhen.com.cn.R; import shenzhen.com.cn.common.http.BaseCallBack; import shenzhen.com.cn.common.http.HttpNet; import shenzhen.com.cn.common.http.HttpUrlConstants; import shenzhen.com.cn.common.util.SharedPreferencesKeeper; import shenzhen.com.cn.common.util.ToastDialog; import shenzhen.com.cn.common.view.CustomProgressDlg; public class CashLoanActivity extends TakePhotoActivity { /** 顶部返回按钮 */ private Button comm_top_bar_left_btn; /** 顶部中间标题 */ private TextView comm_top_bar_mid_text; /** Called when the activity is first created. */ private WebView webView; private int flag=0; protected CustomProgressDlg dialog; private Activity context; private int photoType=0;//0:身份证正面照1:身份证背面照2:持身份证自拍照 private String tit_back=""; private WebSettings webSettings; @SuppressLint("SetJavaScriptEnabled") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.about_us); context=this; comm_top_bar_left_btn = (Button) findViewById(R.id.comm_top_bar_left_btn); comm_top_bar_left_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (tit_back.equals("借款")||tit_back.equals("还款")||tit_back.equals("个人中心")){ finish(); }else{ if (webView.canGoBack()){ webView.goBack(); }else{ finish(); } } } }); comm_top_bar_mid_text = (TextView) findViewById(R.id.comm_top_bar_mid_text); webView = (WebView) findViewById(R.id.mainWebView); /** webView相关属性的设置 */ webSettings= webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); // webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) // KITKAT { webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } String url=""; comm_top_bar_mid_text.setText(getIntent().getStringExtra("title")); url=getIntent().getStringExtra("url"); webView.addJavascriptInterface(new JsInteration (),"kh"); webView.setWebChromeClient(new WebChromeClient(){ @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); tit_back=webView.getTitle(); comm_top_bar_mid_text.setText(webView.getTitle()); } }); webView.setWebViewClient(new MyCustomWebViewClient()); webView.loadUrl(url); } @Override protected void onDestroy() { super.onDestroy(); if (dialog != null){ dialog.dismiss(); dialog = null; } } //h5网页唤起相机拍照 public class JsInteration { @JavascriptInterface public void openCamera(int i) { photoType=i; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { requestPermissions( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, CODE_FOR_WRITE_PERMISSION); return; } else { openCamare(); } } else { openCamare(); } } @JavascriptInterface public void backApp(boolean isGo){ if (isGo){ finish(); }else{ webView.loadUrl("javascript:history.go(-1)"); } } } private static int CODE_FOR_WRITE_PERMISSION=1; @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode==CODE_FOR_WRITE_PERMISSION){ if (permissions[0].equals(Manifest.permission.CAMERA)) { //成功,开启摄像头 openCamare(); } else { //授权失败 ToastDialog.showToast(this,"请打开相机权限和存储权限"); } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } TakePhoto takePhoto; private void openCamare(){ File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); final Uri imageUri = Uri.fromFile(file); takePhoto = getTakePhoto(); // CompressConfig compressConfig=new CompressConfig.Builder().setMaxSize(1024*1024).create(); LubanOptions option=new LubanOptions.Builder() .setGear(Luban.CUSTOM_GEAR) .setMaxHeight(1000) .setMaxWidth(1000) .setMaxSize(1024*1024) .create(); CompressConfig config=CompressConfig.ofLuban(option); takePhoto.onEnableCompress(config,false); takePhoto.onPickFromCapture(imageUri); } private class MyCustomWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("tel")){ Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_DIAL, uri); startActivity(intent); }else{ view.loadUrl(url); } return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); showProgressDialog(context,""); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // comm_top_bar_mid_text.setText(view.getTitle()); hideProgressDialog(); } public void onReceivedError(WebView view, int errorCode,String description, String failingUrl) { hideProgressDialog(); Toast.makeText(CashLoanActivity.this, "抱歉, 加载失败" + description,Toast.LENGTH_SHORT).show(); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){ if (tit_back.equals("借款")||tit_back.equals("还款")||tit_back.equals("个人中心")){ finish(); }else{ if (webView.canGoBack()){ webView.goBack(); }else{ finish(); } } return true; } return super.onKeyDown(keyCode, event); } @Override public void takeCancel() { super.takeCancel(); runOnUiThread(new Runnable() { @Override public void run() { webView.loadUrl("javascript:shutCamera()"); } }); } @Override public void takeSuccess(TResult result) { super.takeSuccess(result); if (result!=null &&result.getImages()!=null&&result.getImages().size()>0) { String path=result.getImages().get(0).getPath(); File file = new File(path); try { InputStream filin= new FileInputStream(file); update(filin); } catch (FileNotFoundException e) { e.printStackTrace(); } } } @Override public void takeFail(TResult result, String msg) { super.takeFail(result, msg); ToastDialog.showToast(context, "图片选择失败,请重试"); } private void update(final InputStream is) { String url= HttpUrlConstants.URL_210; HashMap<String,String> param=new HashMap<>(); param.put("outerId", SharedPreferencesKeeper.readInfomation(context,2)); // param.put("channelId","123"); param.put("photoUrl",fileToBase64(is)); param.put("photoType",photoType+""); HttpNet.doHttpRequestWithType(HttpNet.POST, url, param, new BaseCallBack() { @Override public void success(Object data) { runOnUiThread(new Runnable() { @Override public void run() { webView.loadUrl("javascript:shutCamera()"); } }); try { JSONObject obj=new JSONObject(data.toString()); if (obj.getInt("code")==0){ String url=obj.getString("data"); String call = "javascript:getImgUrl("+photoType+",\""+url+"\")"; webView.loadUrl(call); } }catch (Exception e){ e.printStackTrace(); } } @Override public void failed(Object data) { runOnUiThread(new Runnable() { @Override public void run() { webView.loadUrl("javascript:shutCamera()"); } }); String call = "javascript:getImgUrl("+photoType+")"; webView.loadUrl(call); // showToastMsg("图片上传失败,请重试"); } }); } //将输入流转换成字符串 public static String fileToBase64(InputStream in) { String base64 = null; try { byte[] bytes = new byte[in.available()]; int length = in.read(bytes); base64 = Base64.encodeToString(bytes, 0, length, Base64.DEFAULT); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (in != null) { in.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return base64; } /** * 显示进度框 * @param msg 进度框文本提示 */ protected void showProgressDialog(Context context, String msg){ if (dialog == null) { dialog = new CustomProgressDlg(context, R.style.MyDialog, msg); } if (null != dialog && !dialog.isShowing()) { try { dialog.show(); } catch (Exception e) { e.printStackTrace(); } } } /** * 隐藏进度提示框 */ public void hideProgressDialog(){ if (null != dialog && dialog.isShowing()) { try { dialog.dismiss(); dialog = null; } catch (Exception e) { e.printStackTrace(); } } } }