Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Zxing圖片識別 從相冊選取二維碼圖片進行解析總結

Zxing圖片識別 從相冊選取二維碼圖片進行解析總結

編輯:關於Android編程

在Zxing掃描識別和圖片識別的解析對象是相同的

本文分三個步驟:

1 獲取相冊的照片

2 解析二維碼圖片

3 返回結果

 

1) 獲取相冊照片

google對4.4的uri做了點改動 為了適配多種手機 需要做一個判斷版本

在Activity中開啟相冊:

  1. IntentinnerIntent=newIntent();//"android.intent.action.GET_CONTENT"
  2. if(Build.VERSION.SDK_INT<19){
  3. innerIntent.setAction(Intent.ACTION_GET_CONTENT);
  4. }else{
  5. // innerIntent.setAction(Intent.ACTION_OPEN_DOCUMENT); 這個方法報 圖片地址 空指針;使用下面的方法
  6. innerIntent.setAction(Intent.ACTION_PICK);
  7. }
  8.  
  9. innerIntent.setType("image/*");
  10.  
  11. IntentwrapperIntent=Intent.createChooser(innerIntent,"選擇二維碼圖片");
  12.  
  13. CaptureActivity.this
  14. .startActivityForResult(wrapperIntent,REQUEST_CODE);

選中了照片後返回的數據在onActivityResult方法中獲取

  1. @Override
  2. protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
  3.  
  4. super.onActivityResult(requestCode,resultCode,data);
  5.  
  6. if(resultCode==RESULT_OK){
  7.  
  8. switch(requestCode){
  9.  
  10. caseREQUEST_CODE:
  11.  
  12. String[]proj={MediaStore.Images.Media.DATA};
  13. //獲取選中圖片的路徑
  14. Cursorcursor=getContentResolver().query(data.getData(),
  15. proj,null,null,null);
  16.  
  17. if(cursor.moveToFirst()){
  18.  
  19. intcolumn_index=cursor
  20. .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
  21. photo_path=cursor.getString(column_index);
  22. if(photo_path==null){
  23. photo_path=Utils.getPath(getApplicationContext(),
  24. data.getData());
  25. Log.i("123pathUtils",photo_path);
  26. }
  27. Log.i("123path",photo_path);
  28.  
  29. }
  30.  
  31. cursor.close();
  32.  
  33. newThread(newRunnable(){
  34.  
  35. @Override
  36. publicvoidrun(){
  37.  
  38. Resultresult=scanningImage(photo_path);
  39. //Stringresult=decode(photo_path);
  40. if(result==null){
  41. Looper.prepare();
  42. Toast.makeText(getApplicationContext(),"圖片格式有誤",0)
  43. .show();
  44. Looper.loop();
  45. }else{
  46. Log.i("123result",result.toString());
  47. //Log.i("123result",result.getText());
  48. //數據返回
  49. Stringrecode=recode(result.toString());
  50. Intentdata=newIntent();
  51. data.putExtra("result",recode);
  52. setResult(300,data);
  53. finish();
  54. }
  55. }
  56. }).start();
  57. break;
  58.  
  59. }
  60.  
  61. }
  62.  
  63. }

上面這段代碼

<1> 根據返回的照片信息 獲取圖片的路徑photo_path

<2> 開啟一個解析線程調用解析方法Result result = scanningImage(photo_path); 將photo_path傳進去

<3> 對返回的解析的Result對象進行判斷,獲取字符串

<4> 調用recode對result數據進行中文亂碼處理( 具體在步驟3中說明 )

  1. Stringrecode=recode(result.toString());

<5>這裡我將result 通過setResult(); 返回給了 父Activity

<6> Utils.getPath(getApplicationContext(),data.getData()); //將圖片Uri 轉換成絕對路徑

  1. publicclassUtils{
  2.  
  3. publicstaticfinalbooleanisChineseCharacter(StringchineseStr){
  4. char[]charArray=chineseStr.toCharArray();
  5. for(inti=0;i //是否是Unicode編碼,除了"?"這個字符.這個字符要另外處理
  6. if((charArray[i]>='\u0000'&&charArray[i]<'\uFFFD')
  7. ||((charArray[i]>'\uFFFD'&&charArray[i]<'\uFFFF'))){
  8. continue;
  9. }else{
  10. returnfalse;
  11. }
  12. }
  13. returntrue;
  14. }
  15.  
  16. /**
  17. *GetafilepathfromaUri.ThiswillgetthethepathforStorageAccess
  18. *FrameworkDocuments,aswellasthe_datafieldfortheMediaStoreand
  19. *otherfile-basedContentProviders.
  20. *
  21. *@paramcontext
  22. *Thecontext.
  23. *@paramuri
  24. *TheUritoquery.
  25. *@authorpaulburke
  26. */
  27. publicstaticStringgetPath(finalContextcontext,finalUriuri){
  28.  
  29. finalbooleanisKitKat=Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT;
  30.  
  31. //DocumentProvider
  32. if(isKitKat&&DocumentsContract.isDocumentUri(context,uri)){
  33. //ExternalStorageProvider
  34. if(isExternalStorageDocument(uri)){
  35. finalStringdocId=DocumentsContract.getDocumentId(uri);
  36. finalString[]split=docId.split(":");
  37. finalStringtype=split[0];
  38.  
  39. if("primary".equalsIgnoreCase(type)){
  40. returnEnvironment.getExternalStorageDirectory()+"/"
  41. +split[1];
  42. }
  43.  
  44. //TODOhandlenon-primaryvolumes
  45. }
  46. //DownloadsProvider
  47. elseif(isDownloadsDocument(uri)){
  48.  
  49. finalStringid=DocumentsContract.getDocumentId(uri);
  50. finalUricontentUri=ContentUris.withAppendedId(
  51. Uri.parse("content://downloads/public_downloads"),
  52. Long.valueOf(id));
  53.  
  54. returngetDataColumn(context,contentUri,null,null);
  55. }
  56. //MediaProvider
  57. elseif(isMediaDocument(uri)){
  58. finalStringdocId=DocumentsContract.getDocumentId(uri);
  59. finalString[]split=docId.split(":");
  60. finalStringtype=split[0];
  61.  
  62. UricontentUri=null;
  63. if("image".equals(type)){
  64. contentUri=MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  65. }elseif("video".equals(type)){
  66. contentUri=MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  67. }elseif("audio".equals(type)){
  68. contentUri=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  69. }
  70.  
  71. finalStringselection="_id=?";
  72. finalString[]selectionArgs=newString[]{split[1]};
  73.  
  74. returngetDataColumn(context,contentUri,selection,
  75. selectionArgs);
  76. }
  77. }
  78. //MediaStore(andgeneral)
  79. elseif("content".equalsIgnoreCase(uri.getScheme())){
  80. returngetDataColumn(context,uri,null,null);
  81. }
  82. //File
  83. elseif("file".equalsIgnoreCase(uri.getScheme())){
  84. returnuri.getPath();
  85. }
  86.  
  87. returnnull;
  88. }
  89.  
  90. /**
  91. *GetthevalueofthedatacolumnforthisUri.Thisisusefulfor
  92. *MediaStoreUris,andotherfile-basedContentProviders.
  93. *
  94. *@paramcontext
  95. *Thecontext.
  96. *@paramuri
  97. *TheUritoquery.
  98. *@paramselection
  99. *(Optional)Filterusedinthequery.
  100. *@paramselectionArgs
  101. *(Optional)Selectionargumentsusedinthequery.
  102. *@returnThevalueofthe_datacolumn,whichistypicallyafilepath.
  103. */
  104. publicstaticStringgetDataColumn(Contextcontext,Uriuri,
  105. Stringselection,String[]selectionArgs){
  106.  
  107. Cursorcursor=null;
  108. finalStringcolumn="_data";
  109. finalString[]projection={column};
  110.  
  111. try{
  112. cursor=context.getContentResolver().query(uri,projection,
  113. selection,selectionArgs,null);
  114. if(cursor!=null&&cursor.moveToFirst()){
  115. finalintcolumn_index=cursor.getColumnIndexOrThrow(column);
  116. returncursor.getString(column_index);
  117. }
  118. }finally{
  119. if(cursor!=null)
  120. cursor.close();
  121. }
  122. returnnull;
  123. }
  124.  
  125. /**
  126. *@paramuri
  127. *TheUritocheck.
  128. *@returnWhethertheUriauthorityisExternalStorageProvider.
  129. */
  130. publicstaticbooleanisExternalStorageDocument(Uriuri){
  131. return"com.android.externalstorage.documents".equals(uri
  132. .getAuthority());
  133. }
  134.  
  135. /**
  136. *@paramuri
  137. *TheUritocheck.
  138. *@returnWhethertheUriauthorityisDownloadsProvider.
  139. */
  140. publicstaticbooleanisDownloadsDocument(Uriuri){
  141. return"com.android.providers.downloads.documents".equals(uri
  142. .getAuthority());
  143. }
  144.  
  145. /**
  146. *@paramuri
  147. *TheUritocheck.
  148. *@returnWhethertheUriauthorityisMediaProvider.
  149. */
  150. publicstaticbooleanisMediaDocument(Uriuri){
  151. return"com.android.providers.media.documents".equals(uri
  152. .getAuthority());
  153. }
  154.  
  155. }

2) 解析二維碼圖片

  1. protectedResultscanningImage(Stringpath){
  2. if(TextUtils.isEmpty(path)){
  3.  
  4. returnnull;
  5.  
  6. }
  7. //DecodeHintType和EncodeHintType
  8. Hashtablehints=newHashtable();
  9. hints.put(DecodeHintType.CHARACTER_SET,"utf-8");//設置二維碼內容的編碼
  10. BitmapFactory.Optionsoptions=newBitmapFactory.Options();
  11. options.inJustDecodeBounds=true;//先獲取原大小
  12. scanBitmap=BitmapFactory.decodeFile(path,options);
  13. options.inJustDecodeBounds=false;//獲取新的大小
  14.  
  15. intsampleSize=(int)(options.outHeight/(float)200);
  16.  
  17. if(sampleSize<=0)
  18. sampleSize=1;
  19. options.inSampleSize=sampleSize;
  20. scanBitmap=BitmapFactory.decodeFile(path,options);
  21.  
  22.  
  23.  
  24. RGBLuminanceSourcesource=newRGBLuminanceSource(scanBitmap);
  25. BinaryBitmapbitmap1=newBinaryBitmap(newHybridBinarizer(source));
  26. QRCodeReaderreader=newQRCodeReader();
  27. try{
  28.  
  29. returnreader.decode(bitmap1,hints);
  30.  
  31. }catch(NotFoundExceptione){
  32.  
  33. e.printStackTrace();
  34.  
  35. }catch(ChecksumExceptione){
  36.  
  37. e.printStackTrace();
  38.  
  39. }catch(FormatExceptione){
  40.  
  41. e.printStackTrace();
  42.  
  43. }
  44.  
  45. returnnull;
  46. }


3) 返回結果

首先對result判斷是否為空 ,如果為空就代表 二維碼不標准或者不是二維碼圖片

在子線程中使用Toast 需要初始化looper

  1. Resultresult=scanningImage(photo_path);
  2. //Stringresult=decode(photo_path);
  3. if(result==null){
  4. Looper.prepare();
  5. Toast.makeText(getApplicationContext(),"圖片格式有誤",0)
  6. .show();
  7. Looper.loop();
  8. }else{
  9. Log.i("123result",result.toString());
  10. //Log.i("123result",result.getText());
  11. //數據返回
  12. Stringrecode=recode(result.toString());
  13. Intentdata=newIntent();
  14. data.putExtra("result",recode);
  15. setResult(300,data);
  16. finish();
  17. }
 

Result 對象返回的就是二維碼掃描的結果

調用recode(result.toString) 方法進行中文亂碼處理 代碼如下:

  1. privateStringrecode(Stringstr){
  2. Stringformart="";
  3.  
  4. try{
  5. booleanISO=Charset.forName("ISO-8859-1").newEncoder()
  6. .canEncode(str);
  7. if(ISO){
  8. formart=newString(str.getBytes("ISO-8859-1"),"GB2312");
  9. Log.i("1234ISO8859-1",formart);
  10. }else{
  11. formart=str;
  12. Log.i("1234stringExtra",str);
  13. }
  14. }catch(UnsupportedEncodingExceptione){
  15. //TODOAuto-generatedcatchblock
  16. e.printStackTrace();
  17. }
  18. returnformart;
  19. }
 

處理好之後將結果字符串 返回給父Activity

對於圖片識別有些事項需要注意..

二維碼的圖標需要保證圖片盡量不傾斜 拍照的時候 最好保證手機與二維碼 水平

附圖:

\

 

\

 

\

  1.  
 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved