H5调用安卓摄像头扫码并把扫码结果返回_h5调用原生android实现扫一扫功能-程序员宅基地

技术标签: webview交互  h5 调android相机  H5调用安卓扫码  js 调用android扫码界面  android 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 + "')"); 把结果传回去了

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pysunwen/article/details/81182582

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签