close

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

image

2.開啟一個新的專案,並選擇空的活動(Empty Activity)

image

3.我們在主要頁面上(activity_main.xml)新增一個按鈕,未來就透過這個按鈕呼叫條碼掃描器來幫我們作掃描

image

4.我們知道 andorid的程式碼是以JAVA為基底,因此這次我們把CODE SCANNER的JAVA CODE加進我們的程式里,當成一個CLASS來呼叫

   因此我們要在JAVA的資料夾中新增一個叫做CodeScanner的 JAVA class

image

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

image

(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)[出現]在主畫面

這時候就大功告成拉~

image

arrow
arrow

    筱寒Love分享 發表在 痞客邦 留言(0) 人氣()