总所周知,二维码非常普及,android当中我们一般做二维码扫一扫功能大部分用的是zxing库,但是zxing的库demo中没有实现本地相册二维码功能,小编今天拿出来说一下哈哈。

首先我们先导入zxing库,可在build的dependencies里添加 implementation ‘com.google.zxing:core:3.3.1’

             // 通过激活系统图库,选择一张图片Intent innerIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");startActivityForResult(wrapperIntent, IMAGE_CODE);

//我们可以通过这行几行代码进入系统相册选择一张图片然后在onActivityResult里获取数据

但是这里有个小的细节要注意一下:

我们要确保有存储权限之后,这个获取二维码的功能才能正常使用,所有我们应该这样写:

private final int IMAGE_CODE = 0;   //这里的IMAGE_CODE是自己任意定义的
/
//跳转相册
private void onJumpPictures(){PackageManager pm = getPackageManager();boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, getPackageName()));//判断有没有android.permission.WRITE_EXTERNAL_STORAGE权限if (permission) {//如果有权限则激活系统相册// 激活系统图库,选择一张图片Intent innerIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");startActivityForResult(wrapperIntent, IMAGE_CODE);return;}else {//请求存储权限displayFrameworkBugMessageAndExit();}}//打开权限申请框private void displayFrameworkBugMessageAndExit() {AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle(getString(R.string.app_name));builder.setMessage("存储权限未开启");builder.setPositiveButton("我的"), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();showInstalledAppDetails(getApplicationContext(), getPackageName());}});builder.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {dialog.dismiss();}});builder.show();}/*** 调用系统InstalledAppDetails界面显示已安装应用程序的详细信息。* 对于Android 2.3(Api Level9)以上,使用SDK提供的接口; 2.3以下,使用非公开的接口(查看InstalledAppDetails源码)。** @param context* @param packageName 应用程序的包名*/public static void showInstalledAppDetails(Context context, String packageName) {Intent intent = new Intent();final int apiLevel = Build.VERSION.SDK_INT;if (apiLevel >= 9) { // 2.3(ApiLevel 9)以上,使用SDK提供的接口intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);Uri uri = Uri.fromParts(SCHEME, packageName, null);intent.setData(uri);} else { // 2.3以下,使用非公开的接口(查看InstalledAppDetails源码)// 2.2和2.1中,InstalledAppDetails使用的APP_PKG_NAME不同。final String appPkgName = (apiLevel == 8 ? APP_PKG_NAME_22: APP_PKG_NAME_21);intent.setAction(Intent.ACTION_VIEW);intent.setClassName(APP_DETAILS_PACKAGE_NAME,APP_DETAILS_CLASS_NAME);intent.putExtra(appPkgName, packageName);}intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}//用户从相册选择图片之后的回调@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != RESULT_OK) {        //此处的 RESULT_OK 是系统自定义得一个常量return;} else {//此处的用于判断接收的Activity是不是你想要的那个//这说明是用户点击了图片返回到的app界面if (requestCode == IMAGE_CODE) {Result result = null;try {String[] proj = {MediaStore.Images.Media.DATA};// 获取选中图片的路径//                外界的程序访问ContentProvider所提供数据 可以通过ContentResolver接口Cursor cursor = getContentResolver().query(data.getData(),proj, null, null, null);if (cursor.moveToFirst()) {int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);path = cursor.getString(column_index);if (path == null) {path = Utils.getPath(getApplicationContext(),data.getData());}}cursor.close();result = scanningImage(path);if (result == null) {Log.i(TAG,"未识别到二维码");} else {Log.i(TAG,"识别到的二维码" + result.toString());}} catch (Exception e) {Log.i(TAG,"报错信息");}}}}}// TODO: 解析部分图片protected Result scanningImage(String path) {Bitmap scanBitmap;if (TextUtils.isEmpty(path)) {return null;}// DecodeHintType 和EncodeHintTypeHashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true; // 先获取原大小scanBitmap = BitmapFactory.decodeFile(path, options);options.inJustDecodeBounds = false; // 获取新的大小int sampleSize = (int) (options.outHeight / (float) 200);if (sampleSize <= 0)sampleSize = 1;options.inSampleSize = sampleSize;scanBitmap = BitmapFactory.decodeFile(path, options);if (scanBitmap == null) {return null;}// --------------测试的解析方法---PlanarYUVLuminanceSource-这几行代码对project没作功----------LuminanceSource source1 = new PlanarYUVLuminanceSource(rgb2YUV(scanBitmap), scanBitmap.getWidth(),scanBitmap.getHeight(), 0, 0, scanBitmap.getWidth(),scanBitmap.getHeight());BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source1));MultiFormatReader reader1 = new MultiFormatReader();Result result1;try {result1 = reader1.decode(binaryBitmap);String content = result1.getText();Log.i("123content", content);} catch (NotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}// ----------------------------RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap);BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));QRCodeReader reader = new QRCodeReader();try {return reader.decode(bitmap1, hints);} catch (NotFoundException e) {e.printStackTrace();} catch (ChecksumException e) {e.printStackTrace();} catch (FormatException e) {e.printStackTrace();}return null;}/*** 中文乱码* <p>* 暂时解决大部分的中文乱码 但是还有部分的乱码无法解决 .** @return*/private String recode(String str) {String formart = "";try {boolean ISO = Charset.forName("ISO-8859-1").newEncoder().canEncode(str);if (ISO) {formart = new String(str.getBytes("ISO-8859-1"), "GB2312");Log.i("1234      ISO8859-1", formart);} else {formart = str;Log.i("1234      stringExtra", str);}} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return formart;}/*** //TODO: TAOTAO 将bitmap由RGB转换为YUV //TOOD: 研究中** @param bitmap 转换的图形* @return YUV数据*/public byte[] rgb2YUV(Bitmap bitmap) {// 该方法来自QQ空间int width = bitmap.getWidth();int height = bitmap.getHeight();int[] pixels = new int[width * height];bitmap.getPixels(pixels, 0, width, 0, 0, width, height);int len = width * height;byte[] yuv = new byte[len * 3 / 2];int y, u, v;for (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {int rgb = pixels[i * width + j] & 0x00FFFFFF;int r = rgb & 0xFF;int g = (rgb >> 8) & 0xFF;int b = (rgb >> 16) & 0xFF;y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;y = y < 16 ? 16 : (y > 255 ? 255 : y);u = u < 0 ? 0 : (u > 255 ? 255 : u);v = v < 0 ? 0 : (v > 255 ? 255 : v);yuv[i * width + j] = (byte) y;// yuv[len + (i >> 1) * width + (j & ~1) + 0] = (byte) u;// yuv[len + (i >> 1) * width + (j & ~1) + 1] = (byte) v;}}return yuv;}

Utils:

/*** Get a file path from a Uri. This will get the the path for Storage Access* Framework Documents, as well as the _data field for the MediaStore and* other file-based ContentProviders.* * @param context*            The context.* @param uri*            The Uri to query.* @author paulburke*/public static String getPath(final Context context, final Uri uri) {final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;// DocumentProviderif (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {// ExternalStorageProviderif (isExternalStorageDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];if ("primary".equalsIgnoreCase(type)) {return Environment.getExternalStorageDirectory() + "/"+ split[1];}// TODO handle non-primary volumes}// DownloadsProviderelse if (isDownloadsDocument(uri)) {final String id = DocumentsContract.getDocumentId(uri);final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(id));return getDataColumn(context, contentUri, null, null);}// MediaProviderelse if (isMediaDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];Uri contentUri = null;if ("image".equals(type)) {contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ("video".equals(type)) {contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ("audio".equals(type)) {contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}final String selection = "_id=?";final String[] selectionArgs = new String[] { split[1] };return getDataColumn(context, contentUri, selection,selectionArgs);}}// MediaStore (and general)else if ("content".equalsIgnoreCase(uri.getScheme())) {return getDataColumn(context, uri, null, null);}// Fileelse if ("file".equalsIgnoreCase(uri.getScheme())) {return uri.getPath();}return null;}/*** Get the value of the data column for this Uri. This is useful for* MediaStore Uris, and other file-based ContentProviders.* * @param context*            The context.* @param uri*            The Uri to query.* @param selection*            (Optional) Filter used in the query.* @param selectionArgs*            (Optional) Selection arguments used in the query.* @return The value of the _data column, which is typically a file path.*/public static String getDataColumn(Context context, Uri uri,String selection, String[] selectionArgs) {Cursor cursor = null;final String column = "_data";final String[] projection = { column };try {cursor = context.getContentResolver().query(uri, projection,selection, selectionArgs, null);if (cursor != null && cursor.moveToFirst()) {final int column_index = cursor.getColumnIndexOrThrow(column);return cursor.getString(column_index);}} finally {if (cursor != null)cursor.close();}return null;}/*** @param uri*            The Uri to check.* @return Whether the Uri authority is ExternalStorageProvider.*/public static boolean isExternalStorageDocument(Uri uri) {return "com.android.externalstorage.documents".equals(uri.getAuthority());}/*** @param uri*            The Uri to check.* @return Whether the Uri authority is DownloadsProvider.*/public static boolean isDownloadsDocument(Uri uri) {return "com.android.providers.downloads.documents".equals(uri.getAuthority());}/*** @param uri*            The Uri to check.* @return Whether the Uri authority is MediaProvider.*/public static boolean isMediaDocument(Uri uri) {return "com.android.providers.media.documents".equals(uri.getAuthority());}

基本上只用调用一下代码就ok了,没什么难度,只是有一个点注意一下,就是存储权限一定要开,有些手机默认就开启了,有些手机需要用户去点击,不然就会识别不出来!

Android实现识别相册二维码相关推荐

  1. Android Zxing识别图片二维码识别率低

    1.使用Zxing对图片进行识别二维码 在gradle中引入识别库: implementation 'com.google.zxing:core:3.4.1' 对Bitmap进行识别二维码: int[ ...

  2. Android实现二维码扫描功能-ZXing识别图片二维码,相册选图

    文章目录 1.演示 2.权限问题 3.实现步骤 4.工具类 5.图片Uri处理(重要更新) 1.演示 2.权限问题 部分朋友在打开相册时遇到读写权限未授权的问题,我在开发的时候没有遇到,也没有注册读写 ...

  3. Android 识别图片二维码

    zxing依赖: compile 'cn.yipianfengye.android:zxing-library:2.2' 初始化:private String SAVE_PIC_PATH = Envi ...

  4. 1分钟快速实现高效的扫描二维码,急速识别手机相册二维码

    最近由于项目需求,需要在二维码扫描时添加识别相册内二维码的功能,于是,遇到了许多问题在这里总结,好为以后不在采坑. 1.二维码识别速度慢,效率低 2.手机相册内的二维码识别速度慢,识别不出来 好了,主 ...

  5. Android利用zxing生成二维码,识别二维码,中间填充图片超详细、超简易教程

    gayhub上的zxing可用于生成二维码,识别二维码 gayhub地址:https://github.com/zxing/zxing 此文只是简易教程,文末附有完整代码和demo下载地址,进入正题: ...

  6. android仿微信识别相册中二维码图片信息

    仿照微信识别相册中二维码,写了一个Demo,供参考使用 1.添加依赖,基于zxing,使用了Glide选择的图片进行了显示 compile 'com.google.zxing:core:3.2.1'c ...

  7. Android 识别CAD二维码和复杂二维码

    1.采用鸿蒙二维码扫描,可识别CAD二维码和复杂二维码 // scankitSDK华为鸿蒙扫描 implementation 'com.huawei.hms:scanplus:1.3.1.300' / ...

  8. android 从图片获取二维码

    之前的博客我记得讲过关于扫描二维码的内容,昨天,组长让我不仅可以扫描获取二维码,还可以通过图片获取里面的二维码.比如别人拍了一张二维码的照片,发送给你,app应该可以获取图片的二维码. 自己在网上查了 ...

  9. 魔坊APP项目-15-邀请好友(业务逻辑流程图、服务端提供邀请好友的二维码生成接口、客户端通过第三方识别微信二维码,服务端提供接口允许访问、App配置私有协议,允许第三方应用通过私有协议,唤醒APP)

    邀请好友 1.业务逻辑流程图 客户端提供点击"邀请好友"以后的页面frame,html/invite.html,代码: <!DOCTYPE html> <html ...

最新文章

  1. 码云上传代码添加标签_如何使用码云-百度经验
  2. 使用CoreLocation进行定位(Swift版)
  3. 在/sys目录下建立一个文件,并且实现信息的读取和存储
  4. MULE ESB中custom,flows,connectors等的使用方法
  5. 【Linux系列】centos7中防火墙相关命令
  6. 容器操作系统虚拟化_为什么操作系统在容器化世界中很重要
  7. java做flv直播服务器,EasyDSS流媒体服务器软件(支持RTMP/HLS/HTTP-FLV/视频点播/视频直播)-正式环境安装部署攻略...
  8. xp python转化为exe_使用Py2exe从python脚本生成的exe在xp上不起作用
  9. AJAX请求 $.post方法的使用
  10. 19电子设计速成实战宝典pdf_开发宝典丛书:Visual C++编程实战宝典PDF
  11. 我与WCF有个约会之牵手篇-第一个WCF示例程序
  12. Nvivo简介、学习经验分享及教程
  13. selenium模拟键盘操作大全
  14. 阿里云服务器地域的选择
  15. 有什么好用的软件推荐?
  16. Caffe深度学习框架作者贾扬清online内容分享II
  17. Jetson AGX Orin刷机教程,奶奶看完都说会了!
  18. python话费充值_【图片】话费充值解决方案(附代码)转载【开发吧】_百度贴吧...
  19. 网易我的世界服务器如何装组件,网易我的世界组件包怎么使用-网易我的世界组件包如何使用...
  20. 无源定位入门(一)TDOA(3)CRLB

热门文章

  1. 中国计算机专家 —— 张效祥
  2. 亲测奥维互动地图访问GMAP方法
  3. 【全教程】各类刷机教程总汇 — 强刷 - 刷内核 - 卡刷
  4. ASO优化之应用商店关键词的实现
  5. 宝哥面试题分享(16):Git面试题:git常用命令、如何解决版本冲突、git和svn的区别
  6. 作者专访 | 从受益者到贡献者,朱凯的 ClickHouse 升级之路
  7. 社交电商与传统电商的优势对比
  8. 都是假的!这位小姐姐 P 的图,认真看你就输了!
  9. 【字符串处理】【模拟】NBA工资
  10. 英语四六级翻译8:奢侈品消费