투케이2K

941. (Android/Java) [라이브러리 버전 변경] zxing 라이브러리 4.3.0 변경 및 QR 스캔 기능 소스 코드 본문

Android

941. (Android/Java) [라이브러리 버전 변경] zxing 라이브러리 4.3.0 변경 및 QR 스캔 기능 소스 코드

투케이2K 2025. 1. 17. 20:00

[개발 환경 설정]

개발 툴 : AndroidStudio

개발 언어 : Java / Kotlin

 

[소스 코드]

 

// --------------------------------------------------------------------------------------
[개발 및 테스트 환경]
// --------------------------------------------------------------------------------------

- 언어 : Java / Kotlin

- 개발 툴 : AndroidStudio

- 기술 구분 : Camera / QR / Barcode

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[사전) 필요 설정] : AndroidManifest 카메라 사용 권한 설정
// --------------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.javaproject">


    <!-- ============================================================= -->
    <!-- [카메라 : QR 스캔] -->
    <!-- ============================================================= -->
    <uses-permission android:name="android.permission.CAMERA"/>


    <application
        android:name=".A_Application">

    </application>

</manifest>

// --------------------------------------------------------------------------------------





// --------------------------------------------------------------------------------------
[소스 코드]
// --------------------------------------------------------------------------------------

// --------------------------------------------------------------
// TODO [SEARCH FAST] : [Observable] : [QR 및 Barcode 스캔 팝업창 호출 메소드]
// --------------------------------------------------------------
// TODO [필요 퍼미션] : 카메라 퍼미션
// --------------------------------------------------------------
// TODO [필요 설치 라이브러리] :
// --------------------------------------------------------------
/*
* // implementation 'com.journeyapps:zxing-android-embedded:3.5.0' // AS-IS
* implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // TO-BE
* implementation "com.google.zxing:core:3.3.0"
* */
// --------------------------------------------------------------
// TODO [호출 방법 소스 코드]
// --------------------------------------------------------------
/*
try {

    // [팝업창 활성 수행]
    C_Ui_View.observable_Qr_Barcode_Scan(A_Intro.this, "Qr 및 Barcode 스캔", "닫기")
            .subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
            .observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
            .subscribe(new Observer<String>() { // [Observable.create 타입 지정]
                @Override
                public void onSubscribe(@NonNull Disposable d) {
                }
                @Override
                public void onNext(@NonNull String value) {
                    S_Log._D_("Qr 및 Barcode 스캔 결과 확인", new String[]{ String.valueOf(value) });
                }
                @Override
                public void onError(@NonNull Throwable e) {
                    S_Log._E_("Qr 및 Barcode 스캔 에러 확인", new String[]{ String.valueOf(e.getMessage()) });
                }
                @Override
                public void onComplete() {
                }
            });

}
catch (Exception e){
    e.printStackTrace();
}
*/
// -----------------------------------------------------------------------------------------
static AlertDialog camera_scan_alert = null;
public static Observable<String> observable_Qr_Barcode_Scan(Activity mContext, String title, String ok){

    // [로직 처리 실시]
    return Observable.create(subscriber -> {

        try {
            // ===============================================================
            S_Log._D_("Qr 및 Barcode 스캔 팝업창 호출 수행 실시", null);
            // ===============================================================


            // [변수 선언]
            if (camera_scan_alert != null){
                camera_scan_alert = null;
            }
            final boolean[] scanFlag = {false}; // [연속 스캔 콜백 방어]


            // TODO [UI 생성 실시] : 커스텀 뷰
            final DecoratedBarcodeView barcodeScannerView = new DecoratedBarcodeView( mContext );
            barcodeScannerView.setPadding(70,70,70,70);

            CameraSettings cameraSettings = new CameraSettings(); // [카메라 설정 관련]
            //cameraSettings.setRequestedCameraId(1); // [전방 카메라]
            cameraSettings.setRequestedCameraId(0); // [후방 카메라]

            barcodeScannerView.getBarcodeView().setCameraSettings(cameraSettings);

            barcodeScannerView.initializeFromIntent(mContext.getIntent());

            barcodeScannerView.resume(); // [수행]


            // TODO [Qr 및 바코드 스캔 이벤트 지정]
            barcodeScannerView.decodeContinuous(new BarcodeCallback() {
                @Override
                public void barcodeResult(BarcodeResult result) {
                    try {

                        if(scanFlag[0] == false){ //TODO [최초 1번 스캔된 경우]

                            String result_data = String.valueOf(result.toString()); // [스캔 결과]

                            S_Log._D_("Qr 및 Barcode 스캔 결과 확인", new String[]{String.valueOf(result_data)});

                            scanFlag[0] = true; // [플래그 값 변경]

                            // [팝업창 생성 실시]
                            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                @Override
                                public void run() {

                                    // [알림 팝업창 표시]
                                    C_Ui_View.observableAlert(mContext, "Qr 및 Barcode 스캔 결과", result_data, "결과 확인", "다시 스캔")
                                            .subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
                                            .observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
                                            .subscribe(new Observer<Boolean>() { // [Observable.create 타입 지정]
                                                @Override
                                                public void onSubscribe(@NonNull Disposable d) {
                                                }
                                                @Override
                                                public void onNext(@NonNull Boolean value) {

                                                    if (value == true){ // [확인 클릭]

                                                        // -----------------------------------------
                                                        // TODO [리턴 데이터 반환]
                                                        // -----------------------------------------
                                                        try {
                                                            subscriber.onNext(result_data);
                                                            subscriber.onComplete();

                                                            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                                                @Override
                                                                public void run() {

                                                                    if (barcodeScannerView != null){
                                                                        barcodeScannerView.pause(); // [스캔 동작 중지 처리]
                                                                    }

                                                                }
                                                            }, 0);

                                                            if (camera_scan_alert != null && camera_scan_alert.isShowing() == true){
                                                                camera_scan_alert.dismiss();
                                                                camera_scan_alert = null;
                                                            }
                                                        }
                                                        catch (Exception ex){
                                                            ex.printStackTrace();
                                                        }
                                                    }
                                                    else { // [취소 클릭]

                                                        // -----------------------------------------
                                                        // TODO [다시 스캔 시도]
                                                        // -----------------------------------------

                                                        scanFlag[0] = false; // [플래그 값 변경]
                                                    }
                                                }
                                                @Override
                                                public void onError(@NonNull Throwable e) {
                                                }
                                                @Override
                                                public void onComplete() {
                                                }
                                            });

                                }
                            }, 0);

                        }
                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }
                }

                @Override
                public void possibleResultPoints(List<ResultPoint> resultPoints) {

                }
            });


            // [팝업창 생성 실시]
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {

                    if (mContext != null){

                        // [AlertDialog 팝업창 생성]
                        camera_scan_alert = new AlertDialog.Builder(mContext)
                                .setTitle(title) //[팝업창 타이틀 지정]
                                //.setIcon(R.drawable.app_icon) //[팝업창 아이콘 지정]
                                //.setMessage("\n") //[팝업창 내용 지정]
                                .setView( barcodeScannerView )
                                .setCancelable(false) //[외부 레이아웃 클릭시도 팝업창이 사라지지않게 설정]
                                .setPositiveButton(ok, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        S_Log._D_("Qr 및 Barcode 스캔 팝업창 ["+String.valueOf(ok)+"] 클릭", null);


                                        // TODO [리턴 데이터 반환]
                                        try {
                                            subscriber.onNext("");
                                            subscriber.onComplete();

                                            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                                @Override
                                                public void run() {

                                                    if (barcodeScannerView != null){
                                                        barcodeScannerView.pause(); // [스캔 동작 중지 처리]
                                                    }

                                                }
                                            }, 0);

                                            if (camera_scan_alert != null && camera_scan_alert.isShowing() == true){
                                                camera_scan_alert.dismiss();
                                                camera_scan_alert = null;
                                            }

                                        }
                                        catch (Exception ex){
                                            ex.printStackTrace();
                                        }

                                    }
                                })
                                .show();


                        // TODO [팝업창 레이아웃 사이즈 변경]
                        //*
                        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
                        Window window = camera_scan_alert.getWindow();
                        lp.copyFrom(window.getAttributes());

                        //lp.width = WindowManager.LayoutParams.MATCH_PARENT;
                        //lp.height = WindowManager.LayoutParams.MATCH_PARENT;

                        //lp.width =  (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 350, mContext.getResources().getDisplayMetrics());
                        //lp.height = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 350, mContext.getResources().getDisplayMetrics());

                        Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
                        DisplayMetrics outMetrics = new DisplayMetrics();
                        display.getMetrics(outMetrics);
                        float density = mContext.getResources().getDisplayMetrics().density;
                        float dpHeight = outMetrics.heightPixels / density;
                        float dpWidth = outMetrics.widthPixels / density;

                        int dpWidthValue = (int)dpWidth;
                        int dpHeightValue = (int)dpHeight;
                        int width = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpWidthValue, mContext.getResources().getDisplayMetrics());
                        int height = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpHeightValue - 50, mContext.getResources().getDisplayMetrics());

                        lp.width =  width;
                        lp.height = height;

                        window.setAttributes(lp);
                        // */


                        // TODO [카메라 권한 부여 상태 확인]
                        if (C_Permission.getCameraPermisseionEnable(mContext) == true){
                            S_Log._W_("Qr 및 Barcode 스캔 : 카메라 권한 상태 확인 : 정상", null);
                        }
                        else {
                            S_Log._E_("Qr 및 Barcode 스캔 : 카메라 권한 상태 확인 : 비정상", null);

                            C_Ui_View.showAlert(mContext, 0, "알 림", "카메라 권한이 비활성 상태입니다. 카메라 권한 활성 후 해당 기능을 사용해주세요.", "확인", "");
                        }

                    }

                }
            }, 0);

        } catch (final Exception e){
            e.printStackTrace();

            // ------------------------------------------------------
            // TODO [리턴 데이터 반환]
            // ------------------------------------------------------
            try {
                subscriber.onNext("");
                subscriber.onComplete();
            }
            catch (Exception ex){
                ex.printStackTrace();
            }
        }

    });
}

// --------------------------------------------------------------------------------------
​

 

반응형
Comments