개발모음집

Android, Google Chart Api를 이용한 QR code 생성 및 xzing을 이용한 QR코드 스캐너 만들기 본문

Android

Android, Google Chart Api를 이용한 QR code 생성 및 xzing을 이용한 QR코드 스캐너 만들기

void 2018. 3. 28. 09:00

1.  QR code 생성하기

    http://chart.apis.google.com/chart?cht=qr&chs=350x350&chl={담고싶은 문자열 정보} 

    위에서 350x350은 생성될 QR 코드의 가로x세로 사이즈이고 맨 끝의 = 이후에 담고 싶은 문자열을 입력하면 된다('{', '}'은 생략).

출처 : evnt-hrzn


google이 제공하는 URL에 문자열을 추가하여 접근하면 내가 만들고 싶은 문자열로 QR 코드를 생성해준다.


그러면 이 QR코드가 이미지니까 서버에 있는 이미지를 쉽게 안드로이드에서 볼 수 있게 해주는 API인 AQUERY로 이미지가져와야지 (참고 내블로그)


private AQuery aq = new AQuery( this );


String qrcodeStr="만들고 싶은 qr코드의 String값";

binding = DataBindingUtil.setContentView(this, QRCODE);
aq.id(binding.qrcodeIv).image("http://chart.apis.google.com/chart?cht=qr&chs=350x350&chl="+qrcodeStr);

참고로 mvvm 패턴을 써서 바인딩을 함

mvc 패턴이라면 아래와 같이 하면 됨

String qrcodeStr="만들고 싶은 qr코드의 String값"; ImageView img = (ImageView)this.findViewById(R.id.img);
aq.id( img ).image("http://chart.apis.google.com/chart?cht=qr&chs=350x350&chl="+qrcodeStr);


2. QR 리더기

2-1 SurfaceView로 만들기

2-2 zxing 라이브러리로 만들기


2-1은 커스텀으로 UI를 추가해줘야해서 2-2 zxing로 구현


2-1 SurfaceView로 만들기

QrcodeReaderActivity.java

package com.blank.android.allnight.AddToFriends;

import android.Manifest;
import android.content.pm.PackageManager;
import android.databinding.DataBindingUtil;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.blank.android.allnight.R;
import com.blank.android.allnight.databinding.ActivityQrcodeReaderBinding;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;

import java.io.IOException;

public class QrcodeReaderActivity extends AppCompatActivity {

ActivityQrcodeReaderBinding binding;


CameraSource cameraSource;
BarcodeDetector barcodeDetector;

private static final int QRCODEREADER = R.layout.activity_qrcode_reader;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 데이터 바인딩
binding = DataBindingUtil.setContentView(this, QRCODEREADER);

barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();

// 카메라 설정
cameraSource = new CameraSource
.Builder(this, barcodeDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedFps(29.8f) // 프레임, 높을 수록 리소스를 많이 먹음
.setRequestedPreviewSize(1080, 1920) // 확실한 용도를 잘 모르겠음. 필자는 핸드폰 크기로 설정
.setAutoFocusEnabled(true) // AutoFocus를 안하면 초점을 못 잡아서 화질이 흐림.
.build();

// Callback을 이용해서 SurfaceView를 실시간으로 Mobile Vision API와 연결
binding.surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try { // try-catch 문은 Camera 권한획득을 위한 권장사항
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
binding.surfaceView.refreshDrawableState();
cameraSource.start(binding.surfaceView.getHolder()); // Mobile Vision API 시작
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

}

// SurfaceView가 종료되었을 때, Mobile Vision API 종료
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
Log.d("NowStatus", "SurfaceView Destroyed and CameraSource Stopped");
}
});

barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
Log.d("NowStatus", "BarcodeDetector SetProcessor Released");
}

// TODO 바코드가 인식되었을 때 동작할 기능 구현
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0) {
String barcodeContents = barcodes.valueAt(0).displayValue; // 바코드 인식 결과물
Log.d("Detection", barcodeContents);
}
}
});
}

}


activity_qrcode_reader.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.blank.android.allnight.AddToFriends.QrcodeReaderActivity">

<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />


</android.support.constraint.ConstraintLayout>

</layout>


참고: github


2-2 zxing 라이브러리로 만들기


surfaceview로 동작은 하는데 카메라앱처럼 동작하기 때문에 QR코드리더기처럼 UI를 커스텀해줘야하기 때문에 개발에 시간이 걸릴 것으로 예상한다.

그래서 xzing 라이브러리로 구현한다.


// xzing 리더기로 이동
binding.qrcodeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new IntentIntegrator(QrcodeActivity.this).initiateScan();
}
});


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

// com.google.zxing.integration.android.IntentIntegrator.REQUEST_CODE
// = 0x0000c0de; // Only use bottom 16 bits
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result == null) {
// 취소됨
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
// 스캔된 QRCode --> result.getContents()
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}

참고: 티스토리