android 到7.X之後 已經回歸到android studio的開發工具,不再以eclipse為開發環境
因此介面上就有些許不同 這次我們要談的是使用andorid studio快速開發1維條碼掃描應用程式
因為條碼掃描牽扯到影像辨識、演算法等等不是很輕鬆就可以自立完成的事情
好在開源程式庫github有許多免費的開源程式碼可以使用
這次我們使用的是原始碼是國人Magic Len開發的「簡易條碼掃描器」
https://github.com/magiclen/Easy-Barcode-Scanner
改良很多 zXing」(com.google.zxing.client.android)的小問題
對我們想要快速開發的朋友來說 是很棒的懶人包
這次我們就手把手的從建立專案開始一步步到完成能實際掃描1維條碼全部都實作一次
----------正片開始-------------------------
1.下載並安裝android studio
https://developer.android.com/studio
2.開啟一個新的專案,並選擇空的活動(Empty Activity)
3.我們在主要頁面上(activity_main.xml)新增一個按鈕,未來就透過這個按鈕呼叫條碼掃描器來幫我們作掃描
4.我們知道 andorid的程式碼是以JAVA為基底,因此這次我們把CODE SCANNER的JAVA CODE加進我們的程式里,當成一個CLASS來呼叫
因此我們要在JAVA的資料夾中新增一個叫做CodeScanner的 JAVA class
5.我們直接把簡易條碼掃描器的原始碼包進來,以後就可以呼叫來使用,這邊要特別說明的是,Android允許App可以去呼叫別的app中的功能來使用
因此使用者如果沒有安裝簡易條碼掃描器這個App時,會引導到google play進行安裝,這邊的原始碼是開一個接口讓你的app去呼叫簡易條碼掃描器這個App
把以下的程式碼整包丟到先前新增的CodeScanner class:
package org.magiclen.code; import java.util.List; import java.util.Locale; import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; /** * 條碼掃描 * * @author magiclen * */ public class CodeScanner { // -----類別常數----- private static final String SCAN_MODES = "SCAN_MODE"; private static final String USE_CROP = "USE_CROP"; private static final String SCAN_PREFIX = "SCAN_PREFIX"; private static final String[] STRING_INSTALL_TITLE = new String[] { "Install Barcode Scanner", "安裝條碼掃描器" }; private static final String[] STRING_INSTALL_CLOSE = new String[] { "Close", "關閉" }; private static final String[] STRING_INSTALL_INSTALL = new String[] { "Install", "安裝" }; private static final String[] STRING_INSTALL_MESSAGE = new String[] { "In order to scan barcode, you neet to install Easy Barcode Scanner first.", "為了能夠掃描條碼,您需要一個簡易條碼掃描器。" }; private static final String[] STRING_URL_EASY_BARCODE_SCANNER = new String[] { "https://play.google.com/store/apps/details?id=org.magiclen.barcodescanner" }; // -----類別列舉----- public static enum Mode { PRODUCT_MODE, SCAN_MODE, ONE_D_MODE, TWO_D_MODE, QR_CODE_MODE, DATA_MATRIX_MODE; } // -----類別介面----- public static interface CodeReaderListener { public void codeReadResult(final String type, final String data); } // -----類別變數----- private static boolean chinese = isChinese(); // -----類別方法----- private static boolean isChinese() { final Locale locale = Locale.getDefault(); return locale.equals(Locale.CHINESE) || locale.equals(Locale.SIMPLIFIED_CHINESE) || locale.equals(Locale.TRADITIONAL_CHINESE); } private static String getString(final String[] string) { int index = chinese ? 1 : 0; if (index >= string.length) { index = 0; } return string[index]; } private static int ACTIVITY_SCANNER = 9974; // -----物件變數----- private Activity activity; private Fragment fragment; private CodeReaderListener codeReaderListener; private Mode mode = Mode.SCAN_MODE; private boolean crop = false; private String scanPrefix = null; // -----建構子----- public CodeScanner(final Activity activity, final CodeReaderListener codeReaderListener) { this.activity = activity; this.codeReaderListener = codeReaderListener; } public CodeScanner(final Fragment fragment, final CodeReaderListener codeReaderListener) { this(fragment.getActivity(), codeReaderListener); this.fragment = fragment; } // -----物件方法----- public Activity getActivity() { if (activity != null) { return activity; } else { return null; } } public CodeReaderListener getCodeReaderListener() { return codeReaderListener; } public void setCrop(final boolean crop) { this.crop = crop; } public boolean getCrop() { return crop; } public void setMode(final Mode mode) { if (mode != null) { this.mode = mode; } else { this.mode = Mode.SCAN_MODE; } } public Mode getMode() { return mode; } public void setScanPrefix(final String scanPrefix) { this.scanPrefix = scanPrefix; } public String getScanPrefix() { return scanPrefix; } public boolean scan() { final PackageManager packageManager = activity.getPackageManager(); final Intent easyBarcodeScanner = new Intent("org.magiclen.barcodescanner.SCAN"); easyBarcodeScanner.setPackage("org.magiclen.barcodescanner"); final List<ResolveInfo> list = packageManager.queryIntentActivities(easyBarcodeScanner, PackageManager.MATCH_DEFAULT_ONLY); if (list.size() > 0) { easyBarcodeScanner.putExtra(SCAN_MODES, mode.toString()); easyBarcodeScanner.putExtra(USE_CROP, crop); easyBarcodeScanner.putExtra(SCAN_PREFIX, scanPrefix); if (fragment != null) { fragment.startActivityForResult(easyBarcodeScanner, ACTIVITY_SCANNER); } else { activity.startActivityForResult(easyBarcodeScanner, ACTIVITY_SCANNER); } return true; } else { new AlertDialog.Builder(activity).setTitle(getString(STRING_INSTALL_TITLE)).setMessage(getString(STRING_INSTALL_MESSAGE)).setPositiveButton(getString(STRING_INSTALL_INSTALL), new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { final String url = getString(STRING_URL_EASY_BARCODE_SCANNER); final Intent openURLIntent = new Intent(Intent.ACTION_VIEW); openURLIntent.setData(Uri.parse(url)); final List<ResolveInfo> list = packageManager.queryIntentActivities(openURLIntent, PackageManager.MATCH_DEFAULT_ONLY); if (list.size() > 0) { final Intent destIntent = Intent.createChooser(openURLIntent, null); activity.startActivity(destIntent); } } }).setNegativeButton(getString(STRING_INSTALL_CLOSE), null).show(); return false; } } public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == ACTIVITY_SCANNER && codeReaderListener != null) { if (resultCode == Activity.RESULT_OK) { final String resultType = data.getStringExtra("code_type"); final String resultData = data.getStringExtra("code_data"); codeReaderListener.codeReadResult(resultType, resultData); } else { codeReaderListener.codeReadResult(null, null); } } } }
6.在android app開發裏面,想要去呼叫一個功能,例如我們現在想要去呼叫[掃描]這個功能,就必須建立一個Intent(意圖),當按鈕按下時,就可以觸發這個Intent,
我們用比較簡單不傷大腦的說法來簡化一下:
我(1)[按下按鈕]後,(2)[呼叫]在(3)[新頁面]里(4)[掃描條碼],(5)[掃描有結果]後,(6)[條碼內容]會(7)[出現]在主畫面
先把MainActivity.java所有程式碼貼上來,之後再一一講解:
package com.example.scanbutton_20200317; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.content.Intent; import android.view.View; import android.widget.Button; import android.widget.Toast; import org.magiclen.code.CodeScanner; public class MainActivity extends AppCompatActivity { final private int LAUNCH_ScanAct=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // buildViews(); //自定畫面動作邏輯 } private void buildViews(){ final Button btScan; btScan=(Button)findViewById(R.id.ScanBtId); btScan.setOnClickListener(btListener); } private View.OnClickListener btListener=new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(); intent.setClass(MainActivity.this, Scanner.class); startActivityForResult(intent,LAUNCH_ScanAct); } }; protected void onActivityResult(int requestCode, int resultCode, Intent data){ if(requestCode != LAUNCH_ScanAct) return; switch(resultCode){ case RESULT_OK: Bundle bundle=data.getExtras(); String bookCode=bundle.getString("bookCode"); Toast.makeText(MainActivity.this,bookCode, Toast.LENGTH_SHORT).show(); break; case RESULT_CANCELED: Toast.makeText(MainActivity.this,"掃描錯誤!",Toast.LENGTH_SHORT).show(); } } }
接下來我們就一步步說明怎麼實現這個動作:
(1)[按下按鈕]:
我們剛剛已經在主畫面新建立一個按鈕叫作(ScanBtId),接下來我們要在MainActivity.java裏面描述按鈕的動作:
我們建立了一個btListener,讓Listener去監聽SCAN按鈕是不是被觸發
private void buildViews(){ final Button btScan; btScan=(Button)findViewById(R.id.ScanBtId); btScan.setOnClickListener(btListener); } private View.OnClickListener btListener=new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(); intent.setClass(MainActivity.this, Scanner.class); startActivityForResult(intent,LAUNCH_ScanAct); } };
(2)[呼叫]Intent(意圖)
可以在上面的程式碼裡面看到,當按下按鈕時,我們建立了一個新的Intent
(3)建立[新頁面]
為了讓Intent能呼叫一個新的畫面,我們必須新增一個空的Acitvity(活動),並命名叫作Scanner,同時會自動產生一個叫做Scanner.java的檔案在Java
(4)[掃描條碼]
為了在新活動中能使用掃描條碼的功能,我們把呼叫掃描器的程式碼放進Scanner.java中:
package com.example.scanbutton_20200317; import androidx.appcompat.app.AppCompatActivity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import org.magiclen.code.CodeScanner; import org.magiclen.code.CodeScanner; public class Scanner extends AppCompatActivity { private static final String QR_KEY = ""; CodeScanner cs; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); CodeScanner.CodeReaderListener codeReaderListener=new CodeScanner.CodeReaderListener() { @Override public void codeReadResult(String type, String data) { Intent intent = new Intent(); Bundle backbundle=new Bundle(); backbundle.putString("bookCode",data); intent.putExtras(backbundle); setResult(RESULT_OK,intent); finish(); } }; cs = new CodeScanner(this, codeReaderListener); cs.setMode(CodeScanner.Mode.ONE_D_MODE); cs.setScanPrefix(QR_KEY); cs.setCrop(true); cs.scan(); } protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { cs.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data); } }
(5)[掃描有結果]
如果掃描有結果後, codeReadResult(String type, String data)就會將掃描到的條碼放入bookCode這個字串中,並藉由onActivityResult回傳到主畫面
(6)[條碼內容]
回到MainActivity.java
我們來處理回傳的資料:
switch(resultCode){ case RESULT_OK: Bundle bundle=data.getExtras(); String bookCode=bundle.getString("bookCode"); Toast.makeText(MainActivity.this, "掃描結果:"+bookCode, Toast.LENGTH_SHORT).show(); break; case RESULT_CANCELED: Toast.makeText(MainActivity.this,"掃描錯誤!",Toast.LENGTH_SHORT).show(); }
(7)[出現]在主畫面
這時候就大功告成拉~
留言列表