Skywriter is a modern Android application that allows you to browse characters organized by game series, select them visually, and write their NFC data to physical tags using your Android device's NFC capabilities. The app supports multiple tag types including Mifare Classic 1K and NTAG215 tags.
- π± Dual Mode Support: Choose between different character databases and tag types
- π Home Screen: Intuitive mode selection to switch between character types
- π Browse Characters: View all characters organized by game series with collapsible headers
- π Smart Search: Fast partial matching search to quickly find specific characters
- π Character Details: View detailed information including biography, abilities, and element types
- πΎ NFC Writing: Write character data to compatible NFC tags with full verification
- β Tag Compatibility Checker: Comprehensive tool that automatically detects tag type and verifies compatibility
- π§Ή Tag Eraser: Clear tags to a known blank state before writing
- π Automatic Authentication: Extracts and uses authentication keys from source data
- π Real-time Feedback: Progress indicators and detailed status messages
- β Write Verification: Reads back written data to ensure successful writes
- π¨ Beautiful UI: Clean white background with navy blue accents (Material Design 3)
- π± Modern Design: Collapsible game sections, intuitive navigation, and smooth animations
- π‘οΈ Safety First: User-initiated actions only - tap buttons before any NFC operations
β οΈ Smart Warnings: Compatibility checker warns about potential issues before writing- π Error Handling: Graceful handling of locked tags, authentication failures, and incompatible tags
- π± Persistent Header: Logo and menu accessible from all screens
- π Quick Navigation: Logo click returns to home screen
- ποΈ MVVM Architecture: Clean separation of concerns with ViewModels and LiveData
- π§ͺ Comprehensive Testing: Unit tests, instrumented tests, and E2E test coverage
- π¦ Portal Compatible: Writes ALL blocks including sector trailers for full compatibility
- π Key Extraction: Automatically extracts authentication keys from source data
- π± Multi-density Support: Optimized icons and resources for all screen densities
- π Power Management: Keeps screen on during NFC operations to prevent interruptions
- π Connection Management: Automatic reconnection handling for stable NFC operations
Skywriter features a clean, modern design with:
- White Background: Easy on the eyes, professional appearance
- Navy Blue Accents: Primary color (#001F3F) for buttons, headers, and highlights
- Material Design 3: Latest Material Design components and patterns
- Custom Branding: Skywriter logo in app icon and header
- No Drop Shadows: Flat design with clean edges
Screenshots coming soon
- Android Device: Android 7.0 (API 24) or higher with NFC support
- NFC Tags:
- Mifare Classic 1K compatible tags (for character mode)
- NTAG215 tags (for compatible tag mode)
- Android Studio: Latest version recommended (for development)
-
Clone the repository:
git clone https://github.com/BitcoinErrorLog/skywriter.git cd skywriter -
Prepare Character Data:
- Character JSON files should be in
app/src/main/assets/Android_NFC_Data/ - Compatible tag JSON files should be in
app/src/main/assets/Amiibo_NFC_Data/ - The app will automatically load all characters on first launch
- Character JSON files should be in
-
Build the APK:
./gradlew assembleDebug
The APK will be in
app/build/outputs/apk/debug/skywriter.apk -
Install on Device:
- Transfer the APK to your Android device
- Enable "Install from Unknown Sources" if needed
- Install and launch the app
- Launch the app - You'll see the home screen with mode selection
- Choose a Mode:
- Character Mode: For writing character data to Mifare Classic tags
- Compatible Tag Mode: For writing compatible tag data to NTAG215 tags
- Navigate: Use the logo to return home, or the menu button for quick access
- Select Mode - Choose your desired mode from the home screen
- Browse - View all characters organized by game series
- Expand/Collapse Games - Tap game headers to expand or collapse character lists
- Search - Tap the search FAB to quickly find specific characters by name
- View Details - Tap any character card to see detailed information including biography and abilities
-
Select a Character:
- Browse or search to find your desired character
- Tap the character card to open details
-
Start Write Process:
- Tap "Write to Tag" in the character details dialog
- You'll be taken to the write screen
-
Initiate Write:
- Tap the "Write" button (user action required)
- The app will automatically check tag compatibility when tag is detected
- Compatibility check runs automatically - no need to tap again
-
Compatibility Check:
- β Compatible: Writing begins automatically
β οΈ Warning: You can choose to write anyway or cancel- β Incompatible: Detailed error message with recommendations
-
Wait for Completion:
- Watch the progress indicator
- The app verifies writes by reading back data
- Success message appears when complete
- Tag is ready to use
-
Open Tag Checker:
- Tap the menu (three dots) in the toolbar
- Select "Check Tag Compatibility"
-
Check a Tag:
- The checker automatically detects tag type (Mifare Classic or NTAG215)
- Tap the "Check Tag" button (user action required)
- Then tap your phone to the NFC tag
- View detailed compatibility report
-
Review Results:
- See tag type, block/page count, authentication status
- View tag contents and current data
- Read issues and recommendations
- Use "Check Again" to test another tag
-
Open Tag Checker:
- Navigate to the tag checker from the menu
-
Check Tag First:
- Check the tag to see its current state
-
Erase Tag:
- Tap "Erase Tag" button
- Confirm the erase operation
- Tag will be cleared to a blank state
- Verification ensures data was actually erased
- Package Name:
com.bitcoinerrorlog.skywriter - Min SDK: 24 (Android 7.0 Nougat)
- Target SDK: 34 (Android 14)
- Compile SDK: 34
- Build Tools: Latest Android Gradle Plugin
- Language: Kotlin 100%
Mifare Classic 1K Tags:
- Tag Type: Mifare Classic 1K (64 blocks, 16 sectors)
- Authentication: Automatic key extraction from source data
- Block Writing: All 64 blocks including sector trailers
- UID Handling: Graceful handling of locked UID blocks
- Verification: Reads back critical blocks to verify writes
NTAG215 Tags:
- Tag Type: NTAG215 (135 pages, 540 bytes)
- Page-based Writing: Writes all 135 pages including UID pages
- Compatibility Check: Verifies ATQA/SAK and read/write capability
- Write Verification: Reads back critical pages to ensure data was written
- Erase Support: Can erase all data pages to blank state
- Pattern: MVVM (Model-View-ViewModel)
- UI: Material Design 3 Components
- Navigation: AndroidX Navigation Component
- Async: Kotlin Coroutines
- State: LiveData and ViewModel
- Database: JSON-based asset loading (no SQLite)
Portal devices require complete and accurate NFC data to recognize characters. This app ensures full compatibility by:
For Mifare Classic Tags:
- Writes ALL Blocks: Including sector trailers (blocks 3, 7, 11, 15, etc.)
- Extracts Keys: Automatically extracts Key A and Key B from source data
- Proper Authentication: Uses extracted keys for sector authentication
- Complete Data: All 64 blocks written in correct order
- Error Handling: Continues writing even if Block 0 (UID) is locked
- Write Verification: Verifies critical blocks were written correctly
For NTAG215 Tags:
- Writes ALL Pages: All 135 pages including UID pages (if not locked)
- Compatibility Check: Verifies tag is genuine NTAG215 before writing
- Write Verification: Reads back critical pages to ensure data persistence
- Erase Support: Can clear tags to blank state for fresh writes
Mifare Classic: The app extracts authentication keys from the sector trailer blocks in your source data:
- Reads Key A (bytes 0-5) and Key B (bytes 10-15) from each sector trailer
- Uses these keys for authentication before writing each sector
- Falls back to default keys if extraction fails
NTAG215:
- No authentication required (uses NfcA technology)
- Verifies tag type using ATQA and SAK values
- Checks read/write capability before writing
To verify compatibility:
- Write a character to a compatible tag
- Use the tag checker to verify the write was successful
- Place the tag on the portal device
- The portal should recognize the character
Important: Most standard NFC tags have locked UIDs that cannot be changed. This is normal and expected:
- β Character data in data blocks/pages is what the portal primarily reads
- β The app handles locked UIDs gracefully
- β Write verification ensures data was written even if UID is locked
β οΈ For 100% compatibility, you may need UID-changeable tags
Unit Tests (run on JVM):
./gradlew testInstrumented Tests (run on device/emulator):
./gradlew connectedAndroidTestAll Tests:
./gradlew test connectedAndroidTest- β Unit Tests: Data models, NFC writer utilities, erase operations, WriteResult types
- β Instrumented Tests: Database operations, NFC manager functionality, UI navigation
- β E2E Tests: Simulated NFC write flow
Note: Unit tests for NFC operations are limited because Android framework classes cannot be mocked. For comprehensive NFC testing, use instrumented tests with actual hardware or manual testing.
See TESTING_NFC.md and RUN_TESTS.md for detailed testing documentation.
# Build debug APK (automatically copies to root as skywriter.apk)
./gradlew assembleDebug
# Build release APK (automatically copies to root as skywriter.apk)
./gradlew assembleRelease
# Manually copy APK to root (if needed)
./gradlew copyApkToRoot
# Run lint checks
./gradlew lint
# Clean build
./gradlew cleanNote: The APK is automatically copied to the root directory (skywriter.apk) after each build. This makes it easy to find and share the latest build.
skywriter/
βββ app/
β βββ src/
β β βββ main/
β β β βββ java/... # Kotlin source files
β β β βββ res/ # Resources (layouts, strings, icons)
β β β βββ assets/ # JSON character data
β β βββ test/ # Unit tests
β β βββ androidTest/ # Instrumented tests
β βββ build.gradle.kts # App-level build config
βββ gradle/ # Gradle wrapper
βββ archive/ # Archived files (gitignored)
βββ README.md # This file
Data Layer:
CharacterModel: Parcelable data class representing a characterAmiiboModel: Data class for compatible tag dataNFCDatabase: JSON file parsing and character loadingAmiiboDatabase: JSON file parsing for compatible tag dataCharacterRepository: Data access abstractionAmiiboRepository: Data access for compatible tags
NFC Layer:
MifareClassicWriter: Core NFC writing logic with authenticationNTAG215Writer: Writing logic for NTAG215 tagsNFCManager: NFC adapter and tag detection managementTagCompatibilityChecker: Detailed tag compatibility analysis for Mifare ClassicNTAG215CompatibilityChecker: Compatibility checking for NTAG215 tagsTagEraser: Erase functionality for Mifare Classic tagsAmiiboTagEraser: Erase functionality for NTAG215 tagsTagReader: Read tag contents and identify charactersAmiiboTagReader: Read NTAG215 tag contentsWriteResult: Sealed class for operation results
UI Layer:
MainActivity: Host activity with navigation and NFC handlingHomeFragment: Mode selection screenCharacterListFragment: Character browsing with searchAmiiboListFragment: Compatible tag browsing with searchCharacterDetailDialog: Character information displayAmiiboDetailDialog: Compatible tag information displayWriteNFCFragment: NFC writing interface for charactersWriteAmiiboFragment: NFC writing interface for compatible tagsTagCheckFragment: Standalone tag compatibility checker with erase
ViewModel:
CharacterViewModel: State management for character list and searchAmiiboViewModel: State management for compatible tag list and search
Core Android:
- AndroidX Core KTX
- AppCompat
- Material Design Components 3
- Constraint Layout
Architecture:
- Lifecycle (ViewModel, LiveData)
- Navigation Component
- Kotlin Coroutines
Testing:
- JUnit 4
- Mockito
- AndroidX Test
- Espresso
- β Ensure NFC is enabled in device settings
- β Check that device supports the required tag type
- β Verify NFC permissions in app settings
- β Some devices require NFC to be enabled in quick settings
- β Tag may be locked or use non-default keys (app handles this automatically)
- β Tag may not be compatible (use tag checker first)
- β Ensure tag is properly positioned during write (keep steady)
- β Try a different tag if issues persist
- β Check that write verification passed (app verifies writes automatically)
- β Verify JSON files are in the correct assets directory
- β Check JSON file format matches expected structure
- β
Review logcat for parsing errors:
adb logcat | grep Skywriter - β Ensure files are properly formatted JSON (not corrupted)
- β Use the tag checker before writing to verify compatibility
- β Ensure tag matches the selected mode (Mifare Classic or NTAG215)
- β Check that tag is not write-protected
- β Some tags may require specific authentication keys
- β Verify tag type is correctly detected by the checker
- β Ensure you have JDK 17 or higher installed
- β Check that Android SDK is properly configured
- β
Try
./gradlew cleanthen rebuild - β See DEBUGGING.md for debugging tips
- TESTING_NFC.md: Comprehensive NFC testing guide
- RUN_TESTS.md: Quick reference for running tests
- DEBUGGING.md: Debugging tips and log capture
We welcome contributions! Here's how:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Add tests for new functionality
- Run tests:
./gradlew test connectedAndroidTest - Commit your changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Kotlin coding conventions
- Use meaningful variable and function names
- Add comments for complex logic
- Write tests for new features
[Add your license here]
- Built with β€οΈ using Kotlin and Material Design 3
- NFC data format based on Flipper Zero
.nfcfile structure - Designed for compatibility with portal devices
For issues, questions, or contributions:
- Open an issue on GitHub
- Check existing documentation
- Review troubleshooting section above
Made with β€οΈ for the NFC community
β Star this repo if you find it useful!