最近公司又双叒叕有需求了,之前接入的H5界面需要和原生交互,说白了就是H5调用android原生扫码界面,并把扫码结果传过去,现在功能写完了简单的总结一下,有类似功能的童鞋可以参考一下,老规矩,先看效果图 :
1.通过 JavascriptInterface 方式扫码:
2.通url拦截方式扫码:
本人也是安卓新手,技术水平和文采能力有限,如果觉得有什么不妥的地方多多交流,
码字不易,转载说明出处:https://blog.csdn.net/pysunwen/article/details/81182582
代码部分:
首先就是项目里面需要集成Zxing扫码类库,可以在Github上集成官方的,也可以集成一些第三方的,第三方的比较简单,基本添加一行依赖,再初始化一下就可以了,很简单的,我这里是直接从项目里拷贝的类库,然后import Module 就可以了,这里不详细介绍
MainActivity
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
//webView支持JS
settings.setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/test.html");
webView.addJavascriptInterface(this,"android");//"android" 和h5要一致
setWebViewClient();
}
/**
* WebViewClient
*/
private void setWebViewClient() {
webView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//通过url拦截进行跳转
if (url != null && url.contains("doscan")){
Intent intent = new Intent(MainActivity.this,MyScanActivity.class);
startActivityForResult(intent, 666);
return true;
} else {
return false;
}
}
});
}
/**
* 注解方法 注意:doScan()一定要和h5里面的 android.doScan();方法一致
*/
@JavascriptInterface
public void doScan(){
Intent intent = new Intent(this,MyScanActivity.class);
startActivityForResult(intent,666);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode ==666 && null !=data){
String result = data.getStringExtra("result").trim();
//setScanResult(result) 方法就是调用H5里面的有参方法,注意方法名要一致
webView.loadUrl("javascript:setScanResult('" + result + "')");
}
}
}
这个主界面一打开就加载本地的test.html 文件,放在assers 目录下,H5里面就两个button ,和一个展示扫码结果的div标签,h5不懂也没关系,主要和前段约定好一些方法名和参数名就可以了
-
@JavascriptInterface
这种方法在4.2之前是有漏洞的,4.2之后为了补掉漏洞提供了
@JavascriptInterface
对象注解的方式建立Javascript对象和android原生对象的绑定,提供给JavaScript调用的方法必须带有@JavascriptInterface
。
这个方法就是暴露给JavaScript调用的,方法里面可以做一些操作:比如界面跳转,打开相机,拨打电话等等操作,比较注意的是一定记得家注解:@JavascriptInterface 然后注意的是WebView 调用webView.addJavascriptInterface(this,"android");方法如下:
webView.addJavascriptInterface(this,"android");
//java方法
@JavascriptInterface
public void doScan(){
Intent intent = new Intent(this,MyScanActivity.class);
startActivityForResult(intent,666);
}
//js方法
document.getElementById("butten1").onclick = function(){
android.doScan();
};
-
url拦截
这个方法也比较简单,就是js点击触发一个事件,按钮指向一个地址,android在webView的setWebViewClient 里面重写
shouldOverrideUrlLoading 这个方法,事先和前端约定好关键字,如果地址里面包含"xxx" 就做一些本地的操作如下:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//通过url拦截进行跳转
if (url != null && url.contains("doscan")){
Intent intent = new Intent(MainActivity.this,MyScanActivity.class);
startActivityForResult(intent, 666);
return true;
} else {
return false;
}
}
activity_main.xml 里面仅仅一个webview没啥好说的
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="dahuatech.bocai.com.webscan.MainActivity">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
</RelativeLayout>
test.html 就两个button 和一个div标签用于展示结果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<button id="butten1" style="width:200px;height:30px;margin-bottom: 20px;">通过注解方式调用安卓扫码</button>
<br/>
<a href="doscan:androidscan" ><input type="button" value="通过url拦截方式调用安卓扫码" style="width:200px;height:30px;"></a>
<br/>
<div id="text"></div>
</body>
<script type="text/javascript">
document.getElementById("butten1").onclick = function(){
<!--调用安卓原生方法-->
android.doScan();
};
var text = document.getElementById("text");
<!--安卓调用js有参方法,参数就是扫码结果-->
function setScanResult(result){
text.innerHTML = "扫码结果:"+result;
};
</script>
</html>
这里是我直接用的项目里面的库,当然你也可以直接用github封装好的库,比我自定义更方便,我这里直接用项目里现成的,就不用地方的了,下面是自定的扫码界面:
MyScanActivity
public class MyScanActivity extends CaptureActivity implements View.OnClickListener {
private ImageView ivOpenlight;
private LinearLayout ll_openlight;
private TextView tvOpenlight;
private boolean isLightOpen = true;
private ImageView ivBack;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_scan);
initEvent();
}
private void initEvent() {
ivBack = findViewById(R.id.iv_back);
ivOpenlight = findViewById(R.id.iv_openlight);
ll_openlight = findViewById(R.id.ll_openlight);
tvOpenlight = findViewById(R.id.tv_openlight);
ll_openlight.setOnClickListener(this);
ivBack.setOnClickListener(this);
}
@Override
public int layoutID() {
return R.layout.activity_my_scan;
}
@Override
public int surfaceViewID() {
return R.id.preview_view;
}
@Override
public int viewFindViewID() {
return R.id.viewfinder_view;
}
@Override
public void handleQrContent(String qrContent) {
String qrContent1 = qrContent;
ivOpenlight.setImageResource(R.mipmap.iv_light_closed);
tvOpenlight.setText("打开闪光灯");
isLightOpen = false;
super.onPause();
super.onDestroy();
super.onResume();
//扫码完成直接关闭当前Act,并把结果带过去
Intent intent = new Intent();
intent.putExtra("result", qrContent);
setResult(666, intent);
finish();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ll_openlight:
if (isLightOpen) {
if (cameraManager != null) {
ivOpenlight.setImageResource(R.mipmap.iv_light_closed);
tvOpenlight.setText("打开闪光灯");
cameraManager.offLight();
isLightOpen = false;
}
} else {
if (cameraManager != null) {
ivOpenlight.setImageResource(R.mipmap.iv_light_open);
tvOpenlight.setText("关闭闪光灯");
cameraManager.openLight();
isLightOpen = true;
}
}
break;
case R.id.iv_back:
finish();
break;
}
}
}
activity_myscan.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:wang="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_scan_h5"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="dahuatech.bocai.com.webscan.MyScanActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/preview_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#44000000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="扫一扫"
android:textColor="#ffffff"
android:textSize="16dp" />
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:src="@mipmap/pic_back" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.wang.zxinglibrary.zXing.ViewfinderView
android:id="@+id/viewfinder_view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
wang:angleLength="30dp"
wang:angleWidth="3dp"
wang:borderColor="@color/viewfinder_laser"
wang:hint=""
wang:hintPaddingTop="20dp"
wang:hintTextColor="@color/viewfinder_laser"
wang:hintTextSize="16sp"
wang:lineColor="@color/viewfinder_laser"
wang:mastColor="@color/viewfinder_laser" />
<LinearLayout
android:id="@+id/ll_openlight"
android:layout_width="wrap_content"
android:layout_height="37dp"
android:layout_marginTop="80dp"
android:background="@drawable/shape_scanh5">
<ImageView
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:id="@+id/iv_openlight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/iv_light_open" />
<TextView
android:id="@+id/tv_openlight"
android:textSize="15dp"
android:paddingRight="15dp"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭闪光灯"
android:textColor="#ffffff" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
最后扫码结束后在onActivityResult方法里面调用webView.loadUrl("javascript:setScanResult('" + result + "')"); 把结果传回去了