H5调用安卓摄像头扫码并把扫码结果返回

最近公司又双叒叕有需求了,之前接入的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 + "')"); 把结果传回去了

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值