需求:
网页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;//再进行质量压缩 } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持找一找教程网。