# android studio QRcode 掃描及生成 教學 ## (不含Android studio 教學) ### 按esc可選擇頁面 ---- # 環境介紹 ---- ``` 項目 名稱 開發工具: 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) ---- ### 下載[Mysql connectcor 5.1.48](https://dev.mysql.com/downloads/connector/j/5.1.html) ---- #### 開啟Project並將connector裝進lib ![](https://i.imgur.com/CLp1Xib.jpg) ---- #### 啟動連線設定 ``` <uses-permission android:name="android.permission.INTERNET" /> ``` ![](https://i.imgur.com/yX0ZHYa.jpg) ---- #### 連接質料庫程式碼 說明在下一頁 ``` 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' ``` ![](https://i.imgur.com/wz6Q1NQ.jpg) ---- 啟動相機 ![](https://i.imgur.com/o3dwqlK.jpg) ---- 請在介面中放置一個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); } ``` ---- 先來看看目前樣子 ![](https://i.imgur.com/JaRRudX.jpg) ---- 接著需要顯示於介面上 並設定關閉程式時關閉相機 ``` 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(); } }); ``` ---- ![](https://i.imgur.com/JRURtBd.jpg) ---- 建立掃描執行 ``` 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 ![](https://i.imgur.com/pO5hg2D.jpg) ---- 接下來製作對焦 在主程式外建立一個事件 (@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 ``` ![](https://i.imgur.com/d5wOEOO.jpg) ---- 介面建立個ImageView ID設為helloworld ![](https://i.imgur.com/tEfLOdI.jpg) ---- 接著 直接使用 ``` 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(); } ``` ---- 研究看看吧~~ ![](https://i.imgur.com/Z5esiKa.jpg)