Android에서 QR 코드 생성하기

최근 몇 년 사이 모바일 기기의 보급과 함께 QR 코드는 일상생활 전반에 깊숙이 자리 잡았다. 특히 모바일 결제, 명함 공유, URL 접속 등 다양한 분야에서 활용되며 사용자 경험을 풍부하게 하고 있다. 이번 글에서는 Android 애플리케이션 내에서 개인 정보를 담은 QR 코드를 동적으로 생성하는 방법을 살펴볼 것이다.

복잡한 알고리즘 구현 없이도 효과적으로 QR 코드를 생성할 수 있도록, 본 예제에서는 오픈소스 라이브러리인 ZXing (Zebra Crossing)의 핵심 JAR 파일을 활용한다. 해당 라이브러리는 바코드 및 QR 코드 인코딩/디코딩 기능을 제공하며, 안정성과 호환성이 검증되어 널리 사용되고 있다. 필요한 core.jar 파일은 공개된 링크나 Maven 저장소를 통해 다운로드할 수 있다.

1. 프로젝트 설정 및 라이브러리 추가

Android Studio에서 새 프로젝트를 생성한 후, app/libs 디렉터리에 다운로드한 core.jar 파일을 복사한다. 이후 프로젝트 구조에서 해당 JAR 파일을 의존성으로 등록해야 한다. Gradle을 사용한다면 다음과 같이 선언할 수도 있다:

implementation files('libs/core.jar')

2. UI 레이아웃 설계

QR 코드 출력 영역과 입력 폼을 포함하는 간단한 인터페이스를 구성한다. 사용자가 회사명, 전화번호, 이메일, 웹사이트 등을 입력하면 이를 기반으로 vCard 형식의 문자열을 생성하고, 그 결과를 이미지로 시각화한다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <LinearLayout
        android:id="@+id/input_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/qrcode_display"
            android:layout_width="180dp"
            android:layout_height="180dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="24dp" />

        <EditText
            android:id="@+id/edit_company"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="회사명 (선택)" />

        <EditText
            android:id="@+id/edit_phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="전화번호 (선택)"
            android:inputType="phone" />

        <EditText
            android:id="@+id/edit_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="이메일 주소 (선택)"
            android:inputType="textEmailAddress" />

        <EditText
            android:id="@+id/edit_website"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="웹사이트"
            android:text="http://" />

        <Button
            android:id="@+id/btn_generate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="QR 코드 생성" />
    </LinearLayout>
</RelativeLayout>

3. 액티비티 로직 구현

입력값을 수집하여 vCard 포맷의 문자열로 변환하고, ZXing 라이브러리를 사용해 QR 코드 비트맵을 생성한다. 중앙에 로고 이미지를 삽입하는 기능도 포함하여 시각적 완성도를 높였다.

public class QRGeneratorActivity extends AppCompatActivity {

    private EditText editCompany, editPhone, editEmail, editWebsite;
    private ImageView qrcodeView;
    private Bitmap logoBitmap;
    private static final int LOGO_SIZE_RATIO = 50; // 로고 크기 조절 기준

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_generator);

        initializeViews();
        logoBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.app_logo);
    }

    private void initializeViews() {
        editCompany = findViewById(R.id.edit_company);
        editPhone = findViewById(R.id.edit_phone);
        editEmail = findViewById(R.id.edit_email);
        editWebsite = findViewById(R.id.edit_website);
        qrcodeView = findViewById(R.id.qrcode_display);

        findViewById(R.id.btn_generate).setOnClickListener(v -> generateQRCode());
    }

    private void generateQRCode() {
        String company = editCompany.getText().toString().trim();
        String phone = editPhone.getText().toString().trim();
        String email = editEmail.getText().toString().trim();
        String website = editWebsite.getText().toString().trim();

        StringBuilder vcard = new StringBuilder("BEGIN:VCARD\nVERSION:3.0");
        if (!company.isEmpty()) vcard.append("\nORG:").append(company);
        if (!phone.isEmpty()) vcard.append("\nTEL:").append(phone);
        if (!email.isEmpty()) vcard.append("\nEMAIL:").append(email);
        if (!website.isEmpty()) vcard.append("\nURL:").append(website);
        vcard.append("\nEND:VCARD");

        try {
            Bitmap qrBitmap = createQRWithLogo(vcard.toString(), logoBitmap);
            qrcodeView.setImageBitmap(qrBitmap);
        } catch (WriterException e) {
            Toast.makeText(this, "QR 생성 실패", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    private Bitmap createQRWithLogo(String content, Bitmap logo) throws WriterException {
        MultiFormatWriter writer = new MultiFormatWriter();
        Hashtable hints = new Hashtable<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        BitMatrix result = writer.encode(content, BarcodeFormat.QR_CODE, 400, 400, hints);
        int width = result.getWidth();
        int height = result.getHeight();
        int[] pixels = new int[width * height];

        int halfWidth = width / 2;
        int halfHeight = height / 2;
        int logoHalfSize = LOGO_SIZE_RATIO;

        Bitmap scaledLogo = Bitmap.createScaledBitmap(
                logo,
                logoHalfSize * 2,
                logoHalfSize * 2,
                false
        );

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (result.get(x, y)) {
                    int pixelX = x - halfWidth + logoHalfSize;
                    int pixelY = y - halfHeight + logoHalfSize;

                    if (x >= halfWidth - logoHalfSize && x < halfWidth + logoHalfSize &&
                        y >= halfHeight - logoHalfSize && y < halfHeight + logoHalfSize) {
                        pixels[y * width + x] = scaledLogo.getPixel(pixelX, pixelY);
                    } else {
                        pixels[y * width + x] = 0xFF000000;
                    }
                } else {
                    pixels[y * width + x] = 0xFFFFFFFF;
                }
            }
        }

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }
}

위 코드는 입력된 정보를 기반으로 표준적인 vCard 형식의 문자열을 만들어내며, 이를 QR 코드로 인코딩한다. 중앙에 앱 로고를 삽입함으로써 브랜드 인지도를 강화할 수 있으며, 시각적으로도 더 매력적인 결과물을 얻을 수 있다.

태그: Android QR Code ZXing Barcode vCard

6월 20일 19:01에 게시됨