欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android网页H5 Input选择相机和系统相册

程序员文章站 2022-06-04 12:19:18
需求: 网页h5的input选择相机和系统相册,并且返回压缩的图片到h5。 代码: 1、webview代码 package com.zql.sdk;...

需求:

网页h5的input选择相机和系统相册,并且返回压缩的图片到h5。

代码:

1、webview代码

package com.zql.sdk;
 
import android.app.activity;
import android.content.context;
import android.content.intent;
import android.content.pm.packagemanager;
import android.net.uri;
import android.os.build;
import android.os.bundle;
import android.support.annotation.requiresapi;
import android.util.log;
import android.view.keyevent;
import android.view.view;
import android.view.window;
import android.webkit.javascriptinterface;
import android.webkit.valuecallback;
import android.webkit.webchromeclient;
import android.webkit.webview;
import android.webkit.webviewclient;
import android.widget.imageview;
import android.widget.textview;
import android.widget.toast;
 
import java.io.ioexception;
 
/**
 * 浏览器组件
 * created by zst on 2018/5/16.
 */
 
public class webviewactivity extends activity implements view.onclicklistener {
  public static final string intent_url = "intent_url";//请求连接
  public static final string intent_params_string = "intent_params_string";//请求参数字符串
  public static final string intent_request_way = "intent_request_way";//请求方式(post/get)
 
  private webview wvshow;
  private textview tv_back_title;
  private textview tv_title;
  private imageview iv_back;
  private textview tv_right;
 
  public valuecallback<uri[]> uploadmessage;
  private valuecallback<uri> muploadmessage;
 
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    requestwindowfeature(window.feature_no_title);//去掉标题栏
    setcontentview(r.layout.activity_web_view);
 
    tv_back_title = (textview) findviewbyid(r.id.tv_back_title);
    tv_title = (textview) findviewbyid(r.id.tv_title);
    iv_back = (imageview) findviewbyid(r.id.iv_back);
    tv_right = (textview) findviewbyid(r.id.tv_right);
 
    iv_back.setonclicklistener(this);
    tv_back_title.setonclicklistener(this);
    tv_right.setonclicklistener(this);
 
    initview();
    initdata();
  }
 
  private void initdata() {
    string intenturl = getintent().getstringextra(intent_url);
    string intentparams = getintent().getstringextra(intent_params_string);
    string intentrequestway = getintent().getstringextra(intent_request_way);
 
    log.e("webview请求", "连接:" + intenturl + "....." + "参数:" + intentparams);
 
    if (intentrequestway.equals("get")) {
      wvshow.loadurl(intenturl + "?" + intentparams);//get请求
    } else if (intentrequestway.equals("post")) {
      wvshow.posturl(intenturl, intentparams.getbytes());//post请求
    } else {
      toast.maketext(webviewactivity.this, "请求方式参数错误", toast.length_short).show();
    }
 
////    wvshow.loadurl("http://qas-gw.baofoo.com/merchant_page?code=6d8950fc495c2a63106ce45d2647e21aec04001b53b3d7aac2f8af3b3d24f84a6c51c92843814b270eb28ead11820178fad5a20a7278f042");//get请求
//
//    string htmldata = "<!doctype html>\n" +
//        "<html>\n" +
//        "<head>\n" +
//        "  <meta charset=\"utf-8\">\n" +
//        "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no\">\n" +
//        "  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n" +
//        "  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n" +
//        "  <title>修改资料</title>\n" +
//        "  <script src=\"./jquery-1.8.3.js\"></script>\n" +
//        "</head>\n" +
//        "\n" +
//        "<body>\n" +
//        "  <div classname=\"image-uploader\">\n" +
//        "  <input id=\"imginput\" classname=\"imginput\" type=\"file\" accept=\"image/*\" />\n" +
//        "  <img id=\"imgshow\" classname=\"imgshow\" />\n" +
//        " </div>\n" +
//        "\n" +
//        "<script> \n" +
//        " $('#imginput').change(function () {\n" +
//        "  readurl(this);\n" +
//        "});\n" +
//        "\n" +
//        "function readurl(input){\n" +
//        " if (input.files && input.files[0]) {\n" +
//        "  const reader = new filereader();\n" +
//        "  reader.readasdataurl(input.files[0]);\n" +
//        "  reader.onload = (e) => {\n" +
//        "    $('#imgshow').attr('src', e.target.result);\n" +
//        "   };\n" +
//        "  };\n" +
//        " };\n" +
//        "</script>\n" +
//        "</body>\n" +
//        "</html>";
//
//    log.e("网页", htmldata);
//
//    wvshow.loaddatawithbaseurl(null, htmldata, "text/html", "utf-8", null);
  }
 
  private void initview() {
    wvshow = (webview) findviewbyid(r.id.wv_body);
    wvshow.getsettings().setjavascriptenabled(true);//允许与js 交互
    wvshow.getsettings().setdefaulttextencodingname("utf-8");//支持中文
    //在js中调用本地java方法
    wvshow.addjavascriptinterface(new jsinterface(this), "androidyzh");
    wvshow.getsettings().setdomstorageenabled(true);//允许缓存、开启dom(双重重定向白屏问题)
    wvshow.setwebviewclient(new webviewclient() {
      //覆盖shouldoverrideurlloading 方法
      @override
      public boolean shouldoverrideurlloading(webview view, string url) {
        if (url == null) return false;
        try {
          if (url.startswith("http:") || url.startswith("https:")) {
            view.loadurl(url);
            return true;
          } else {
            intent intent = new intent(intent.action_view, uri.parse(url));
            startactivity(intent);
            return true;
          }
        } catch (exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的app, 会导致crash)
          return false;
        }
      }
    });
    wvshow.setwebchromeclient(new webchromeclient() {//监听网页加载
      @override
      public void onprogresschanged(webview view, int newprogress) {
//        if (newprogress == 100) {
//          // 网页加载完成
//          pbprogress.setvisibility(view.gone);
//        } else {
//          // 加载中
//          pbprogress.setprogress(newprogress);
//        }
        super.onprogresschanged(view, newprogress);
      }
 
      @override
      public void onreceivedtitle(webview view, string title) {
        super.onreceivedtitle(view, title);
        tv_title.settext(title);
      }
 
      public void openfilechooser(valuecallback<uri> uploadmsg) {
        log.e("点击", "1");
        imgutil.choicephoto(webviewactivity.this);
      }
 
      public void openfilechooser(valuecallback<uri> uploadmsg, string accepttype) {
        openfilechooser(uploadmsg);
        log.e("点击", "3");
      }
 
      public void openfilechooser(valuecallback<uri> uploadmsg, string accepttype, string capture) {
        openfilechooser(uploadmsg);
        log.e("点击", "4");
      }
 
      @requiresapi(api = build.version_codes.lollipop)
      public boolean onshowfilechooser(webview mwebview, valuecallback<uri[]> filepathcallback, webchromeclient.filechooserparams filechooserparams) {
        if (uploadmessage != null) {
          uploadmessage.onreceivevalue(null);
          uploadmessage = null;
        }
        uploadmessage = filepathcallback;
        log.e("点击", "2");
        imgutil.choicephoto(webviewactivity.this);
        return true;
      }
 
    });
 
  }
 
  @override
  public void onclick(view v) {
    int i = v.getid();
    if (i == r.id.iv_back) {
      if (wvshow.cangoback()) {
        wvshow.goback();
      } else {
        finish();
      }
    } else if (i == r.id.tv_back_title) {
      finish();
    }
  }
 
  /**
   * js调用原生方法
   */
  private class jsinterface {
    private context mcontext;
 
    public jsinterface(context context) {
      this.mcontext = context;
    }
 
    @javascriptinterface
    public void closeh5(string name) {//关闭sdk
      log.e("网页", "方法入参:" + name);
 
      finish();
    }
 
    @javascriptinterface
    public void downloadfile(string name) {//下载文件
      log.e("网页", "方法入参:" + name);
 
      //这里是把地址用默认浏览器打开,在浏览器中下载
      uri uri = uri.parse(name);
      intent intent = new intent();
      intent.setaction("android.intent.action.view");
      intent.setdata(uri);
      startactivity(intent);
    }
  }
 
  //重写activity的onkeydown事件,判断当用户按下“返回”按钮,webview返回上一页
  @override
  public boolean onkeydown(int keycode, keyevent event) {
    if ((keycode == keyevent.keycode_back) && wvshow.cangoback()) {
      wvshow.goback();
      return true;
    } else {
      finish();
    }
 
    return super.onkeydown(keycode, event);
  }
 
  @requiresapi(api = build.version_codes.lollipop)
  @override
  protected void onactivityresult(int requestcode, int resultcode, intent intent) {
 
    if (resultcode == result_ok) {//正确返回
      switch (requestcode) {
        case imgutil.take_photo://相机返回
          log.e("返回相机", imgutil.imageuri.tostring());
 
          //相机返回rui
          //uri uritake = imgutil.imageuri;
          uri uritake = null;
          try {
            uritake = imgutil.getcompressuri(webviewactivity.this, imgutil.imageuri);
          } catch (ioexception e) {
            e.printstacktrace();
          }
          //显示在页面
          if (uploadmessage == null) return;
          uri[] imgtaskuris = {uritake};
          uploadmessage.onreceivevalue(imgtaskuris);
          uploadmessage = null;
          if (null == muploadmessage) return;
          uri result = intent == null || resultcode != mainactivity.result_ok ? null : uritake;
          muploadmessage.onreceivevalue(result);
          muploadmessage = null;
 
          break;
        case imgutil.choose_photo://相册返回
          try {
            if (intent != null) {
              //相册返回
              log.e("返回", "intent2:" + intent.getdata().tostring() + "..." + uploadmessage);
              //相册返回uri
              //uri urichoose = intent.getdata();
              uri urichoose = imgutil.getcompressuri(webviewactivity.this, intent.getdata());
              //显示在页面
              if (uploadmessage == null) return;
              uri[] imgchooseuris = {urichoose};
              uploadmessage.onreceivevalue(imgchooseuris);
              //uploadmessage.onreceivevalue(webchromeclient.filechooserparams.parseresult(resultcode, intent));
              uploadmessage = null;
 
              log.e("返回", "intent3:" + webchromeclient.filechooserparams.parseresult(resultcode, intent).tostring());
            }
            break;
          } catch (exception e) {
            e.printstacktrace();
            uiutil.showtoast(this, "图片选择失败");
          }
          break;
      }
    } else {
      uiutil.showtoast(this, "图片选择失败");
    }
  }
 
  @override
  public void onrequestpermissionsresult(int requestcode, string[] permissions, int[] grantresults) {
    switch (requestcode) {
      case imgutil.request_code_album://相册存储权限
        if (grantresults.length > 0 && grantresults[0] == packagemanager.permission_granted) {
          imgutil.openalbum(this);
        } else {
          uiutil.showtoast(this, "选择图库需要同意权限");
        }
        break;
      case imgutil.request_code_camera://相机拍照权限
        if (grantresults[0] == packagemanager.permission_granted) {//允许
          imgutil.opencamera(webviewactivity.this);
        } else {//拒绝
          uiutil.showtoast(this, "只有同意相机权限,才能使用扫码功能");
        }
        break;
      default:
    }
  }
 
}

2、imgutil.java工具类

1)、选择相机方法(选择相机的方法还有额外的代码,具体点击这里)

2)、选择相册方法

3)、压缩图片方法

package com.zql.sdk;
 
import android.manifest;
import android.app.activity;
import android.app.activitymanager;
import android.app.alertdialog;
import android.content.contentresolver;
import android.content.context;
import android.content.dialoginterface;
import android.content.intent;
import android.content.pm.packagemanager;
import android.database.cursor;
import android.graphics.bitmap;
import android.graphics.bitmapfactory;
import android.net.uri;
import android.os.build;
import android.provider.mediastore;
import android.support.annotation.requiresapi;
import android.support.v4.app.activitycompat;
import android.support.v4.content.contextcompat;
import android.support.v4.content.fileprovider;
import android.util.log;
import android.widget.toast;
 
import java.io.bytearrayinputstream;
import java.io.bytearrayoutputstream;
import java.io.file;
import java.io.filenotfoundexception;
import java.io.ioexception;
import java.io.inputstream;
import java.util.arraylist;
import java.util.list;
 
/**
 * 图片工具类
 * created by xiaoshuai on 2018/8/17.
 */
 
public class imgutil {
  public static final int take_photo = 1;//拍照
  public static final int choose_photo = 2;//选择相册
  public static final int request_code_camera = 3;//相机权限请求
  public static final int request_code_album = 4;//相册权限请求
  public static uri imageuri;//相机拍照图片保存地址
 
  /**
   * 选择图片,从图库、相机
   *
   * @param activity 上下文
   */
  public static void choicephoto(final activity activity) {
    //采用的是系统dialog作为选择弹框
    new alertdialog.builder(activity).settitle("上传头像")//设置对话框标题
        .setpositivebutton("拍照", new dialoginterface.onclicklistener() {//添加确定按钮
          @requiresapi(api = build.version_codes.m)
          @override
          public void onclick(dialoginterface dialog, int which) {
 
            arraylist<string> permissions = new arraylist<>();
            if (activity.checkselfpermission(manifest.permission.camera) != packagemanager.permission_granted) {
              permissions.add(manifest.permission.camera);
            }
 
            if (permissions.size() == 0) {//有权限,跳转
              //打开相机-兼容7.0
              imgutil.opencamera(activity);
            } else {
              activity.requestpermissions(permissions.toarray(new string[permissions.size()]), request_code_camera);
            }
//            if (build.version.sdk_int >= 23) {//检查相机权限
//              arraylist<string> permissions = new arraylist<>();
//              if (activity.checkselfpermission(manifest.permission.camera) != packagemanager.permission_granted) {
//                permissions.add(manifest.permission.camera);
//              }
//
//              if (permissions.size() == 0) {//有权限,跳转
//                //打开相机-兼容7.0
//                opencamera(activity);
//              } else {
//                activity.requestpermissions(permissions.toarray(new string[permissions.size()]), request_code_camera);
//              }
//            } else {
//              //打开相机-兼容7.0
//              opencamera(activity);
//            }
          }
        }).
        setnegativebutton("系统相册", new dialoginterface.onclicklistener() {
          @override
          public void onclick(dialoginterface dialog, int which) {
            //如果有权限申请,请在activity中onrequestpermissionsresult权限返回里面重新调用openalbum()
            if (contextcompat.checkselfpermission(activity, manifest.permission.write_external_storage) != packagemanager.permission_granted) {
              activitycompat.requestpermissions(activity, new string[]{manifest.permission.write_external_storage}, request_code_album);
            } else {
              openalbum(activity);
            }
          }
        }).show();//在按键响应事件中显示此对话框
  }
 
  /**
   * 打开相机
   * 兼容7.0
   *
   * @param activity
   */
  public static void opencamera(activity activity) {
    // 创建file对象,用于存储拍照后的图片
    file outputimage = new file(activity.getexternalcachedir(), "output_image.jpg");
    try {
      if (outputimage.exists()) {
        outputimage.delete();
      }
      outputimage.createnewfile();
    } catch (ioexception e) {
      e.printstacktrace();
    }
    if (build.version.sdk_int < 24) {
      imageuri = uri.fromfile(outputimage);
    } else {
      //android 7.0系统开始 使用本地真实的uri路径不安全,使用fileprovider封装共享uri
      //参数二:fileprovider绝对路径 com.dyb.testcamerademo:项目包名
      imageuri = fileprovider.geturiforfile(activity, "com.zql.sdk.fileprovider", outputimage);
    }
    // 启动相机程序
    intent intent = new intent("android.media.action.image_capture");
    intent.putextra(mediastore.extra_output, imageuri);
    activity.startactivityforresult(intent, take_photo);
  }
 
  /**
   * 打开图库
   * @param activity
   */
  public static void openalbum(activity activity) {
    //调用系统图库的意图
    intent choosepicintent = new intent(intent.action_pick, null);
    choosepicintent.setdataandtype(mediastore.images.media.external_content_uri, "image/*");
    activity.startactivityforresult(choosepicintent, choose_photo);
 
    //打开系统默认的软件
    //intent intent = new intent("android.intent.action.get_content");
    //intent.settype("image/*");
    //activity.startactivityforresult(intent, choose_photo); // 打开相册
  }
 
  /**
   * 通过uri获取路径filepath
   * @param context
   * @param uri
   * @return
   */
  public static string getfilepath( final context context, final uri uri ) {
    if ( null == uri ) return null;
 
    final string scheme = uri.getscheme();
    string data = null;
 
    if ( scheme == null )
      data = uri.getpath();
    else if ( contentresolver.scheme_file.equals( scheme ) ) {
      data = uri.getpath();
    } else if ( contentresolver.scheme_content.equals( scheme ) ) {
      cursor cursor = context.getcontentresolver().query( uri, new string[] { mediastore.images.imagecolumns.data }, null, null, null );
      if ( null != cursor ) {
        if ( cursor.movetofirst() ) {
          int index = cursor.getcolumnindex( mediastore.images.imagecolumns.data );
          if ( index > -1 ) {
            data = cursor.getstring( index );
          }
        }
        cursor.close();
      }
    }
    return data;
  }
 
  /**
   * 得到byte[]
   * leancloud上传文件是需要byte[]数组的
   * 这里对传入的图片uri压缩,并转换为byte[]后返回
   *
   * @param activity 上下文
   * @param uri   传入图片的uri
   * @return byte[]
   */
  public static byte[] getimgbytefromuri(activity activity, uri uri) throws ioexception {
    //先进行尺寸压缩
    bitmap bitmap = getbitmapformuri(activity, uri);
 
    //再进行质量压缩
    bytearrayoutputstream out = new bytearrayoutputstream();
    bitmap.compress(bitmap.compressformat.png, 100, out);//100表示不压缩,直接放到out里面
    int options = 90;//压缩比例
    while (out.tobytearray().length / 1024 > 200) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
      out.reset(); // 重置baos即清空baos
      bitmap.compress(bitmap.compressformat.jpeg, options, out);// 这里压缩options%,把压缩后的数据存放到baos中
      options -= 10;// 每次都减少10
    }
    log.e("压缩-提交", out.tobytearray().length + "");
 
    byte[] bs = out.tobytearray();//转换为byte提交
 
    return bs;
  }
 
  public static uri getcompressuri(activity activity, uri uri) throws ioexception {
    //先进行尺寸压缩
    bitmap bitmap = getbitmapformuri(activity, uri);
 
    uri uricompress = uri.parse(mediastore.images.media.insertimage(activity.getcontentresolver(), bitmap, null,null));
 
//    //再进行质量压缩
//    bytearrayoutputstream out = new bytearrayoutputstream();
//    bitmap.compress(bitmap.compressformat.png, 100, out);//100表示不压缩,直接放到out里面
//    int options = 90;//压缩比例
//    while (out.tobytearray().length / 1024 > 200) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
//      out.reset(); // 重置baos即清空baos
//      bitmap.compress(bitmap.compressformat.jpeg, options, out);// 这里压缩options%,把压缩后的数据存放到baos中
//      options -= 10;// 每次都减少10
//    }
//    log.e("压缩-提交", out.tobytearray().length + "");
//
//    byte[] bs = out.tobytearray();//转换为byte提交
 
    return uricompress;
  }
 
 
  /**
   * 图片尺寸压缩
   *
   * 宽度高度不一样:依靠规定的高或宽其一最大值来做界限
   * 高度宽度一样:依照规定的宽度压缩
   *
   * @param uri
   */
  public static bitmap getbitmapformuri(activity ac, uri uri) throws filenotfoundexception, ioexception {
    inputstream input = ac.getcontentresolver().openinputstream(uri);
    bitmapfactory.options onlyboundsoptions = new bitmapfactory.options();
    onlyboundsoptions.injustdecodebounds = true;
    onlyboundsoptions.indither = true;//optional
    onlyboundsoptions.inpreferredconfig = bitmap.config.argb_8888;//optional
    bitmapfactory.decodestream(input, null, onlyboundsoptions);
    input.close();
    int originalwidth = onlyboundsoptions.outwidth;
    int originalheight = onlyboundsoptions.outheight;
    if ((originalwidth == -1) || (originalheight == -1))
      return null;
    //图片分辨率以750x450为标准
    float hh = 800f;//这里设置高度为750f
    float ww = 800f;//这里设置宽度为450f
    float sq = 800f;//这里设置正方形为300f
    //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
    log.e("缩放", originalwidth + "..." + originalheight);
    int be = 1;//be=1表示不缩放
    if (originalwidth > originalheight && originalwidth > ww) {//如果宽度大,根据宽度固定大小缩放
      be = (int) (originalwidth / ww);
    } else if (originalwidth < originalheight && originalheight > hh) {//如果高度高,根据宽度固定大小缩放
      be = (int) (originalheight / hh);
    } else if (originalwidth == originalheight && originalwidth > sq) {//如果高度和宽度一样,根据任意一边大小缩放
      //be = (int) (originalheight / sq);
      be = (int) (originalwidth / sq);
    }
    if (be <= 0) {//如果缩放比比1小,那么保持原图不缩放
      be = 1;
    }
    log.e("缩放", be + "");
    //比例压缩
    bitmapfactory.options bitmapoptions = new bitmapfactory.options();
    bitmapoptions.insamplesize = be;//设置缩放比例
    bitmapoptions.indither = true;//optional
    bitmapoptions.inpreferredconfig = bitmap.config.argb_8888;//optional
    input = ac.getcontentresolver().openinputstream(uri);
    bitmap bitmap = bitmapfactory.decodestream(input, null, bitmapoptions);
    input.close();
 
    return bitmap;//再进行质量压缩
  }
 
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。