android studio QRcode 掃描及生成 教學

(不含Android studio 教學)

環境介紹

項目 名稱
開發工具: Android studio
Android版本 api:20 android 4.4w
資料庫: MySQL (目前使用db4free)
掃描QRcode: Google Mobile Vision 16.2.0
產生QRcode: Zxing android embedded 3.4.0
資料庫連結: MySQL connector 5.1.48

部分重點說明

MySQL connector 版本別超過5以上(會失敗)
Android版本 別超過 20 對焦方式編寫在 21 開始不同
也可以嘗試使用新版本的對焦方式(我沒成功)

連接MySQL教學
(使用JDBC)

開啟Project並將connector裝進lib

啟動連線設定

<uses-permission android:name=”android.permission.INTERNET” />

連接質料庫程式碼

       yoyo.start();
    final Thread yoyo = new Thread(new Runnable() {
        @Override
        public void run() {
        
        //加載驅動
          try {
            Class.forName("com.mysql.jdbc.Driver");
            Log.v("ha", "加載JDBC驅動成功");
        } catch (ClassNotFoundException e) {
            Log.e("ha", "加載JDBC驅動失敗");
            return;
        }
        
        //連接資料庫
            String url="jdbc:mysql://db4free.net:3306/kmbmteam?serverTimezone=UTC";
            try {
                Connection conn;
                conn= DriverManager.getConnection(url,"(帳號)","(密碼)");
                Log.v("ha", "遠程連接成功!");
                if (conn != null) {
                    String sql = "SELECT * FROM kmbmteam.member";
                    java.sql.Statement statement = conn.createStatement();
                    ResultSet rSet = statement.executeQuery(sql);
                    while (rSet.next()) {
                        showa=showa+"/n"+rSet.getString(3);
                    }
                    conn.close();
                    return;
                }
            } catch (SQLException e) {
                Log.e("ha", "遠程連接失敗!"+e);
            }

        }

    });
    

程式碼說明

額外執行緒程式碼
因為資料庫連結程式不能在介面主執行緒執行
主要是因為 若在主程式執行連結資料庫錯誤或延遲會導致整個軟體出錯

    final Thread yoyo = new Thread(new Runnable() {
        @Override
        public void run() {
            程式內容....
        }

    });
    
    //在主程式使用 yoyo.start();就可執行

額外說明

因為是額外執行緒所以不行控制介面
若要控制介面需要另外呼叫

/主程式外建立
TextView changetextview;

//主程式 需要讓建立的物件與介面物件連結
protected void onCreate(Bundle savedInstanceState) {
    changetextview=(TextView)findViewById(R.id.物件名稱
    yoyo.start();
}
//額外執行緒
final Thread yoyo = new Thread(new Runnable() {
        @Override
        public void run() {
            //此為額外執行緒內
            
            changetextview.post(new Runnable() {
                        @Override
                        public void run() {
                            changetextview.setText("修改介面內容")
                        }
                        
            
            
            
            //此為額外執行緒內
        }

    });

建立掃描QRcode

安裝套件

implementation ‘com.google.android.gms:play-services-vision:16.2.0’

啟動相機


請在介面中放置一個TextView以及一個surfaceView
接著再程式碼區宣告所需物件

SurfaceView surfaceView;
TextView textView;
CameraSource cameraSource;
BarcodeDetector barcodeDetector;

在介面主程式連結物件

surfaceView=(SurfaceView)findViewById(R.id.surfaceView);
textView=(TextView)findViewById(R.id.textView);

barcodeDetector = new BarcodeDetector.Builder(this)
      .setBarcodeFormats(Barcode.QR_CODE).build();
cameraSource=new CameraSource.Builder(this,barcodeDetector)
      .setRequestedPreviewSize(500,500).build();

取得相機權限

 if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},1);
        }

先來看看目前樣子


接著需要顯示於介面上
並設定關閉程式時關閉相機

 surfaceView.getHolder().addCallback(new SurfaceHolder.Callback(){
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

                if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA)
                        != PackageManager.PERMISSION_GRANTED)
                    return;
                try{
                    cameraSource.start(holder);
                }catch (IOException e){
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

建立掃描執行

barcodeDetector.setProcessor(new Detector.Processor<Barcode>(){
            @Override
            public void release() {

            }

            @Override 
            public void receiveDetections(Detector.Detections<Barcode> detections) {
                final SparseArray<Barcode> qrCodes=detections.getDetectedItems();
                if(qrCodes.size()!=0){
                //掃描成功會執行此區
                    //控制介面
                    textView.post(new Runnable() {
                        @Override
                        public void run() {
                                textView.setText(qrCodes.valueAt(0).displayValue);
                                       
                    }
                    });
                }
            }


        });

完成可作基本掃描的Scanner

接下來製作對焦
在主程式外建立一個事件
(@scanner)錯誤 請把它改成此頁面名稱

    @StringDef({
            Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
            Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
            Camera.Parameters.FOCUS_MODE_AUTO,
            Camera.Parameters.FOCUS_MODE_EDOF,
            Camera.Parameters.FOCUS_MODE_FIXED,
            Camera.Parameters.FOCUS_MODE_INFINITY,
            Camera.Parameters.FOCUS_MODE_MACRO
    })
    @Retention(RetentionPolicy.SOURCE)
    private @interface FocusMode {}
    public static boolean cameraFocus( CameraSource cameraSource, @scanner.FocusMode String focusMode) {
        Field[] declaredFields = CameraSource.class.getDeclaredFields();

        for (Field field : declaredFields) {
            if (field.getType() == Camera.class) {
                field.setAccessible(true);
                try {
                    Camera camera = (Camera) field.get(cameraSource);
                    if (camera != null) {
                        Camera.Parameters params = camera.getParameters();

                        if (!params.getSupportedFocusModes().contains(focusMode)) {
                            return false;
                        }

                        params.setFocusMode(focusMode);
                        camera.setParameters(params);
                        return true;
                    }
                    return false;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

                break;
            }
        }
        return false;
    }

接著建立按鈕或surface建立事件 並給予啟動對焦

 public  void focus_onclick(View v){
        cameraFocus(cameraSource,Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    }

#完成 如果不成功可以問問我

製作產生QRcode

安裝套件

com.journeyapps:zxing-android-embedded:3.4.0

介面建立個ImageView
ID設為helloworld

接著
直接使用

ImageView thisisimg = (ImageView) findViewById(R.id.helloworld);
BarcodeEncoder encoder = new BarcodeEncoder();
        try {
            Bitmap bit = encoder.encodeBitmap("here_is_showing", BarcodeFormat.QR_CODE,
                    250, 250);
            thisisimg .setImageBitmap(bit);
        } catch (WriterException e) {
            e.printStackTrace();
        }