Skip to content

Repository files navigation

NFCommunicator

Get it on Google Play

NFCommunicator is an Android app from Alsatian Consulting for offline one-message NFC card communication. The app reads, writes, and clears a single AES-256-GCM encrypted message on an NFC tag using a shared password. There is no account, no cloud sync, and no network access. Tags are compatible with any Android device that can access them through standard NDEF APIs, with additional raw MIFARE Classic support on handsets that expose that tech.

What It Does

Core Functionality

NFCommunicator stores one AES-256-GCM encrypted plain-text message on an NFC tag and reads it back using a shared password. Core operations are:

  • Read: hold the tag to the phone on the Read tab. If the tag contains the app's encrypted message, the payload is cached immediately. If a password is already entered it is tried automatically; otherwise you enter the password afterward to decrypt.
  • Write: enter the password twice, type a plain-text message, review the estimated encrypted size for both NDEF and raw MIFARE Classic storage, tap Write to Card, and scan the tag.
  • Clear Card: available from both tabs; overwrites NDEF tags with an empty NDEF message or zeros the app's raw MIFARE Classic storage region.

Tag Modes

NDEF mode: works with any NFC tag Android can access through standard NDEF APIs. Non-NDEF tags can be NDEF-formatted when Android exposes NdefFormatable.

Raw MIFARE Classic mode: preferred automatically when the scanned tag exposes MifareClassic on the device. Intentionally skips sector 0 and all sector trailer blocks to avoid manufacturer data and ACL blocks, giving the app a contiguous storage region for one encrypted message.

UI Details

  • Pending scans lock the active form fields and tabs so the captured password/message cannot drift before the tag is processed.
  • The app gives immediate haptic feedback on tag detection plus a success/error toast and vibration when the NFC operation completes.
  • Password fields are cleared after each completed read, write, or clear operation.
  • The read screen lets you select or copy the decrypted message.
  • When the last scanned tag exposes an exact capacity, the write screen shows the maximum unencrypted character count that fits on that backend and keeps a live character count for the message draft.
  • Raw MIFARE Classic tag summaries show both the app-usable storage estimate and the card's full reported geometry (such as MIFARE Classic 1K, sector count, and total bytes).
  • The selected tab, write draft, and last scanned tag summary survive activity recreation, but passwords and decrypted message text remain memory-only and are not restored from saved state.
  • Reader mode stays active while the app is in the foreground, so tags produce passive detection feedback and update the last scanned tag summary even before Read, Write, or Clear is armed.
  • On the Read tab, passive detection reads and caches compatible encrypted payloads automatically instead of waiting for a manual scan-arm action.
  • If a card is readable but does not contain one of this app's encrypted messages, the read flow reports that directly.
  • Failure states include a secondary diagnostic explanation when the app can narrow the cause to handset support limits, common-key authentication failure, payload incompatibility, or a lost tag during I/O.

Import, Export, and Data Handling

NFCommunicator does not import or export files. The encrypted payload is written to and read from NFC tags only. No data is stored on the device beyond the transient in-memory state for the current session.

How It Does It

Architecture

Primary platform/framework: Android 8.0+ / Kotlin / Jetpack Compose / Gradle.

Key components:

  • MainActivity — single-activity entry point with singleTop launch mode; handles NFC foreground dispatch.
  • Compose UI with two tabs: Read and Write.
  • ViewModel-based state management; tab state, write draft, and last tag summary survive configuration changes.
  • NFC access via NfcAdapter, Tag, Ndef, NdefFormatable, and MifareClassic APIs.
  • AES-256-GCM encryption with PBKDF2-HMAC-SHA256 key derivation; per-message random salt and nonce.

Dependencies: Jetpack Compose BOM, androidx.compose.material3, androidx.compose.material:material-icons-extended, androidx.lifecycle:lifecycle-viewmodel-compose, androidx.lifecycle:lifecycle-runtime-compose, com.google.android.material.

Minification: R8 enabled in release builds. FLAG_SECURE enabled in release; disabled in the screenshot build type.

Processing Logic

  • Encryption: AES-256-GCM. Key derivation: PBKDF2-HMAC-SHA256. Per-message random salt and nonce ensure no two ciphertexts are identical.
  • The payload format is self-describing: the app encodes salt, nonce, and ciphertext together so that Read can detect compatible payloads and report incompatible ones clearly.
  • Storage backend is selected automatically: raw MIFARE Classic when available, NDEF otherwise.

Launch Modes

Normal Launch

Open the installed NFCommunicator app from the Android launcher.

Development Launch

./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

CLI / Headless / Service Mode

Not applicable. NFCommunicator is an Android UI app.

How to Install

Prerequisites

  • Android 8.0+ (min SDK 26), targeting Android 16 (SDK 36)
  • An NFC-capable Android device
  • For building from source: Android Studio or Gradle with JDK 17, Android SDK with API 36

Recommended Installation

Install the pre-built APK from the GitHub releases page:

adb install -r NFCommunicator-1.0-release.apk

Or sideload the APK directly on the device. The signed AAB (NFCommunicator-1.0-release.aab) is the Play Store artifact; the APK is for direct installs.

Signed artifacts are available in playstore/release/1.0/. Verify with:

sha256sum -c playstore/release/1.0/SHA256SUMS.txt

Manual Installation

git clone https://github.com/AlsatianConsulting/NFCommunicator.git
cd NFCommunicator

# Debug build
./gradlew assembleDebug

# Install on connected device
adb install -r app/build/outputs/apk/debug/app-debug.apk

Files to Edit or Create

File Purpose
keystore.properties Release signing; do not commit. Default path: ~/.config/nfccommunicator/keystore.properties
local.properties Set sdk.dir= to your Android SDK path

Override the default signing properties path via environment variable:

export NFC_COMMUNICATOR_SIGNING_PROPERTIES=/path/to/nfcommunicator-signing.properties

Additional Install Modes

Signed Release Build

NFC_COMMUNICATOR_SIGNING_PROPERTIES=/path/to/nfcommunicator-signing.properties \
  ./gradlew assembleRelease bundleRelease

Place keystore.properties at ~/.config/nfccommunicator/keystore.properties (or at the path pointed to by NFC_COMMUNICATOR_SIGNING_PROPERTIES) with the keystore next to it.

Screenshot Build (FLAG_SECURE disabled)

./gradlew assembleScreenshot

Offline Install

No external network access is required at runtime. Gradle dependencies are fetched from Maven Central at build time.

How to Use It

First Run

  1. Launch NFCommunicator. Two tabs appear: Read and Write.
  2. No permissions prompt is required beyond NFC access (enabled at the system level). Grant notification permission if prompted.
  3. Reader mode activates immediately in the foreground; passive tag detection begins.

Common Workflows

  1. Read an encrypted tag: on the Read tab, hold the tag to the phone. If the tag contains the app's encrypted message, it is cached. Enter the password and tap Decrypt.
  2. Write an encrypted message: on the Write tab, enter the password twice, type your message, tap Write to Card, and scan the tag.
  3. Clear a tag: tap Clear Card from either tab, then scan the tag to erase the app's payload.

Usage Examples

Write tab → enter password → confirm password → type message → tap "Write to Card" → scan tag
Read tab → scan tag → enter password → view decrypted message → copy to clipboard
Either tab → tap "Clear Card" → scan tag → payload erased

Configuration

Setting Location Description Default
FLAG_SECURE build.gradle.kts build type Blocks screenshots in production Enabled in release
NFC foreground dispatch MainActivity Keeps reader mode active in foreground Always on

Data Storage and Exports

  • No data is persisted to device storage.
  • Passwords and decrypted message text are in-memory only and are not restored after activity recreation.
  • Tab selection, write draft, and last scanned tag summary survive configuration changes (device rotation) but are not saved across app restarts.
  • Nothing leaves the device.

Screenshots

Screenshots are available in playstore/screenshots/selected/:

Read Tab — Default

Read Default

Write Tab — Default

Write Default

Write Tab — Filled

Write Filled

Write Tab — Pending Scan

Write Pending

Write Tab — Cancelled

Write Cancelled

Clear Pending

Clear Pending

Read Tab — Active

Read Tab

Read Tab — Password Entered

Read Password Entered

Read Tab — No Tag Error

Read No Tag Error

About

NFCommunicator
Version 1.0
(c) Alsatian Consulting, LLC 2026
GitHub: https://github.com/AlsatianConsulting
Website: https://www.alsatian.consulting

Check for Updates

Production GitHub repository must be selected before release wiring or code signing.

Troubleshooting

Installer Fails

Run the manual installation steps above. Confirm ANDROID_HOME or sdk.dir in local.properties is set correctly.

App Launches but Does Not Work

  • Confirm NFC is enabled on the device (Settings > Connected Devices > NFC).
  • Confirm the app is in the foreground when scanning (NFC foreground dispatch is active only while the app is on screen).
  • Check Android logcat for NFC dispatch errors: adb logcat -s NfcDispatch NFCommunicator.

Missing Data or Empty Results

  • If a card reads as incompatible, it either has no payload or was written by a different app or format.
  • Verify the password used for reading matches the password used for writing.
  • If MIFARE Classic authentication fails, the tag may use non-default sector keys; the app uses standard transport keys.

Permission Problems

Permission Purpose
android.permission.NFC Required for all tag operations
android.permission.VIBRATE Haptic feedback on scan events

No additional permissions are required. If NFC is unavailable or disabled, the app will not function.

Testing and Validation

# Unit tests
./gradlew :app:testDebugUnitTest

# Build for screenshot validation
./gradlew assembleScreenshot

Release artifact verification:

sha256sum -c playstore/release/1.0/SHA256SUMS.txt
File SHA-256
NFCommunicator-1.0-release.apk b4c76a9480a922b94bfe498c8502c38ddae4a74eb35675fae693760d6e5be9b0
NFCommunicator-1.0-release.aab c4baf5eb3bc97683048dc2de90cf15b8ddbba479175d4c6b02f04b9aafb0bbc5

Project Layout

NFCommunicator/
├── README.md
├── RELEASE.md
├── LICENSE
├── build.gradle.kts           — root build
├── settings.gradle.kts
├── gradle.properties
├── keystore.properties.example
├── app/
│   ├── build.gradle.kts       — versionCode=1, versionName=1.0, minSdk=26, compileSdk=36
│   ├── lint.xml
│   └── src/main/
│       └── AndroidManifest.xml
└── playstore/
    ├── metadata/              — Play Store listing text
    ├── screenshots/           — selected/ and raw/
    ├── release/1.0/           — signed APK, AAB, SHA256SUMS.txt
    ├── privacy-policy.html
    ├── icon-512x512.png
    └── feature-graphic-1024x500.png

Known Limitations

  • One message per card: only one encrypted payload can be stored per tag; there is no multi-message or multi-key mode.
  • Offline only: no accounts, sync, or stored passwords. Password sharing between sender and recipient must happen out-of-band.
  • MIFARE Classic handset dependency: raw MIFARE Classic support requires the handset to expose the MifareClassic tech. Some devices (particularly those using certain NXP NFC controller firmware) do not expose this API even for compatible tags.
  • No key management: the app does not store, manage, or recover passwords. A forgotten password means the encrypted payload on the tag is unrecoverable.
  • Android 8.0+ required: minSdk = 26.

Privacy and Security

  • Encryption: AES-256-GCM. Key derivation: PBKDF2-HMAC-SHA256. Per-message random salt and nonce.
  • No data stored on device: passwords and decrypted messages are in-memory only and cleared after each operation.
  • No network access: no internet permission is declared.
  • allowBackup="false" and dataExtractionRules prevent OS-level backup of app data.
  • FLAG_SECURE blocks screenshot and screen-recording capture in production builds.
  • Nothing leaves the device unless the user copies the decrypted message to another app.

Release Notes

Version 1.0 (versionCode 1) — 2026-05-11

  • Initial release.
  • AES-256-GCM encryption with PBKDF2-HMAC-SHA256 key derivation.
  • NDEF read/write/clear.
  • Raw MIFARE Classic read/write/clear on compatible handsets.
  • Automatic backend selection (MIFARE Classic preferred when available).
  • Dark Material 3 theme built from #E87722.
  • Passive foreground tag detection on Read tab.
  • Clear diagnostics for unsupported tags, wrong passwords, payload format errors, and tag-loss events.

Latest signed artifact: playstore/release/1.0/NFCommunicator-1.0-release.aab (Play Store) and playstore/release/1.0/NFCommunicator-1.0-release.apk (direct install).

License

Copyright (c) Alsatian Consulting, LLC.

Licensed under the Apache License, Version 2.0. See LICENSE.

About

A secure offline NFC messaging tool that lets users store, share, update, and erase encrypted text directly on NFC tags without requiring cloud services or network connectivity.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages