# Generate a QR code in Kotlin

> On Android, BarcodeEncoder from zxing-android-embedded produces a Bitmap in one call: BarcodeEncoder().encodeBitmap(text, BarcodeFormat.QR_CODE, 512, 512). Display it in Compose via asImageBitmap(). For styled codes, fetch the keyless API inside a coroutine on Dispatchers.IO, or load its URL directly with an image library.

Source: https://useqr.app/docs/developers/generate-a-qr-code-in-kotlin · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## BarcodeEncoder: ZXing without the ceremony

Raw ZXing on Android means BitMatrix-to-Bitmap plumbing (the JVM version is on the
[Java page](/docs/developers/generate-a-qr-code-in-java)). The
`zxing-android-embedded` wrapper collapses it to one call:

```kotlin
// build.gradle.kts
implementation("com.journeyapps:zxing-android-embedded:4.3.0")
```

```kotlin
import com.google.zxing.BarcodeFormat
import com.journeyapps.barcodescanner.BarcodeEncoder

val bitmap = BarcodeEncoder()
    .encodeBitmap("https://example.com", BarcodeFormat.QR_CODE, 512, 512)
```

Generation is on-device, which is exactly right for sensitive payloads — a WiFi password or
contact card should never leave the phone just to become pixels (see
[client-side vs server-side generation](/docs/security/client-side-vs-server-side-qr-generation)).

## Display in Jetpack Compose

`remember(value)` keeps regeneration off every recomposition:

```kotlin
@Composable
fun QrCode(value: String, modifier: Modifier = Modifier) {
    val bitmap = remember(value) {
        BarcodeEncoder().encodeBitmap(value, BarcodeFormat.QR_CODE, 512, 512)
    }
    Image(
        bitmap = bitmap.asImageBitmap(),
        contentDescription = "QR code linking to $value",
        modifier = modifier,
    )
}
```

Give `contentDescription` the destination, not the word "QR code" — TalkBack users cannot
scan the image, so also surface the underlying link as a tappable element. Render the code
on a white surface: a bitmap on a dark theme background can end up effectively inverted,
which many scanners [refuse to read](/docs/design/why-light-on-dark-qr-codes-fail).

## The keyless API with coroutines

For styling (colours, module and eye shapes) or typed payloads with validation
(`/api/v1/wifi`, `/api/v1/upi`), fetch the
[keyless API](/docs/developers/free-qr-code-api-no-key) — no key, no SDK:

```kotlin
suspend fun fetchQr(data: String): ByteArray = withContext(Dispatchers.IO) {
    val encoded = URLEncoder.encode(data, "UTF-8")
    URL("https://useqr.app/api/v1/qr?data=$encoded&size=1024&ec=Q").readBytes()
}

// decode for display:
val bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
```

`URLEncoder.encode` is mandatory — an unencoded `&` truncates the payload server-side with
no error. If you already ship an image loader such as Coil, skipping the manual fetch and
handing it the API URL directly is simpler still, and the response's immutable cache
headers mean each payload downloads once.

## Verify styled output

If you restyle a code, prove it still decodes. ZXing can round-trip on-device, or one GET
does it server-side:

```kotlin
val report = URL("https://useqr.app/api/v1/verify?data=$encoded&color=6366f1").readText()
// JSON: { "scannable": true, "issues": [] }
```

Why this step matters — especially with logos and brand colours — is covered in
[why verify that your QR code decodes](/docs/developers/why-verify-that-your-qr-code-decodes),
and ZXing's decoder is compared with the alternatives in
[zxing vs quirc vs zbar](/docs/developers/zxing-vs-quirc-vs-zbar).

## FAQ

### What is the easiest way to generate a QR code on Android?
BarcodeEncoder from the zxing-android-embedded library: one call from text to Bitmap, entirely on-device, no network permission needed.

### How do I show a generated QR code in Jetpack Compose?
Wrap the encodeBitmap call in remember keyed on the value, convert with asImageBitmap(), and pass it to Image with a meaningful contentDescription.

### Should I generate on-device or call an API?
On-device for credentials and personal data. The API earns its place for styled output, typed payload validation, and server-side or backend-driven codes.

### Why does my QR code not scan in dark mode?
The background. Keep the code's own background white regardless of theme — a transparent or dark-themed backdrop inverts the code for many scanners.

## Try it

- https://useqr.app/url
- https://useqr.app/json
- https://useqr.app/validate
