Skip to content

Commit fd35f4d

Browse files
authored
Merge pull request #224 from nfcim/develop
Release 3.6.1
2 parents 97b7c26 + 0646493 commit fd35f4d

File tree

21 files changed

+300
-210
lines changed

21 files changed

+300
-210
lines changed

.github/workflows/example-app.yml

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,57 @@ on:
88

99
jobs:
1010
build:
11-
runs-on: ubuntu-latest
1211
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
1312

1413
strategy:
1514
fail-fast: false
1615
matrix:
1716
variant: [debug, release]
17+
target: [apk, ios]
18+
include:
19+
- target: apk
20+
os: ubuntu-latest
21+
pre-build-script: ""
22+
build-args: ""
23+
debug-artifact-path: example/build/app/outputs/flutter-apk/app-debug.apk
24+
release-artifact-path: example/build/app/outputs/flutter-apk/app-release.apk
25+
- target: ios
26+
os: macos-latest
27+
pre-build-script: ""
28+
build-args: "--no-codesign"
29+
artifact-path: |
30+
example/build/ios/iphoneos/Runner.app
31+
32+
runs-on: ${{ matrix.os }}
33+
name: ${{ matrix.target }}-${{ matrix.variant }}
1834

1935
steps:
20-
- uses: actions/checkout@v4
21-
- uses: actions/setup-java@v4
36+
- uses: actions/checkout@v6
37+
- uses: actions/setup-java@v5
38+
if: ${{ matrix.target == 'apk' }}
2239
with:
2340
distribution: 'temurin'
2441
java-version: '21'
2542
- uses: subosito/flutter-action@v2
2643
with:
2744
channel: 'stable'
2845
cache: true
29-
- run: dart pub get
30-
- run: dart format --output=none --set-exit-if-changed .
31-
- run: dart analyze
32-
- run: flutter pub get
33-
working-directory: example/
34-
#- run: flutter test
35-
- run: flutter build apk --${{ matrix.variant }} --verbose
36-
working-directory: example/
37-
- uses: actions/upload-artifact@v4
38-
with:
39-
name: example-apk-${{ matrix.variant }}
40-
path: |
41-
example/build/app/outputs/flutter-apk/app-${{ matrix.variant }}.apk
42-
example/build/reports/*
4346

44-
build-ios:
45-
runs-on: macos-latest
46-
strategy:
47-
fail-fast: false
48-
matrix:
49-
variant: [debug, release]
47+
- name: pre-build-script for ${{ matrix.target }}
48+
run: ${{ matrix.pre-build-script }}
49+
if: ${{ matrix.pre-build-script != '' }}
5050

51-
steps:
52-
- uses: actions/checkout@v4
53-
- uses: subosito/flutter-action@v2
54-
with:
55-
channel: 'stable'
56-
cache: true
5751
- run: flutter pub get
5852
working-directory: example/
59-
- run: flutter build ios --${{ matrix.variant }} --verbose --no-codesign
53+
54+
- name: Run flutter ${{ matrix.variant }} build on ${{ matrix.target }}
55+
run: flutter build ${{ matrix.target }} --${{ matrix.variant }} ${{ matrix.build-args }} --verbose
6056
working-directory: example/
57+
58+
- uses: actions/upload-artifact@v5
59+
with:
60+
name: example-${{ matrix.target }}-${{ matrix.variant }}
61+
path: |
62+
${{ matrix.debug-artifact-path }}
63+
${{ matrix.release-artifact-path }}
64+
${{ matrix.artifact-path }}

.github/workflows/publish.yaml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
name: Publish to pub.dev
22

3-
env:
4-
FLUTTER_VERSION: 3.24.5
5-
63
on:
74
push:
85
tags:
@@ -15,13 +12,12 @@ jobs:
1512
id-token: write
1613
runs-on: ubuntu-latest
1714
steps:
18-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@v6
1916
- uses: dart-lang/setup-dart@v1
2017
- name: Setup Flutter SDK
21-
uses: flutter-actions/setup-flutter@v3
18+
uses: flutter-actions/setup-flutter@v4
2219
with:
2320
channel: stable
24-
version: ${{ env.FLUTTER_VERSION }}
2521
cache: true
2622
- name: Install dependencies
2723
run: flutter pub get

.github/workflows/test.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [master, develop]
6+
pull_request:
7+
branches: [master, develop]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
13+
strategy:
14+
matrix:
15+
channel: [stable, beta]
16+
17+
steps:
18+
- uses: actions/checkout@v6
19+
- uses: subosito/flutter-action@v2
20+
with:
21+
channel: ${{ matrix.channel }}
22+
cache: true
23+
- run: dart pub get
24+
- run: dart format --output=none --set-exit-if-changed lib/
25+
- run: dart analyze
26+
# - run: dart test
27+
- run: dart doc
28+
- name: Upload generated dartdoc
29+
uses: actions/upload-artifact@v5
30+
with:
31+
name: docs-${{ matrix.channel }}
32+
path: doc/
33+
- name: Evaluate score with pana
34+
run: |
35+
dart pub global activate pana
36+
dart pub global run pana .

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,15 @@
191191
* Add Swift package manager support for iOS plugin, bump dependencies
192192
* Fix WebUSB interop on Web, add onDisconnect callback
193193
* Add support for foreground polling on Android (#16, #179)
194+
195+
## 3.6.1
196+
197+
* Refactor with new `dart:js_interop` APIs to fix build with WASM (#223)
198+
* Support `readBlock` / `writeBlock` on Mifare tags on iOS (#205 by @rushank-shah)
199+
* More robust logic on Android
200+
* ensure NFC Handler is always alive (#219)
201+
* prevent an NPE due to wrong API typing (#220)
202+
* add comment on `poll` related to Samsung API bug (#190, #200)
203+
* Add more detailed error message in iOS APIs
204+
* Bump tools to Gradle 9.2.1, AGP 8.13.0, Kotlin 2.2.21
205+
* Now `minSdkVersion` is lowered to 24 (#212)

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Flutter NFC Kit
22

33
[![pub version](https://img.shields.io/pub/v/flutter_nfc_kit)](https://pub.dev/packages/flutter_nfc_kit)
4-
![Build Example App](https://github.com/nfcim/flutter_nfc_kit/workflows/Build%20Example%20App/badge.svg)
4+
[![Test](https://github.com/nfcim/flutter_nfc_kit/actions/workflows/test.yml/badge.svg)](https://github.com/nfcim/flutter_nfc_kit/actions/workflows/test.yml)
5+
[![Build Example App](https://github.com/nfcim/flutter_nfc_kit/actions/workflows/example-app.yml/badge.svg)](https://github.com/nfcim/flutter_nfc_kit/actions/workflows/example-app.yml)
56

67
Yet another plugin to provide NFC functionality on Android, iOS and browsers (by WebUSB, see below).
78

@@ -10,9 +11,9 @@ This plugin's functionalities include:
1011
* read metadata and read & write NDEF records of tags / cards complying with:
1112
* ISO 14443 Type A & Type B (NFC-A / NFC-B / MIFARE Classic / MIFARE Plus / MIFARE Ultralight / MIFARE DESFire)
1213
* ISO 18092 (NFC-F / FeliCa)
13-
* ISO 15963 (NFC-V)
14+
* ISO 15693 (NFC-V)
1415
* R/W block / page / sector level data of tags complying with:
15-
* MIFARE Classic / Ultralight (Android only)
16+
* MIFARE Classic / Ultralight (Android only, MIFARE Classic Read & Write block for iOS)
1617
* ISO 15693 (iOS only)
1718
* transceive raw commands with tags / cards complying with:
1819
* ISO 7816 Smart Cards (layer 4, in APDUs)
@@ -35,7 +36,7 @@ We have the following minimum version requirements for Android plugin:
3536

3637
* Java 17
3738
* Gradle 8.9
38-
* Android SDK 26 (you must set corresponding `jvmTarget` in you app's `build.gradle`)
39+
* Android SDK 24 (you must set corresponding `jvmTarget` in you app's `build.gradle`)
3940
* Android Gradle Plugin 8.7
4041

4142
To use this plugin on Android, you also need to:

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ android {
3434
main.java.srcDirs += 'src/main/kotlin'
3535
}
3636
defaultConfig {
37-
minSdkVersion 26
37+
minSdkVersion 24
3838
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
3939
}
4040
lintOptions {

android/gradle.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
org.gradle.jvmargs=-Xmx1536M
1+
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
22
android.enableJetifier=true
3-
AGPVersion=8.7.3
4-
KotlinVersion=2.1.0
3+
AGPVersion=8.13.0
4+
KotlinVersion=2.2.21
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
#Fri Sep 08 22:01:14 CST 2023
21
distributionBase=GRADLE_USER_HOME
32
distributionPath=wrapper/dists
4-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
54
zipStoreBase=GRADLE_USER_HOME
65
zipStorePath=wrapper/dists

android/src/main/kotlin/im/nfc/flutter_nfc_kit/FlutterNfcKitPlugin.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
7171
return transceiveMethod.invoke(this, data) as ByteArray
7272
}
7373

74+
private fun ensureNfcHandler() {
75+
if (!::nfcHandlerThread.isInitialized || !nfcHandlerThread.isAlive) {
76+
nfcHandlerThread = HandlerThread("FlutterNfcKit-NfcHandlerThread").apply { start() }
77+
nfcHandler = Handler(nfcHandlerThread.looper)
78+
}
79+
}
80+
7481
private fun runOnNfcThread(result: Result, desc: String, fn: () -> Unit) {
7582
val handledFn = Runnable {
7683
try {
@@ -89,6 +96,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
8996
}
9097
}
9198
}
99+
ensureNfcHandler()
92100
if (!nfcHandler.post(handledFn)) {
93101
result.error("500", "Failed to post job to NFC Handler thread.", null)
94102
}
@@ -131,7 +139,9 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
131139
type = "iso7816"
132140
val isoDep = IsoDep.get(tag)
133141
tagTechnology = isoDep
134-
historicalBytes = isoDep.historicalBytes.toHexString()
142+
// historicalBytes() may return null but is wrongly typed as ByteArray!
143+
// https://developer.android.com/reference/kotlin/android/nfc/tech/IsoDep#gethistoricalbytes
144+
historicalBytes = (isoDep.historicalBytes as ByteArray?)?.toHexString() ?: ""
135145
}
136146
tag.techList.contains(MifareClassic::class.java.name) -> {
137147
standard = "ISO 14443-3 (Type A)"
@@ -241,9 +251,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
241251
}
242252

243253
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
244-
nfcHandlerThread = HandlerThread("NfcHandlerThread")
245-
nfcHandlerThread.start()
246-
nfcHandler = Handler(nfcHandlerThread.looper)
254+
ensureNfcHandler()
247255

248256
methodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_nfc_kit/method")
249257
methodChannel.setMethodCallHandler(this)

example/android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ android {
4545

4646
defaultConfig {
4747
applicationId "im.nfc.flutter_nfc_kit_example"
48-
minSdkVersion 26
48+
minSdkVersion 24
4949
targetSdkVersion flutter.targetSdkVersion
5050
versionCode flutterVersionCode.toInteger()
5151
versionName flutterVersionName

0 commit comments

Comments
 (0)