# AB Circle Smart Card I/O Android Library

The library "AbcBluetoothTerminalFactory" is a java module for Android applications to communicate with ABC Bluetooth Smart Card Readers through the Java Smart
Card I/O API defined by [JSR 268](https://jcp.org/en/jsr/detail?id=268); to do so the module implements a custom "terminal factory service provider interface"
(TerminalFactorySpi).

The Java Smart Card I/O API defines a Java API for communication with Smart
Cards using ISO/IEC 7816-4 APDUs. It thereby allows Java applications to
interact with applications running on the Smart Card, to store and retrieve data
on the card, etc.

## Supported Readers

- CIR415
- CIR515

## Getting Started

1. Evaluate Bluetooth Demo application by installing android app, see "Evaluate Demo Project - Option 1"
2. Evaluate Bluetooth Demo application source in Android Studio, see "Evaluate Demo Project - Option 2"
3. Install libraries to your user application, see "Installation"

### Development Environment

``` text
Android Studio - Android Studio Quail 1 | 2026.1.1 Patch 1
```

By default, Android Studio does not supply the Java Smart Card I/O classes.
Therefore in order to use the api, the javax.smartcardio package needs to
be manually imported. To make life easy for you we have packaged a copy of
javax.smartcardio package to a module (smartcardio) for you to use.

The library **smartcardio** imports Java packages from OpenJDK8:

``` java
- javax.smartcardio
- sun.net.www
- sun.nio.cs
- sun.security.action
- sun.security.jca
- sun.security.util
```

## Evaluate Demo Project

Option 1 Build demo project from source:

- To evaluate demo project, select Open from File menu on Android Studio. Choose
   "BluetoothDemo".

Option 2 Install APK:

- You can also run the demo project without Android Studio installed. Copy
   "BluetoothDemo-x.y.z.apk" to your Android device. Launch the installation by
   clicking the file icon on any File Explorer application.

## Installation

### Deploy *AB Circle Smart Card I/O Android Library* in User Application

1. To use the class library in your project, create a libs folder in project directory.

2. Copy "smartcardio-x.y.z.jar" and "abcBluetoothTerminalFactory-.x.y.z.aar" into the libs folder.

3. Click File, Project Structure -> Dependencies.

4. Under "Declared Dependencies", press "+" / "Add Dependency" -> "2 JAR/AAR Dependency"

5. Type "libs" into Step 1 box and press OK

6. Add line below to application AndroidManifest.xml

``` xml
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="true" />
```

e.g.

``` xml
    ...
    ...
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="true" />
    
    <application
    ...
    ...
    ...
```

7. Turn on Bluetooth and Request for Fine Location in application (see example code below)

``` java
    private static final int PERMISSION_ALL = 1;

    private static final String[] PERMISSIONS_OLD = {
            android.Manifest.permission.ACCESS_COARSE_LOCATION,
            android.Manifest.permission.ACCESS_FINE_LOCATION,
    };

    private static final String[] PERMISSIONS = {
            android.Manifest.permission.BLUETOOTH_SCAN,
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.ACCESS_COARSE_LOCATION,
            android.Manifest.permission.ACCESS_FINE_LOCATION,
    };

    private void enableBluetooth() {
        BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();

        if (mBtAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        if (!mBtAdapter.isEnabled()) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Bluetooth needs to be enabled, open bluetooth settings?")
                    .setCancelable(false)
                    .setPositiveButton("Yes", (dialog, id) -> startActivity(new Intent(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS)))
                    .setNegativeButton("No", (dialog, id) -> dialog.cancel());
            final AlertDialog alert = builder.create();
            alert.show();
        }

        /**
         Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
         fire an intent to display a dialog asking the user to grant permission to enable it.
         */
        String[] permissions = (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ? PERMISSIONS : PERMISSIONS_OLD;
        if (!hasPermissions(this, permissions)) {
            ActivityCompat.requestPermissions(this, permissions, PERMISSION_ALL);
        }
    }

```

## Notes for Xamarin Library binding; Transforms to add to Metadata.xml

``` xml
<remove-node path="/api/package[@name='sun.security.action']/class[@name='GetPropertyAction']" />

<remove-node path="/api/package[@name='com.abc.terminalfactory']/class[@name='AbCircleBluetoothTerminalFactorySpi']" />
<remove-node path="/api/package[@name='com.abc.terminalfactory']/class[@name='AbCircleBluetoothTerminalProvider']" />
```

## Built With

- [Android Studio](https://developer.android.com/studio) - Android Studio Quail 1 | 2026.1.1 Patch 1

## History

### Bluetooth Demo

V1.5.1
- Updated library to 1.5.1
- Fixed app closing if 2 connected terminals disconnect at the same time
- Updated terminal refresh from systemtest to prevent duplicate logging
- Upgrade Gradle to 9.5.0

V1.5.0
- Updated library to 1.5.0

V1.4.9

- Updated library to 1.4.9

V1.4.8

- Use executorservice to send commands.
- Updated library to 1.4.8

V1.4.7

- Updated library to 1.4.7

V1.4.6

- Added new ACK Protocol setting to demo app.
- Updated library to 1.4.6
- Updated documentation

V1.4.5

- Updated library to 1.4.5
- Upgrade Gradle to 8.0.2

V1.4.4

- Updated library to 1.4.4.
- Upgrade Gradle to 7.3.1
- Change SDK to 33

V1.4.3

- Updated library to 1.4.3.
- Upgrade Gradle to 7.2.1
- Change SDK to 33

V1.4.2

- Updated library to 1.4.2.
- Update Gradle to 7.2.0

V1.4.1

- Updated library to 1.4.1.
- Update app permission request code

V1.4.0

- Added new discover button to demo app.
- Updated library to 1.4.0.

V1.3.2

- Update AbcBluetoothTerminalFactory to 1.3.2

V1.3.1

- Update AbcBluetoothTerminalFactory to 1.3.1
- Upgrade Gradle to 7.0.1
- Increase target version to Android 12
- Add new permissions needed by Android 12
 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

V1.3.0

- Update AbcBluetoothTerminalFactory to 1.3.0
- Added button for
  - disconnecting reader
  - toggling card status monitoring
  - Get Battery level
  - Get Reader FW verison
- Added Scan Filter section to settings page

V1.2.0

- Update AbcBluetoothTerminalFactory to 1.2.0
- Align version with iOS bluetooth Demo

V1.0.5

- Update AbcBluetoothTerminalFactory to 1.0.5
- Update Gradle to 6.5

V1.0.4

- Update AbcBluetoothTerminalFactory to 1.0.4
- Update Gradle to 6.2.2

V1.0.3

- Update AbcBluetoothTerminalFactory to 1.0.3

V1.0.2

- Update AbcBluetoothTerminalFactory to 1.0.2
- Update gradle to 3.6.2

V1.0.1

- Update AbcBluetoothTerminalFactory to 1.0.1

V1.0.0

- Initial release

### AbcBluetoothTerminalFactory

V1.5.1

- Added fix for device names returning null

V1.5.0

- Add support for custom readers

V1.4.9

- Additional thread safety for fifo buffers.

V1.4.8

- Fixed issue where repeated transmit sometimes gave 'Bad Checksum' error.

V1.4.7

- Improved timeout handling

V1.4.6

- Added ACK Protocol support
- New api's for AbCircleBluetoothTerminalManager:
  - setACKProtocolEnabledForReaders: Enables or disables ACK protocol for newly connected terminals
  - getACKProtocolEnabledForReaders: Returns if ACK protocol for terminals is enabled or disabled
- New api's for AbCircleCardTerminalBluetooth:
  - isACKProtocolEnabled: Returns if ACK protocol is enabled or disabled for the terminal
  - getSerialNumber: Returns the serial number of the terminal

V1.4.5

- Fixed issues with library when bluetooth is suddenly turned off
- Release terminals when bluetooth is suddenly turned off
- Improved parameter selection for T=0 cards with non-default timing
- Added new api disablePPS to AbCircleBluetoothTerminalManager to disable card PPS if required

V1.4.4

- Retry PPS with Default speed (0x11) on card connect error
- Fix Android 13 Bluetooth Permissions
- Optimise proguard/obfuscation rules to avoid class name clashes when used with ABC USB library

V1.4.3

Bugfix:
- Fix Extended APDU chaining
  where T=1 (APDU length > max ccid length) && (smaller than (max ccid length * 2))

V1.4.2

- Fix ATR parsing bug introduced in V1.4.1

V1.4.1

- Add Android 12 support.
- Improve ATR T=15 handling

V1.4.0

- Added 4 new APIs for discovery of readers.

V1.3.2

- Add Fidi automatic speed adjustment for contact readers
  
V1.3.1

- Bug fix for Contact Readers
  Send(PPS) when FiDi=0x11 and Card Protocol is T=1

V1.3.0

- Add CIR415_CL  PID, 4001
- Add CIR515_ICC PID, 5000
- Add additional scan filter API
- Add additional RSSI filter API
- Improve scanning reliability in debug mode
- Fix card detection behavior so that the following program flow works:
1.cardTerminals.waitForChange();
2.cardTerminals.list(CardTerminals.State.CARD_INSERTION);
3.cardTerminals.list(CardTerminals.State.CARD_REMOVAL);

V1.2.0

- Align version with iOS library
- Add API to print library version
- Add Bluetooth scan filters (by NAME and by RSSI)

V1.0.5

- Add unit test for ATR parser
- Fix ATR parser based on unit test results: WTI, TCi and TA2.

V1.0.4

- Add API to disconnect Bluetooth Readers
- Add API calls for library to handle activity stop and resume.
- Disable debug messages for GDPR
- card.disconnect(true); now deactivates card instead of resets card.

V1.0.3

- Improve Bluetooth Handling

V1.0.2

- Add Wait Time Extension

V1.0.1

- Bugfix: connecting T=0 card with "*" fails

V1.0.0

- Initial release
- Supports CIR415

### smartcardio

v1.1.0

- Remove unnecessary files

v1.0.0

- Initial release
- Import javax.smartcardio and package dependencies.

## Versioning

We use [SemVer](http://semver.org/) for versioning.

## Authors

- **ABC Software Team**

See also the list of [contributors]() who participated in this project.

## License

``` text
Copyright (c) 2018-2026, AB Circle Ltd. All rights reserved.
```

``` text
OpenJDK
Copyright (c) 1998-2016, Oracle and/or its affiliates. All rights reserved.

This code is free software; you can redistribute it and/or modify itfff
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation.  Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.

This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).

You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
```

``` text
OpenJDK (the "Name") is a trademark of Oracle America, Inc. ("Oracle")
(the "Trademark Owner").
```

``` text
Android is a trademark of Google LLC.

```

``` text
The Bluetooth® word mark and logos are owned by the Bluetooth SIG, Inc.
```
