[QR코드리더] ZXing을 이용하여 내 안드로이드 어플에 QR코드 스캐너 도입하기

[ZXING]이라는 정말 잘 만들어진 안드로이드에서도 사용할 수 있는 QR코드/바코드 스캐너가 있습니다. 아이폰에서는 적당히 자유롭게 쓸 수 있지만 안드로이드에서는 Intent라는 좋은(?) 개념때문인지 Barcode Scanner라는 프로그램을 설치하여 그것을 Intent로 호출해 사용하게끔 하고 있더군요.

그리하여 ZXing의 안드로이드 소스를 커스터마이징 해서 그냥 사용할 수 있도록 약간 고쳐보았습니다. 만들어진 소스는 ZXing android + android-integration을 통합하여 제작하였습니다.

사용하시는 방법은 소스코드를 그냥 통채로 올리니 참고하시면 되겟지만 간단하게 기록을 해보겠습니다.

1. AndroidManifest.xml에 다음을 추가합니다.

[code]<activity
  android:name=”com.google.zxing.client.android.CaptureActivity”
  android:screenOrientation=”landscape”
  android:configChanges=”orientation|keyboardHidden”
  android:theme=”@android:style/Theme.NoTitleBar.Fullscreen”
  android:windowSoftInputMode=”stateAlwaysHidden”>
    <intent-filter>
      <action android:name=”com.google.zxing.client.android.SCAN”/>
      <category android:name=”android.intent.category.DEFAULT”/>
    </intent-filter>
</activity>

<uses-feature android:name=”android.hardware.camera”/>
<uses-permission android:name=”android.permission.CAMERA”/>
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.FLASHLIGHT”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>[/code]

2. 리소스 파일을 복사합니다. UI를 변경하고 싶을 경우 capture.xml을 변경하시면 됩니다.

res/layout/capture.xml
res/layout/ids.xml

3. 스캐너 호출 방법 (android-integration)

[code]// QR코드/바코드 스캐너를 구동합니다.
IntentIntegrator.initiateScan(MainActivity.this);[/code]

4. 결과 처리 방법

[code]protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
  // QR코드/바코드를 스캔한 결과 값을 가져옵니다.
  IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);

  // 결과값 출력
  new AlertDialog.Builder(this)
  .setTitle(R.string.app_name)
  .setMessage(result.getContents() + ” [” + result.getFormatName() + “]”)
  .setPositiveButton(“확인”, new DialogInterface.OnClickListener()
  {
    @Override
    public void onClick(DialogInterface dialog, int which)
    {
      dialog.dismiss();
    }
  })
  .show();
}[/code]

1394066880.zip

  • 좋은 포스트 보고 갑니다~

    저도 QR코드 다뤄봐야지 생각하고 있었는데, 아이님께 또 배우고 가네요 ^^

  • 시험모드

    UI변경을 하고 싶은데..
    capture.xml 을 만져봐도 변함이 없네요..
    글씨도 다 깨지구요 ㅠㅠ

    어떻게 수정해야 글씨가 안 깨질까요?

    • 아마도 프로젝트의 언어셋문제일듯 한데요. 깨지는 파일을 editplus나 ultraedit같은 안깨지고 읽을수 있는 파일로 읽어서 내용을 복사해서 개발중인 프로젝트 소스로 옮겨붙이세요~

  • 시험모드

    에구.. 소스는 좋은데요.. 제가 만든 기본어플에
    결합을 하고 싶은데.. 너무 어렵네요 휴우..

    위에 써주신 4가지 다 하고, java 파일들 다 넣고
    core.jar 같은것도 다 넣어야 되는건가요?

    • 네에, 모두다 있어야 합니다.

  • NY

    마침 QR코드 관련된 프로젝트를 진행하는데!
    정말 제가 찾던 부분이네요!! 너무 감사합니다!!
    잘 배우고 갑니다!!

  • irisui

    감사합니다 잘보고 갑니다 ^^

  • 주주

    잘보고 갑니다.
    pdf417은 안 읽히던데..
    core.jar에 pdf417 scan 기능도 포함되었던것 아닌가요?
    pdf417 scan 기능이 꼭 필요해서요….
    답변 부탁드려요^^

    • zxing 홈페이지에 가보시면 pdf417은 알파수준의 퀄리티밖에 구현 못했다고 나와있군요.

    • 주주

      그렇군요.빠른 답변 감사합니다^^
      하나만 더 여쭤볼게요.
      실제 barcode scanner 앱을 깔아보니
      바코드 인식 후 url 표시되고, open browser/share via email/share via sms 버튼이 나오던데 ZXingTest에는 어떻게 반영하면 되나요?

    • 그건 Zxing과는 관련없는 질문이신것 같군요. 위의 예제에서 보시면 onActivityResult에서 getContents()로 읽은 값을 출력하는것을 보실수 있는데 이 값을 원하시는 화면 레이아웃으로 보여주시면 되겠네요.

  • 나그네

    좋은 포스트 잘 봤습니다.

    잘 적용되긴 하는데요.

    혹시 카메라 회전을 하려면 어떻게 해야는지..portrait로요

    아 그리고 저도 위에 @시험모드님 말씀처럼

    capture.xml을 수정해도 UI가 변하지 않네요ㅠㅠ

    ViewfinderView.java 쪽을 건들여야하는건지..

  • 회의도트

    잘 봤습니다~

    죄송한데요…위에 주주님 대글에

    그건 Zxing과는 관련없는 질문이신것 같군요. 위의 예제에서 보시면 onActivityResult에서 getContents()로 읽은 값을 출력하는것을 보실수 있는데 이 값을 원하시는 화면 레이아웃으로 보여주시면 되겠네요.

    이렇게 대답하신거요

    URL주소가 안뜨고 바로 URL의 홈페이지 화면이 나오게 하는 것을 레이아웃으로 만들어서 하는게 가능한 건가요??

    • 네 당연히 가능하죠;

    • 회의도트

      죄송한데요..ㅠ방법 알 수 없을까요??간단하게 설명좀..
      제가 하도 안되서 webview xml하나 추가하고 거기에 IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
      String url = result.getContents().toString();

      WebView webview = (WebView) findViewById(R.id.webview);
      webview.loadUrl(url);

      이렇게 작성하니깐 나오긴나오는데요…이렇게 하신다고 하신건가요??혹시 따른방법이시면 알려주실 수 있나요??
      제가 이렇게 뜬 webview위젯에 버튼 하나를 얻이려고 하는데요 이렇게 하니깐
      버튼이 먼저 따로 1번 뜨고 나서 위젯이 뜨더라고요…따로 논다는…따른방법있으면…좀…ㅠㅠ

  • 강준

    웹페이지로 값을 넘기려면 어떻게 해야 하나요?

    • 가장 쉬운 방법은 Intent로 웹브라우저를 호출할때 넘길 URL에 ?key=value와 같이 QueryString으로 넘겨주면 GET방식으로 가져다 쓸수 있을테니 간단한 방법이 아닐까 싶네요.

  • hyunjinnn

    잘봤습니다~!! 감사합니다. 좋은 내용입니다.

  • MainActivity를 제외한 나머지 자바소스는 zxing의 오픈소스를 활용하신건가요???
    만약 활용하셨다면 어떤부분 혹은 어떤파일인가요??

    그리고 res부분의 xml은 직접 작업하신건가요???
    (AndroidManifest포함)

  • ironheel

    qr코드 관련 자료를 찾고 있었는데
    딱 맞는 자료를 찾게 되네요.

    올려주신 자료 고맙게 쓰겠습니다.
    감사합니다.

  • 정말 꼭 필요한 형태의 소스로 만들어 두셨네요.
    너무 감사합니다!

  • 붕냥붕

    오.. 정말 좋은 정보 감사합니다.
    잘 보고 가요^^ 땡큐땡큐땡큐x100

  • simons9989

    아이님 정말 좋은자료 잘보고갑니다~!^^
    그런데 몇까지 궁금한점이 있어서요ㅠㅠ
    지금QRcode를 인식한 후에 인식한 QRcode를 canvas안에다가 띄우는데 그 QRcode가 제대로 나오지가 않습니다
    그래서말인데 canvas에 QRcode bitmap을 인식한 후 띄우는 부분을 좀 컨트롤 하고 싶은데 어딘지좀 알려주실 수 있을까요??

  • 구루미쒸

    QR 코드 인식하고 나면 잠시 떠있는 이지미가 있던데요
    혹시 이걸로 네이버에서 구현한
    내부 이미지를 이용해서
    QR 코드 인식하는 형식으로도 바꿀수 있을까요 ?
    혹시 어디 부분에서 그걸 할수 있는지 아시는가요

  • 프로젝트

    안녕하세요!
    저희 학교 프로젝트를 하던 도중 이 소스가 꼭 필요하여 사용하려고 했는데.. 약간의 에러과정이 있습니다. 잘 모르겟어서 도움을 청하고자 메일을 보내드렸으니.. 꼭 확인해보시고 도움을 주신다면 정말 감사드리겠습니다.

  • 안드로이드잘하고시퓨

    제가 소스를 다운받고 임포트해서 넥서스s에서 실행시키니깐
    바코드 스캐너 띄우기 버튼이 뜨길래 누르니
    ORCode/Barcode
    Scanner(이)가 중지되었습니다.
    라고뜨네요 왜그럴까요??

    • 안드로이드잘하고시퓨

      이거는 로그캣입니다
      03-16 03:57:57.992: E/AndroidRuntime(7651): FATAL EXCEPTION: main
      03-16 03:57:57.992: E/AndroidRuntime(7651): java.lang.ExceptionInInitializerError
      03-16 03:57:57.992: E/AndroidRuntime(7651): at java.lang.Class.newInstanceImpl(Native Method)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at java.lang.Class.newInstance(Class.java:1319)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.Instrumentation.newActivity(Instrumentation.java:1053)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1974)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.ActivityThread.access$600(ActivityThread.java:130)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.os.Handler.dispatchMessage(Handler.java:99)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.os.Looper.loop(Looper.java:137)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at android.app.ActivityThread.main(ActivityThread.java:4745)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at java.lang.reflect.Method.invokeNative(Native Method)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at java.lang.reflect.Method.invoke(Method.java:511)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
      03-16 03:57:57.992: E/AndroidRuntime(7651): at dalvik.system.NativeStart.main(Native Method)
      03-16 03:57:57.992: E/AndroidRuntime(7651): Caused by: java.lang.NoClassDefFoundError: com.google.zxing.ResultMetadataType
      03-16 03:57:57.992: E/AndroidRuntime(7651): at com.google.zxing.client.android.CaptureActivity.(CaptureActivity.java:70)
      03-16 03:57:57.992: E/AndroidRuntime(7651): … 15 more

    • 비밀

      혹시 이런 경우 있으신분들은 lib 폴더를 libs 로 변경하시고 빌드페치 에서 core.jar 를 지워 주면 됩니다

  • 강준호

    이것또한 바코드 스캐너가 설치되어있어야만 정상작동하네요.

    소스들을 포함해서 작성하는게 목적이 아니었던가요?

  • zxing

    올려주신 예제에 포함된 zxing이 몇버젼 인가요?

  • 비밀

    유용한 소스 감사합니다.. 이소스로 자신의 어플만 실행 하도록 처리 하고 싶으신분들을 위해 몇가지 알려 드릴깨요..
    IntentIntegrator.class 에서
    Intent intentScan = new Intent(“com.google.zxing.client.android.SCAN”); 부분을
    Intent intentScan = new Intent(activity, CaptureActivity.class); 바꾸시고요.
    CaptureActivity.class 에서
    if (intent != null && action != null) { 부분에 elas 부분에 source = Source.NATIVE_APP_INTENT;
    decodeFormats = DecodeFormatManager.parseDecodeFormats(intent);
    characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET); 추가 해부시면 됩니다 이상입니다