Created
October 22, 2024 20:09
-
-
Save PaulCreusy/47de0bac3d050b5dba8022d4101621fe to your computer and use it in GitHub Desktop.
NFC Reader Android application with Python and Kivy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__version__ = '1.0' | |
from kivy.app import App | |
from kivy.uix.boxlayout import BoxLayout | |
from kivy.uix.label import Label | |
from kivy.clock import Clock | |
# Android NFC-specific imports | |
from jnius import autoclass, cast | |
from android import activity | |
# Accessing Android NFC Java classes | |
Context = autoclass('android.content.Context') | |
NfcAdapter = autoclass('android.nfc.NfcAdapter') | |
NfcAdapterReader = autoclass('android.nfc.NfcAdapter$ReaderCallback') | |
Ndef = autoclass('android.nfc.tech.Ndef') | |
NdefMessage = autoclass('android.nfc.NdefMessage') | |
Intent = autoclass('android.content.Intent') | |
PendingIntent = autoclass('android.app.PendingIntent') | |
IntentFilter = autoclass('android.content.IntentFilter') | |
NfcAdapter = autoclass('android.nfc.NfcAdapter') | |
class NFCReaderApp(App): | |
def build(self): | |
self.layout = BoxLayout(orientation='vertical') | |
self.label = Label(text="Please scan your NFC card", font_size=42) | |
self.layout.add_widget(self.label) | |
# Schedule the setup of NFC adapter after the app starts | |
Clock.schedule_once(self.setup_nfc, 0) | |
return self.layout | |
def setup_nfc(self, dt): | |
# Get the current Android activity and context | |
self.activity = autoclass('org.kivy.android.PythonActivity').mActivity | |
self.context = self.activity.getApplicationContext() | |
# Get the NFC Adapter | |
self.nfc_adapter = NfcAdapter.getDefaultAdapter(self.context) | |
if not self.nfc_adapter: | |
self.label.text = "NFC not supported on this device." | |
return | |
# Create a PendingIntent to start your app when an NFC tag is discovered | |
intent = Intent(self.context, self.activity.getClass()) | |
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) | |
self.pending_intent = PendingIntent.getActivity( | |
self.context, 0, intent, 0) | |
# Create an intent filter for detecting NFC tags | |
nfc_intent_filter = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED) | |
self.nfc_intent_filter = [nfc_intent_filter] | |
# Enable foreground dispatch to ensure the app catches NFC intents | |
self.nfc_adapter.enableForegroundDispatch( | |
self.activity, self.pending_intent, self.nfc_intent_filter, None) | |
# Bind activity lifecycle events to properly manage NFC (pause/resume) | |
activity.bind(on_new_intent=self.on_new_intent) | |
def on_pause(self): | |
# Disable NFC foreground dispatch when the app goes to background | |
# self.disable_nfc_foreground_dispatch() | |
return True | |
def on_resume(self): | |
# Re-enable NFC foreground dispatch when the app is resumed | |
self.enable_nfc_foreground_dispatch() | |
def enable_nfc_foreground_dispatch(self, *args): | |
print("enable nfc") | |
if self.nfc_adapter: | |
self.nfc_adapter.enableForegroundDispatch( | |
self.activity, self.pending_intent, self.nfc_intent_filter, None) | |
def disable_nfc_foreground_dispatch(self, *args): | |
print("disable nfc") | |
if self.nfc_adapter: | |
self.nfc_adapter.disableForegroundDispatch(self.activity) | |
def on_new_intent(self, intent): | |
# This method is called when an NFC intent is received | |
action = intent.getAction() | |
if action == NfcAdapter.ACTION_TAG_DISCOVERED: | |
self.handle_nfc_tag(intent) | |
def handle_nfc_tag(self, intent): | |
# Get the tag from the intent and cast it to android.nfc.Tag | |
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) | |
if tag is not None: | |
# Cast the Parcelable tag to the correct Tag object | |
tag = cast('android.nfc.Tag', tag) | |
# Get the tag's UID (Unique Identifier) | |
tag_id = tag.getId() | |
tag_uid = ''.join('{:02X}'.format(byte) | |
for byte in tag_id) # Convert to hexadecimal format | |
# Get the list of technologies supported by the tag | |
tech_list = tag.getTechList() | |
# Display the UID and technology list in the app | |
self.label.text = f"Tag UID: {tag_uid}\nTechnologies: {tech_list}" | |
else: | |
self.label.text = "No valid NFC tag detected." | |
if __name__ == "__main__": | |
NFCReaderApp().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment