Skip to content

Commit

Permalink
Add external NFC service source code
Browse files Browse the repository at this point in the history
  • Loading branch information
skjolber committed Oct 3, 2019
1 parent 98c838e commit 5390a02
Show file tree
Hide file tree
Showing 239 changed files with 23,259 additions and 51 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.DS_Store
/build
/captures
build/

# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
Expand Down
42 changes: 26 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
# External NFC Service API (native style) for Android

This API is for interaction with the [External NFC Service](https://play.google.com/store/apps/details?id=com.skjolberg.nfc.external) app found in Google Play.

The [External NFC Service](https://play.google.com/store/apps/details?id=com.skjolberg.nfc.external) app provides NFC-functionality along the lines of native Android NFC for external NFC readers connected via USB.
# External NFC Service API (native style) for Android
Library for interaction with ACS NFC readers over USB for Android devices.

Projects using this library will benefit from:
Features:
- External NFC reader management and interaction
- Parallell use of external and/or internal NFC (i.e. in the same activity, both enabled at the same time)
- Support for both tags and Android devices (Host Card Emulation), simultaneously
- Use of __using Andriod built-in (native) types__ ([Ndef], [MifareUltralight], [IsoDep], etc).

As this project very much simplifies implementation for use-cases requiring external NFC readers, it saves a lot of development time (2-8 weeks depending on use-case and previous knowledge).

# Overview
Bugs, feature suggestions and help requests can be filed with the [issue-tracker].

## License
[Apache 2.0]

# Usage
This repository contains source code for

* An Android library project (the actual API), and
* Demo client apps demonstrating actual usage
* [Basic client app](externalNFCClient)
* [NXP API client](externalNFCNxpClient) for [MIFARE SDK](http://www.mifare.net/en/products/mifare-sdk/)
* [Web Kiosk client](externalNFCWebKiosk) with javascript bindings
* [A server library](externalNFCCore); services for interaction with the readers & tags
* [A client library](externalNFCAPI) (i.e. API), receiving NFC-related intents
* [An NFC library](externalNFCTools) - Android adaptation of NFC Tools
* Demo apps
* [Basic server app](externalNFCService)
* [Basic client app](externalNFCClient)
* [NXP API client](externalNFCNxpClient) for [MIFARE SDK](http://www.mifare.net/en/products/mifare-sdk/)
* [Web Kiosk client](externalNFCWebKiosk) with javascript bindings

There is also a [Host Card Emulation client app](externalNFCHostCardEmulationClient) for use with the [Basic client app](externalNFCClient).

Expand Down Expand Up @@ -105,20 +112,20 @@ You might be interested in

for configuration of your reader. Approximately the same configuration options are available using this API.

# Feature requests
Please email feature requests to [email protected].
# See also
This project contains adapted code from

# Distribution
Get in touch for bulk and/or offline distribution. A library jar is also available on request, simplifying distribution of your own app(s). Source code is also an option.
* NFC Tools for Java
* SMARTRAC SDK for Android NFC NTAG

# Development
# Support
If you need professional, cost-efficient assistance with an NFC project, get in touch. I also do

* Desfire EV1 tech (with encryption) - [example app](https://play.google.com/store/apps/details?id=com.skjolberg.mifare.desfiretool)
* WebView-based apps, either visiting ULRs and/or interaction over Javascript.
* NFC-initiated [wifi connectivity](https://play.google.com/store/apps/details?id=w.i)
* More advanced Host Card Emulation (HCE) for Android
* NFC development tools
* NFC development tools (some are a bit outdatet now)
* [NFC Developer](https://play.google.com/store/apps/details?id=com.antares.nfc)
* [NDEF Tools for Android](https://play.google.com/store/apps/details?id=org.ndeftools.boilerplate&hl=no)
* [Mifare Classic refactor](https://play.google.com/store/apps/details?id=com.skjolberg.nfc.mifareclassic)
Expand All @@ -133,3 +140,6 @@ Feel free to connect with me on [LinkedIn](http://lnkd.in/r7PWDz), see also my [
[MifareUltralight]: https://developer.android.com/reference/android/nfc/tech/MifareUltralight.html
[IsoDep]: https://developer.android.com/reference/android/nfc/tech/IsoDep.html
[Apache Cordova]: https://cordova.apache.org/
[Apache 2.0]: http://www.apache.org/licenses/LICENSE-2.0.html
[issue-tracker]: https://github.com/skjolber/external-nfc-api/issues

13 changes: 12 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.5.1'
}
}

allprojects {
repositories {
google()
jcenter()
}

}

task clean(type: Delete) {
delete rootProject.buildDir
}
6 changes: 5 additions & 1 deletion externalNFCAPI/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ apply plugin: 'com.android.library'

android {
compileSdkVersion 19
buildToolsVersion "27.0.3"
buildToolsVersion "28.0.3"

lintOptions {
abortOnError false
}

defaultConfig {
minSdkVersion 14
Expand Down
4 changes: 0 additions & 4 deletions externalNFCAPI/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,4 @@

<uses-permission android:name="android.permission.NFC" />

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />

</manifest>
10 changes: 5 additions & 5 deletions externalNFCClient/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "27.0.3"
buildToolsVersion "28.0.3"

lintOptions {
abortOnError false
}

defaultConfig {
applicationId "com.skjolberg.nfc.external.client"
Expand All @@ -18,10 +22,6 @@ android {
}
}

repositories {
mavenCentral()
}

dependencies {
api project(':externalNFCAPI')
api 'com.google.code.ndef-tools-for-android:ndeftools:1.2.4'
Expand Down
4 changes: 0 additions & 4 deletions externalNFCClient/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
android:versionCode="3"
android:versionName="1.04" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />

<uses-permission android:name="android.permission.NFC" />

<application
Expand Down
1 change: 1 addition & 0 deletions externalNFCCore/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
47 changes: 47 additions & 0 deletions externalNFCCore/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 19
buildToolsVersion '28.0.3'

lintOptions {
abortOnError false
}

defaultConfig {
minSdkVersion 15
targetSdkVersion 19
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
api project(':externalNFCTools')
compileOnly files('../libs/acssmc-1.1.3.jar')
compileOnly files('../libs/classes-dex2jar.jar')
compileOnly files('../libs/acsbt-1.0.0preview9.jar')

// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.12'
// Optional -- Mockito framework
testImplementation 'org.mockito:mockito-core:1.10.19'
}

task clearJar(type: Delete) {
delete 'build/outputs/ExternalNFCCore.jar'
}

task makeJar(type: Copy) {
from('build/intermediates/bundles/library/')
into('build/outputs/')
include('classes.jar')
rename ('classes.jar', 'ExternalNFCCore.jar')
}

makeJar.dependsOn(clearJar, build)
72 changes: 72 additions & 0 deletions externalNFCCore/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/skjolber/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt

-dontwarn android.nfc.**

-keep public class com.skjolberg.nfc.acs.**
-keep public class com.skjolberg.nfc.NfcReader
-keep public class com.skjolberg.nfc.NfcService
-keep public class com.skjolberg.nfc.NfcTag

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.billing.IInAppBillingService

-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
public void *(android.view.MenuItem);
}

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class * extends android.app.Service {
public static final *;
}

-keep public class com.skjolberg.service.BackgroundUsbService

-keepclassmembers class com.skjolberg.hce.**

-keepclassmembers interface com.skjolberg.hce.**
14 changes: 14 additions & 0 deletions externalNFCCore/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skjolberg.nfc.external.core">

<uses-permission android:name="android.permission.NFC" />

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />


</manifest>
88 changes: 88 additions & 0 deletions externalNFCCore/src/main/java/com/skjolberg/hce/ACRBroadcast.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.skjolberg.hce;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import android.content.Context;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

public class ACRBroadcast {

private static final String TAG = ACRBroadcast.class.getName();

private Context context;

public ACRBroadcast(Context context) {
this.context = context;
}

public void broadcast(String action) {
Intent intent = new Intent();
intent.setAction(action);
sendBroadcast(intent);
}

public void broadcast(String action, String key, boolean value) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtra(key, value);

sendBroadcast(intent);
}

public void broadcast(String action, String key, String value) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtra(key, value);

sendBroadcast(intent);
}

public void broadcast(String action, String key, byte[] value) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtra(key, value);

sendBroadcast(intent);
}

public void broadcast(String action, String key, Parcelable[] value) {
Intent intent = new Intent();
intent.setAction(action);
intent.putExtra(key, value);

sendBroadcast(intent);
}

public void onTagNdefDiscovered(int slotNumber, int[] techList, Bundle[] bundles, Boolean writable, byte[] id, NdefMessage messages, Object instance) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String action = NfcAdapter.ACTION_TAG_DISCOVERED;

final Intent intent = new Intent(action);
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{messages});

Constructor<?>[] constructors = Tag.class.getConstructors();

// public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle, INfcTag tagService)
Parcelable tag = (Parcelable) constructors[0].newInstance(id, techList, bundles, slotNumber, instance);

intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
intent.putExtra(NfcAdapter.EXTRA_ID, id);

Log.d(TAG, "Constructed " + tag);

sendBroadcast(intent);
}


private void sendBroadcast(Intent intent) {
Log.d(TAG, "Broadcast " + intent.getAction());

context.sendBroadcast(intent);
}
}
Loading

0 comments on commit 5390a02

Please sign in to comment.