diff --git a/app/src/androidTest/java/im/status/hardwallet_lite_android/ExampleInstrumentedTest.java b/app/src/androidTest/java/im/status/hardwallet_lite_android/ExampleInstrumentedTest.java deleted file mode 100644 index dad4568..0000000 --- a/app/src/androidTest/java/im/status/hardwallet_lite_android/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package im.status.hardwallet_lite_android; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("im.status.hardwallet_lite_android", appContext.getPackageName()); - } -} diff --git a/app/src/main/java/im/status/hardwallet_lite_android/app/MainActivity.java b/app/src/main/java/im/status/hardwallet_lite_android/app/MainActivity.java deleted file mode 100644 index 27baabd..0000000 --- a/app/src/main/java/im/status/hardwallet_lite_android/app/MainActivity.java +++ /dev/null @@ -1,43 +0,0 @@ -package im.status.hardwallet_lite_android.app; - -import android.nfc.NfcAdapter; -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; -import im.status.hardwallet_lite_android.R; -import im.status.hardwallet_lite_android.io.CardManager; - -import java.security.Security; - -public class MainActivity extends AppCompatActivity { - static { - Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); - } - - private NfcAdapter nfcAdapter; - private CardManager cardManager; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - nfcAdapter = NfcAdapter.getDefaultAdapter(this); - this.cardManager = new CardManager(); - this.cardManager.start(); - } - - @Override - public void onResume() { - super.onResume(); - if (nfcAdapter != null) { - nfcAdapter.enableReaderMode(this, this.cardManager, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null); - } - } - - @Override - public void onPause() { - super.onPause(); - if (nfcAdapter != null) { - nfcAdapter.disableReaderMode(this); - } - } -} diff --git a/app/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java b/app/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java deleted file mode 100644 index cd55e41..0000000 --- a/app/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java +++ /dev/null @@ -1,101 +0,0 @@ -package im.status.hardwallet_lite_android.io; - -import android.nfc.NfcAdapter; -import android.nfc.Tag; -import android.nfc.tech.IsoDep; -import android.util.Log; -import im.status.hardwallet_lite_android.wallet.WalletAppletCommandSet; -import org.spongycastle.util.encoders.Hex; - -import java.io.IOException; - -public class CardManager extends Thread implements NfcAdapter.ReaderCallback { - private static final String TAG = "CardManager"; - - private IsoDep isoDep; - private boolean isRunning; - - public boolean isConnected() { - return this.isoDep != null && this.isoDep.isConnected(); - } - - @Override - public void onTagDiscovered(Tag tag) { - this.isoDep = IsoDep.get(tag); - - try { - this.isoDep = IsoDep.get(tag); - this.isoDep.connect(); - this.isoDep.setTimeout(120000); - } catch (IOException e) { - Log.e(TAG, "error connecting to tag"); - } - } - - public void run() { - boolean connected = this.isConnected(); - - while(true) { - boolean newConnected = this.isConnected(); - if (newConnected != connected) { - connected = newConnected; - Log.i(TAG, "tag " + (connected ? "connected" : "disconnected")); - - if (connected && !isRunning) { - this.onCardConnected(); - } else { - this.onCardDisconnected(); - } - } - - try { - Thread.sleep(50); - } catch (InterruptedException e) { - Log.e(TAG, "error in TagManager thread: " + e.getMessage()); - this.interrupt(); - } - } - } - - private void onCardConnected() { - this.isRunning = true; - - try { - CardChannel cardChannel = new CardChannel(this.isoDep); - // Applet-specific code - WalletAppletCommandSet cmdSet = new WalletAppletCommandSet(cardChannel); - - // First thing to do is selecting the applet on the card. - cmdSet.select().checkOK(); - - // In real projects, the pairing key should be saved and used for all new sessions. - cmdSet.autoPair("WalletAppletTest"); - - // Opening a Secure Channel is needed for all other applet commands - cmdSet.autoOpenSecureChannel(); - - // We send a GET STATUS command, which does not require PIN authentication - APDUResponse resp = cmdSet.getStatus(WalletAppletCommandSet.GET_STATUS_P1_APPLICATION).checkOK(); - - // PIN authentication allows execution of privileged commands - cmdSet.verifyPIN("000000").checkOK(); - - // Cleanup, in a real application you would not unpair and instead keep the pairing key for successive interactions. - // We also remove all other pairings so that we do not fill all slots with failing runs. Again in real application - // this would be a very bad idea to do. - cmdSet.unpairOthers(); - cmdSet.autoUnpair(); - - Log.i(TAG, "GET STATUS response: " + Hex.toHexString(resp.getData())); - } catch (Exception e) { - Log.e(TAG, e.getMessage()); - } - - this.isRunning = false; - } - - private void onCardDisconnected() { - this.isRunning = false; - this.isoDep = null; - } -} diff --git a/app/src/test/java/im/status/hardwallet_lite_android/ExampleUnitTest.java b/app/src/test/java/im/status/hardwallet_lite_android/ExampleUnitTest.java deleted file mode 100644 index 24683d0..0000000 --- a/app/src/test/java/im/status/hardwallet_lite_android/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package im.status.hardwallet_lite_android; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 47825b2..8d3ef8e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.0' + classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong diff --git a/app/.gitignore b/demo/.gitignore similarity index 100% rename from app/.gitignore rename to demo/.gitignore diff --git a/app/build.gradle b/demo/build.gradle similarity index 77% rename from app/build.gradle rename to demo/build.gradle index 471fe28..a3f84b6 100644 --- a/app/build.gradle +++ b/demo/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { - applicationId "im.status.hardwallet_lite_android" + applicationId "im.status.hardwallet_lite_android.demo" minSdkVersion 19 targetSdkVersion 28 versionCode 1 @@ -19,11 +19,11 @@ android { } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' - implementation 'com.madgag.spongycastle:core:1.58.0.0' - implementation 'com.madgag.spongycastle:prov:1.58.0.0' + + implementation project(':lib') + testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/app/proguard-rules.pro b/demo/proguard-rules.pro similarity index 100% rename from app/proguard-rules.pro rename to demo/proguard-rules.pro diff --git a/app/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml similarity index 77% rename from app/src/main/AndroidManifest.xml rename to demo/src/main/AndroidManifest.xml index 6cedd88..d1d1a3d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -1,9 +1,6 @@ - - - + package="im.status.hardwallet_lite_android.demo"> + + + + + + \ No newline at end of file diff --git a/app/src/main/java/im/status/hardwallet_lite_android/io/APDUCommand.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/APDUCommand.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/io/APDUCommand.java rename to lib/src/main/java/im/status/hardwallet_lite_android/io/APDUCommand.java diff --git a/app/src/main/java/im/status/hardwallet_lite_android/io/APDUException.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/APDUException.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/io/APDUException.java rename to lib/src/main/java/im/status/hardwallet_lite_android/io/APDUException.java diff --git a/app/src/main/java/im/status/hardwallet_lite_android/io/APDUResponse.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/APDUResponse.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/io/APDUResponse.java rename to lib/src/main/java/im/status/hardwallet_lite_android/io/APDUResponse.java diff --git a/app/src/main/java/im/status/hardwallet_lite_android/io/CardChannel.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/CardChannel.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/io/CardChannel.java rename to lib/src/main/java/im/status/hardwallet_lite_android/io/CardChannel.java diff --git a/lib/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java new file mode 100644 index 0000000..883f6ee --- /dev/null +++ b/lib/src/main/java/im/status/hardwallet_lite_android/io/CardManager.java @@ -0,0 +1,76 @@ +package im.status.hardwallet_lite_android.io; + +import android.nfc.NfcAdapter; +import android.nfc.Tag; +import android.nfc.tech.IsoDep; +import android.os.SystemClock; +import android.util.Log; +import java.io.IOException; +import java.security.Security; + +public class CardManager extends Thread implements NfcAdapter.ReaderCallback { + + public CardManager() { + Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); + } + + private static final String TAG = "CardManager"; + + private IsoDep isoDep; + private boolean isRunning; + private OnCardConnectedListener onCardConnectedListener; + + public boolean isConnected() { + return isoDep != null && isoDep.isConnected(); + } + + @Override + public void onTagDiscovered(Tag tag) { + isoDep = IsoDep.get(tag); + + try { + isoDep = IsoDep.get(tag); + isoDep.connect(); + isoDep.setTimeout(120000); + } catch (IOException e) { + Log.e(TAG, "error connecting to tag"); + } + } + + public void run() { + boolean connected = isConnected(); + + while (true) { + boolean newConnected = isConnected(); + if (newConnected != connected) { + connected = newConnected; + Log.i(TAG, "tag " + (connected ? "connected" : "disconnected")); + + if (connected && !isRunning) { + onCardConnected(); + } else { + onCardDisconnected(); + } + } + + SystemClock.sleep(50); + } + } + + private void onCardConnected() { + isRunning = true; + + onCardConnectedListener.onConnected(new CardChannel(isoDep)); + + isRunning = false; + } + + private void onCardDisconnected() { + isRunning = false; + isoDep = null; + } + + public void setOnCardConnectedListener(OnCardConnectedListener onConnectedListener) { + onCardConnectedListener = onConnectedListener; + } +} diff --git a/lib/src/main/java/im/status/hardwallet_lite_android/io/OnCardConnectedListener.java b/lib/src/main/java/im/status/hardwallet_lite_android/io/OnCardConnectedListener.java new file mode 100644 index 0000000..2c368bf --- /dev/null +++ b/lib/src/main/java/im/status/hardwallet_lite_android/io/OnCardConnectedListener.java @@ -0,0 +1,5 @@ +package im.status.hardwallet_lite_android.io; + +public interface OnCardConnectedListener { + void onConnected(CardChannel channel); +} diff --git a/app/src/main/java/im/status/hardwallet_lite_android/wallet/SecureChannelSession.java b/lib/src/main/java/im/status/hardwallet_lite_android/wallet/SecureChannelSession.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/wallet/SecureChannelSession.java rename to lib/src/main/java/im/status/hardwallet_lite_android/wallet/SecureChannelSession.java diff --git a/app/src/main/java/im/status/hardwallet_lite_android/wallet/WalletAppletCommandSet.java b/lib/src/main/java/im/status/hardwallet_lite_android/wallet/WalletAppletCommandSet.java similarity index 100% rename from app/src/main/java/im/status/hardwallet_lite_android/wallet/WalletAppletCommandSet.java rename to lib/src/main/java/im/status/hardwallet_lite_android/wallet/WalletAppletCommandSet.java diff --git a/settings.gradle b/settings.gradle index e7b4def..7f35a15 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ -include ':app' +include ':lib' +include ':demo'