Here is another medium blog post: this one is about using NFC Reader Mode on Android, which is something that, as the article suggests, does not seem to be well documented in Android.
The source code for this app can be downloaded from github.
Building on Android
It says it has a pre-compiled version in sampleapp, but as far as I can see that is not true. But it does have a gradlew to build it, so let's try that:$ ./gradlew buildOK, fair enough. Let's install OpenJDK 17:
...
> Android Gradle plugin requires Java 17 to run. You are currently using Java 11.
...
$ apt install openjdk-17-jdkOK, try again:
...
The following additional packages will be installed:
libatk-wrapper-java libatk-wrapper-java-jni openjdk-17-jdk-headless openjdk-17-jre openjdk-17-jre-headless
Suggested packages:
openjdk-17-demo openjdk-17-source visualvm fonts-ipafont-mincho
The following NEW packages will be installed
libatk-wrapper-java libatk-wrapper-java-jni openjdk-17-jdk openjdk-17-jdk-headless openjdk-17-jre openjdk-17-jre-headless
0 to upgrade, 6 to newly install, 0 to remove and 30 not to upgrade.
$ ./gradlew buildYeah, OK, I don't remember doing anything with Android on this computer, so I need to go through all of that. Bear with me if you are already familiar with all this:
...
> SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting the sdk.dir path in your project's local properties file at '/home/gareth/acs1552u/AndroidBasicNfcReader/local.properties'.
...
Installing Android Studio
So, basically I'm going to follow these instructions.Bizarrely, the first instruction is to unpack a .tar.gz file. I had to scroll back up to the top of the page to find the link and download it.
Then it says I need to install some 32-bit libraries as I am on a 64-bit system.
$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386And then I can finally unpack the tarball:
...
The following additional packages will be installed:
gcc-12-base:i386 libc6-i386 libcom-err2:i386 libcrypt1:i386 libgcc-s1:i386 libgpm2:i386 libgssapi-krb5-2:i386 libidn2-0:i386 libk5crypto3:i386 libkeyutils1:i386 libkrb5-3:i386 libkrb5support0:i386
libnsl2:i386 libnss-nis:i386 libnss-nisplus:i386 libssl3:i386 libtinfo5:i386 libtirpc3:i386 libunistring2:i386
Suggested packages:
glibc-doc:i386 locales:i386 gpm:i386 krb5-doc:i386 krb5-user:i386
The following NEW packages will be installed
gcc-12-base:i386 lib32z1 libbz2-1.0:i386 libc6:i386 libc6-i386 libcom-err2:i386 libcrypt1:i386 libgcc-s1:i386 libgpm2:i386 libgssapi-krb5-2:i386 libidn2-0:i386 libk5crypto3:i386 libkeyutils1:i386
libkrb5-3:i386 libkrb5support0:i386 libncurses5:i386 libnsl2:i386 libnss-nis:i386 libnss-nisplus:i386 libssl3:i386 libstdc++6:i386 libtinfo5:i386 libtirpc3:i386 libunistring2:i386
0 to upgrade, 24 to newly install, 0 to remove and 30 not to upgrade.
Need to get 10.6 MB of archives.
After this operation, 40.9 MB of additional disk space will be used.
...
$ cd /usr/localAnd run studio:
$ sudo tar xfz ~/Downloads/android-studio-2024.2.2.13-linux.tar.gz
$ cd android-studio/binA lot of output belches forth from this command, but ultimately a window opens and welcomes me "back" to Android. OK, apparently it can find the Android SDK (~/Android/Sdk apparently), even if the gradle build couldn't. It said it would give me the option to install a newer SDK, but that didn't happen, and I rattled along to the end very quickly. This may come back and bite me.
$ ./studio
...
Back to Gradle
Well, if I have done nothing else there, I have "discovered" my Android SDK, so let's go back to gradle and tell it where that is and see if it can make it any further.ANDROID_HOME=$HOME/Android/Sdk JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ ./gradlew buildOK, that looks promising. Do I have an apk or equivalent?
...
> Task :app:lintReportDebug
Wrote HTML report to file:///home/gareth/acs1552u/AndroidBasicNfcReader/app/build/reports/lint-results-debug.html
BUILD SUCCESSFUL in 2m 7s
90 actionable tasks: 90 executed
$ find . -name '*.apk'OK, very good.
./app/build/outputs/apk/debug/app-debug.apk
./app/build/outputs/apk/release/app-release-unsigned.apk
$ file ./app/build/outputs/apk/debug/app-debug.apk
./app/build/outputs/apk/debug/app-debug.apk: Zip archive data, at least v0.0 to extract, compression method=deflate
$ ls -l ./app/build/outputs/apk/debug/app-debug.apk
-rw-rw-r-- 1 gareth gareth 5953392 Jan 14 16:42 ./app/build/outputs/apk/debug/app-debug.apk
Installing on my Phone
Let's try installing that onto my phone (I really don't think that anything NFC related can be reliably tested in the emulator).So, let's plug the phone in and check that everything works:
$ adb devicesOK, no it doesn't. I'm going to say "this happens to me all the time", but one of the things is that I do this relatively rarely, so it doesn't happen "all the time" and then, the next time it does happen, I've forgotten both why it happens and how to fix it. Let me wander off and Google a few things.
List of devices attached
Oh, yes, right. You can't have your "everyday" phone in "developer mode" all the time because there are a handful of apps (for me, all banking apps) that refuse to start with "USB debugging" turned on. So I turn it off, but that is what you need in order to be able to use adb. So I have just turned on "USB Debugging" and "Stay awake" for now. Hopefully I will remember this after I have turned them off and want to come back to this tomorrow :-)
$ adb install app/build/outputs/apk/debug/app-debug.apk
Performing Streamed Install
Success
Testing out what I can see
OK, now can I find that on the phone? Yes, it's where I would expect it to be and called AndroidBasicNfcReader. When I start it up, it says "Please tap a tag to the reader". Let's start with my door key:
The first thing that I notice and find surprising is that it says it has an entry NdefFormatable but then goes on to say "NOT supporting the NDEF class".
What happens when I tap it onto my USB reader? Uh, nothing. Huh? I suppose this has something to do with the fact that it is a reader and not a card. What if I run up show-atr and then tap it?
Hmmm ... still nothing. If I close the app, it beeps in the normal way. OK, what if I try the apdu card emulation that I tried at the end of last episode that failed?
It just says "please insert smart card" as if I wasn't in contact with the reader.
What I can't do, of course, is to tap the phone to itself, but I can use another Android phone with NFC enabled to do that.

So that works at least and gives a reasonable set of answers, but it's interesting that it still isn't supporting the NDEF class.
Looking into the code, it seems the most important thing it does is call enableReaderMode:
protected void onResume() {This is described in the manual page for NfcAdapter and makes it clear that doing this will turn off peer-peer ("Android Beam") mode. So maybe that's something I should be looking for.
super.onResume();
if (myNfcAdapter != null) {
if (!myNfcAdapter.isEnabled())
showWirelessSettings();
Bundle options = new Bundle();
// Work around for some broken Nfc firmware implementations that poll the card too fast
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
// Enable ReaderMode for all types of card and disable platform sounds
// The option NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK is NOT set
// to get the data of the tag after reading
myNfcAdapter.enableReaderMode(this,
this,
NfcAdapter.FLAG_READER_NFC_A |
NfcAdapter.FLAG_READER_NFC_B |
NfcAdapter.FLAG_READER_NFC_F |
NfcAdapter.FLAG_READER_NFC_V |
NfcAdapter.FLAG_READER_NFC_BARCODE |
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
options);
}
}
No comments:
Post a Comment