项目需求讨论 - WebView下拍照及图片选择功能

前言:

若是以为掘金上看图片放大看不清楚,能够跳到另外的同步发布的连接看,放大图片下部有个能够查看原图功能,很清楚:项目需求讨论 - WebView下拍照及图片选择功能html

如今不少app里面,都会有这么一个需求,就是上传图片的按钮,固然按了这个按钮以后,就会出现二种选择: 1. 直接拍照,2. 相册选择现有图片。android

由于如今的app这块功能会有二个大的状况:web

  1. 所有原生的 app 来实现。
  2. HyBrid 的 app 来实现。

本文先讨论HyBrid的app的实现状况,下次再讨论原生,不过其实大部分实现都是类似的。bash

其实这种在WebView配合下实现这类功能的文章不少不少,可是大多数都是上传一大段代码,而后让你们本身看,千篇一概,因此本文主要是写的完整的思路。服务器

正文:

咱们知道用户会在网页上点击了某个按钮,而后调用起安卓方面的相关操做。而后实现完整的功能。app

1. 网页端:

其实网页端很简单,只须要实现一个简单的<input>标签便可。async

整体思路是一个<input>标签和一个<img>标签重叠在一块儿(<input>在上,<img>在下,相似能够理解<img>做为背景),当选完照片后,最后把图片赋值给<img>标签。ide

可是在给<img>赋值的时候我遇到过不一样的状况:ui

  1. 当在Android这边拍照或者进入图库选完照片后,把图片信息给了网页端后,<input>标签的onchange监听到了图片选择好了,网页端直接把图片上传到服务器并传回来一个地址,显示时把地址拼接成能够找到路径的地址放在<img>标签中就能够了。this

  2. 配合FileReader,FileReader是做为文件API的重要成员用于读取文件。能够参考: h5 实现调用系统拍照或者选择照片并预览

2. Android端:

2.1 WebChromeClient

由于Android端访问网页大部分使用的是WebView,因此咱们这里仍是用WebView来讲明。

既然用户在网页上点击了<input>,咱们确定须要WebView能监听到,比如原生的Button点击咱们要监听也要写一个OnclickListener来实现监听。咱们这里使用的是WebChromeClient

public class ImgWebChromeClient extends WebChromeClient {
        
      //.......
      //.......
        
     public ImgWebChromeClient(Activity activity) {
         this.activity = activity;
     }

        
        
}
复制代码

咱们实现咱们的类,继承WebChromeClient。而后咱们就能够把这个咱们本身定义的WebChromeClient设置给咱们的WebView。

webView.setWebChromeClient(new ImgWebChromeClient(this));
复制代码

咱们能够看到咱们在WebChromeClient在监听<input>点击事件的时候,还要根据不一样的版原本区分,主要是以Android 5.0版原本进行大的划分。

  1. Android 5.0及以上版本:

  2. Android 5.0如下版本:

都是openFileChooser方法,不一样版本的里面参数不一样。

因此咱们能够看到主要是openFileChooseronShowFileChooser方法。

// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> valueCallback) {
            ***
}

// For Android  >= 3.0
public void openFileChooser(ValueCallback valueCallback, String acceptType) {
            ***
}

//For Android  >= 4.1
public void openFileChooser(ValueCallback<Uri> valueCallback, 
                String acceptType, String capture) {
            ***
}

// For Android >= 5.0
@Override
public boolean onShowFileChooser(WebView webView, 
                ValueCallback<Uri[]> filePathCallback, 
                WebChromeClient.FileChooserParams fileChooserParams) {
            ***
     return true;
}
复制代码

不论是什么版本,咱们看到这几个方法的参数里面都有ValueCallback参数。

/**
 * A callback interface used to provide values asynchronously.
 */
public interface ValueCallback<T> {
    /**
     * Invoked when the value is available.
     * @param value The value.
     */
    public void onReceiveValue(T value);
};
复制代码

因此咱们知道了,咱们最后是调用openFileChooseronShowFileChooser方法里面的ValueCallback参数,调用它的onReceiveValue方法把咱们的选择的图片的Uri传入,网页端那边就会收到信息了,就知道用户到底选择了什么图片。

因此咱们最终目标就是获取选择的图片的Uri,而后给ValueCallback.onReceiveValue方法,这就是咱们整个文章的最主要的流程。

2.2 获取相关图片的Uri

上面咱们提到了,咱们最终目标是获取用户选取的图片Uri,而后传给ValueCallback就能够。 因此咱们这里就要讲二大块:

  1. 用户怎么跳到本身想要的界面(相机 or 图库)
  2. 用户在本身想要的界面选择好了图片后 (拍好了照片 or 在图库选择好了图片),如何获取相关图片的Uri

根据这二点,咱们一步步来分析。

2.2.1 相机 or 图库

咱们确定想到是用户点击了某个按钮后,咱们须要跳出一个弹框,而后上面有拍照和图库按钮: 好比我使用系统自带的选择框(不一样手机显示的弹框不一样):

因此咱们这里知道了这个又要细分任务:

  1. 获取相关权限
  2. 如何点击按钮后能够跳到相应界面(拍照 or 图库)。
  3. 如何建立弹框,把上面的按钮显示在上面
2.2.1.1 获取相关权限

emmm......这块我以为应该不须要花更多的时间来讲明了吧,主要就是:

  1. 检查权限 (checkSelfPermission)
  2. 请求权限(requestPermissions)
  3. 回调事件处理(onRequestPermissionsResult)

而咱们要申请的权限无非就是 Camera的权限,还有读写外部存储的权限。

2.2.1.2 如何点击按钮后能够跳到相应界面(拍照 or 图库):

咱们先来看拍照:

2.2.1.2.1 设置打开相机Intent的Action

咱们知道打开某个界面,就是startActivity(Intent);日常好比跳到拨号界面等。只要对Intent设定相应的Action便可。 具体咱们能够看谷歌的Android官方教程网页便可:

Android指南 - 通用 Intent

咱们能够看到有这些:

咱们能够这个目录中看到了相机,咱们具体看相机的介绍:

:当您使用 ACTION_IMAGE_CAPTURE拍摄照片时,相机可能还会在结果 Intent 中返回缩小尺寸的照片副本(缩略图),这个副本以 Bitmap 形式保存在名为 dataextra 字段中。

因此咱们这里跳到拍照界面也是同样,只要创建跳到相机界面的Intent便可:

Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
复制代码
2.2.1.2.2 设置相机拍摄的照片的存储位置

由于有些人须要在本身的APP中调用拍照的功能,存在本身指定的目录下面,因此须要在startActivity启动相机界面时候同时传递过去信息,告诉拍照了以后照片存的位置。

1.咱们先指定咱们的要存储的照片的路径Uri:

其实很简单,设定咱们接下去要拍的照片的完整存储路径,而后获得File对象,再经过Uri.fromFile方法再经过刚才咱们的File对象来得到Uri

(固然若是这里你只须要打开系统相机,如下第二部分能够忽略)

2.获取全部相机的Intent集合:

由于咱们手机上面可能有不少个相机软件,因此咱们须要先找到能打开各自相机软件的Intent,咱们经过PackageManager.queryIntentActivities的方式来进行符合拍照Action的Intent的软件,而后获得它们具体的详细信息,好比包名及对应的activity名字等,而后把相应的Intent变得更加详细便可。

3.把uri赋值给Intent:

在上面贴出的Android 官方网页上面的相机部分其实也提到过了如何设置存储位置:

因此这里咱们只须要找到相应的Intent,而后把咱们的Uri位置赋值给Intent便可:

intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
复制代码

最后只须要startActivity去启动咱们这个指定了打开相机的特定Intent便可。


拍照说完了,咱们再来看在图库界面选择图片: 其实整体思路和拍照是如出一辙,无非就是指定Intent是打开了图库的Intent。

仍是在刚才的Android 官网咱们能够看到:

由于咱们是查看本地的图片,因此咱们要使用 ACTION_GET_CONTENT,同时指定MIME类型是图片类型,若是要进行图片多选,就再指定EXTRA_ALLOW_MULTIPLEtrue

同时也给出了实例代码:

这里我要提一下,咱们在设置IntentAction的时候不仅是可使用ACTION_GET_CONTENT,还可使用ACTION_PICK

咱们能够看到上面写着能够用来选择数据,而后返回被选中的选项。

可是在具体手机操做上有点不一样(不知道不一样的手机系统会不会结果不一样,我只测了模拟器):

ps:最坑的是用ACTION_GET_CONTEN时候多选图片要长按操做,一直觉得没成功,觉得多选图片功能没实现,后来在 Android: Intent.EXTRA_ALLOW_MULTIPLE allows only single picking 上面找到别人的答案,说须要长按

2.2.2 出现选择框让用户选择

咱们能够看到能够自定义弹框,好比咱们设定固定的按钮,而后再点击特定按钮后启动咱们的上面提过的特定的Intent便可。

这里咱们讲若是只是给定咱们想要启动的多个Intent的选项,让系统帮咱们弹出弹框及相关按钮,关键字就是Intent.createChooser方法

直接看图片便可,写的很详细了,或者你们搜相关的关键字也是有不少文章的。好比:Android createChooser方法源码简析等。

2.2.3 获取用户在相机或者图库选择的图片Uri

由于咱们不是单纯的跳到了相机界面或者是图库界面就能够了,咱们还须要获取用户在那些应用外的界面到底选了什么图片,因此单纯的 startActivity确定不够,因此你们确定想到了使用 startActivityForResult来启动,这样才能根据用户不一样的操做来进行相应的处理。

咱们知道须要复写onActivityResult来处理,主要也就三个参数(int requestCode, int resultCode, Intent data)。具体的内容图片里面也写的很清楚。


2.3 Uri 和 ValueCallback

因此咱们ValueCallback实例在 WebChromeClient的方法里面拿到了,Uri也经过相机或者图库的选择下获取到了。最终调用把获取的Uri 赋值给ValueCallback.onReceiveValue()便可。

PS: 取消此次网页点击选取图片的请求,只须要调用onReceiveValue(null)便可。

结语:

emm.......你们轻喷便可。。。。

相关文章
相关标签/搜索