Canonical version: https://thelooplet.com/posts/best-way-to-integrate-felica-nfc-payments-on-pixel-11-devices
Best Way to Integrate FeliCa NFC Payments on Pixel 11 Devices
TL;DR: Update Pixel 11 to the latest OS, enable the new FeliCa flag in the NFC settings, and use Android’s Host Card Emulation (HCE) together with the Google Payments API. This combination gives you a production‑grade, low‑latency, JPSA‑compliant contact‑less payment solution for Japan today.
Table of Contents
- Why FeliCa Matters for Android Payments in Japan
- Pixel 11 – Hardware & Software Landscape
- Prerequisites – What You Need Before Writing Code
- Detecting FeliCa Capability at Runtime
- Enabling the System‑Level FeliCa Toggle
- Permission Model for FeliCa on Android 13+
- Architecture Overview: HCE + Google Payments API
-
Step‑by‑Step Implementation Guide
8.1. Manifest Declarations
8.2. Service Implementation (
HostApduService) 8.3. UsingFeliCaAdapterfor Command Parsing 8.4. Token Provisioning with Google Payments API 8.5. UI Flow & User Prompting - Testing Strategies 9.1. Unit & Instrumented Tests 9.2. End‑to‑End Tests with POS Emulators 9.3. Performance & Power Profiling 9.4. Automated JPSA Certification in CI/CD
- Deployment Checklist & Release‑Gate Considerations
- Trade‑offs & Design Decisions
- Common Pitfalls & How to Avoid Them
- FAQ for Mobile‑Payment Teams
- Conclusion & Next Steps
Why FeliCa Matters for Android Payments in Japan
| Metric | Value (2024) |
|---|---|
| Share of contact‑less transactions using FeliCa | ≈ 71 % |
| Average transaction time for a transit gate (FeliCa) | ≈ 90 ms |
| Battery impact of a single FeliCa tap (Pixel 11) | 0.8 mW vs 1.2 mW for ISO‑DEP |
Sources: Japan Credit Bureau, Android Authority, Google NFC performance labs.
- Market reach – Over two‑thirds of commuters, retail shoppers, and vending‑machine users rely on FeliCa. Ignoring it means losing a huge user base or forcing users into slower QR‑code alternatives.
- User experience – FeliCa’s sub‑100 ms latency feels instantaneous. By contrast, ISO‑DEP‑based tokenisation typically sits around 130–150 ms, which can be noticeable on busy turnstiles.
- Security & compliance – The Japanese Payment Service Association (JPSA) mandates specific cryptographic handling of FeliCa’s Secure Messaging protocol. Using the official stack removes the need to re‑implement AES‑128 key‑derivation logic yourself.
- Competitive parity – Apple Pay has supported FeliCa since iOS 13. Android’s native support on Pixel 11 finally lets you compete on equal footing.
Pixel 11 – Hardware & Software Landscape
| Aspect | Detail |
|---|---|
| NFC controller | Broadcom BCM20793 (revision B) – firmware updated in Android 13.2.0 to expose a FeliCa‑aware controller. |
| OS version required | Android 13 (API 33) or later. The FeliCa flag is gated behind android.hardware.nfc.felica. |
| SKU variance | All Pixel 11 models ship with the same NFC chip, but the “Pixel 11 Pro (US)” SKU lacks the hardware flag due to a supply‑chain variant. |
| System UI | Settings → Connected devices → NFC now shows a dedicated FeliCa toggle (Android 13.2+). |
| SDK additions |
android.nfc.FeliCaAdapter, android.nfc.FeliCaException, and new manifest feature constant PackageManager.FEATURE_NFC_FELICA. |
Key implication: Your code must detect the feature at runtime and fallback gracefully for the few devices that cannot expose FeliCa, even though they are Pixel 11.
Prerequisites – What You Need Before Writing Code
- Pixel 11 devices running Android 13.2 or newer.
- Google Play Services version 23.5+ (required for the Google Payments API).
- Google Payments API credentials – a service account with the
payments.googleapis.comscope, plus a registered merchant ID in the JPSA sandbox. - Access to a FeliCa‑compatible POS emulator – Google’s
NfcFCardEmulationsample or a third‑party test rig (e.g., Sony RC‑S320). - CI infrastructure capable of flashing devices, running
adbcommands, and collecting logcat output. - Team knowledge of Android’s HCE lifecycle (
onDeactivated,processCommandApdu, etc.) and of FeliCa’s command set (Poll, Request Service, Read/Write Without Encryption).
Detecting FeliCa Capability at Runtime
PackageManager pm = context.getPackageManager();
boolean felicaSupported = pm.hasSystemFeature(PackageManager.FEATURE_NFC_FELICA);
Recommended detection flow
public class FelicaCapability {
private final Context ctx;
public FelicaCapability(Context ctx) {
this.ctx = ctx;
}
/** Returns true if the device can run native FeliCa HCE. */
public boolean isAvailable() {
PackageManager pm = ctx.getPackageManager();
boolean hasFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_FELICA);
if (!hasFeature) return false;
try {
return FeliCaAdapter.getInstance() != null;
} catch (Throwable t) {
return false;
}
}
}
Why not rely on a static build‑time check?
Because the hardware flag is SKU‑specific. Shipping a single APK to the Play Store means you must handle both supported and unsupported devices at runtime; otherwise you risk crashes on the “no‑FeliCa” SKU.
Enabling the System‑Level FeliCa Toggle
Starting with Android 13.2, the Settings UI exposes a dedicated FeliCa switch. Users can turn it off even if the generic NFC toggle is on. Your app should:
- Check the toggle state before attempting a transaction.
- Prompt the user to enable it if it is off.
Detecting the toggle programmatically
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context);
boolean isNfcEnabled = nfcAdapter.isEnabled(); // generic NFC
boolean isFelicaEnabled = Settings.Secure.getInt(
context.getContentResolver(),
"nfc_felica_enabled", 0) == 1;
Note: The key
nfc_felica_enabledis not part of the public API but is documented in the Android 13.2 release notes. Accessing it viaSettings.Secureis safe because it does not require additional permissions.
Prompting the user
Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Best practice: Show this prompt before the first payment attempt (e.g., during onboarding). A/B testing by a large Japanese fintech showed a 12 % increase in successful first‑tap conversions when the prompt appeared on the onboarding screen rather than after a failure.
Permission Model for FeliCa on Android 13+
The new permission android.hardware.nfc.felica is runtime‑protected. Request it just like location or camera permissions.
Manifest entry
<uses-permission android:name="android.hardware.nfc.felica" />
Runtime request (Kotlin example)
if (ContextCompat.checkSelfPermission(this, "android.hardware.nfc.felica")
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf("android.hardware.nfc.felica"),
REQUEST_FELICA_PERMISSION)
}
Handling the callback
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_FELICA_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted – initialise FeliCaAdapter
initFelica();
} else {
// Show a rationale and possibly disable payment UI
showPermissionDeniedDialog();
}
}
}
If the permission is denied, any call to FeliCaAdapter will throw a SecurityException. Guard all NFC‑related code paths with a permission check to avoid crashes.
Architecture Overview: HCE + Google Payments API
+-------------------+ +-------------------+ +-------------------+
| Android App UI | <---> | Host Card Emul. | <---> | Google Payments |
| (on Pixel 11) | | (FeliCa HCE) | | API (cloud) |
^ ^ ^
| | |
| NFC (13.56 MHz, NFC‑F) | Token provisioning |
| | & risk assessment |
+-------------------------------+---------------------------+
- Host Card Emulation (HCE) – The device pretends to be a contact‑less smart card. The POS terminal sends FeliCa‑specific frames (Poll, Request Service, etc.) to the Android HCE service.
-
FeliCaAdapter– High‑level wrapper that parses raw frames into Java objects, builds responses, and throws typed exceptions. It shields you from byte‑array fiddling. -
Google Payments API – Cloud service that:
- Stores encrypted payment credentials in Google’s secure element (or in the “Google Wallet” token vault).
- Performs the cryptographic exchange required by JPSA (AES‑128 key derivation, MAC generation).
- Provides risk‑scoring and fraud‑prevention callbacks.
Result: Your app only needs to forward the raw APDU bytes to the API and return the API’s response. All heavy cryptography stays on Google’s servers, satisfying JPSA’s “no private key on device” rule.
Step‑by‑Step Implementation Guide
8.1. Manifest Declarations
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.felicapay">
<!-- Permissions -->
<uses-permission android:name="android.hardware.nfc" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.hardware.nfc.felica" />
<!-- Feature declaration – makes Play Store filter for devices that might support FeliCa -->
<uses-feature android:name="android.hardware.nfc_felica"
android:required="false" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<service
android:name=".FelicaHceService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
</intent-filter>
<!-- AID list – FeliCa uses a proprietary AID (0xF001) -->
<meta-data
android:name="android.nfc.card.service"
android:resource="@xml/felica_service_aid_list" />
</service>
</application>
</manifest>
res/xml/felica_service_aid_list.xml
<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:requireDeviceUnlock="false"
android:description="@string/felica_service_desc">
<!-- FeliCa AID – 0xF001 (4‑byte) -->
<aid-group android:category="other"
android:description="@string/felica_aid_group">
<aid-filter android:name="F001" />
</aid-group>
</host-apdu-service>
8.2. Service Implementation (HostApduService)
public class FelicaHceService extends HostApduService {
private static final String TAG = "FelicaHceService";
private final FeliCaAdapter felica = FeliCaAdapter.getInstance();
@Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
try {
// 1️⃣ Detect Poll command – the first frame a POS sends to discover a FeliCa card.
if (felica.isPollCommand(commandApdu)) {
Log.d(TAG, "Poll command received");
return felica.buildPollResponse(); // Returns a standard 16‑byte response.
}
// 2️⃣ For everything else, delegate to Google Payments API.
byte[] response = GooglePaymentsApi.handleFelicaCommand(commandApdu);
Log.d(TAG, "GooglePaymentsApi returned " + response.length + " bytes");
return response;
} catch (FeliCaException e) {
// Translate adapter‑level errors into ISO‑DEP status words.
Log.e(TAG, "FeliCa error: " + e.getMessage(), e);
return felica.buildErrorResponse(e.getErrorCode());
} catch (Exception e) {
Log.e(TAG, "Unexpected error in HCE service", e);
// Generic error – 0x6F00 (unknown error)
return new byte[]{(byte) 0x6F, 0x00};
}
}
@Override
public void onDeactivated(int reason) {
Log.i(TAG, "HCE service deactivated, reason=" + reason);
// Reason can be DEACTIVATION_LINK_LOSS or DEACTIVATION_DESELECTED.
// No special cleanup required for FeliCa.
}
}
Key points in the code above
| Point | Reason |
|---|---|
isPollCommand |
The first frame a transit gate sends; handling it locally reduces latency (~ 10 ms saved). |
Delegation to GooglePaymentsApi.handleFelicaCommand
|
Keeps cryptographic logic off‑device and ensures JPSA‑approved key handling. |
| Error mapping |
FeliCaException provides JPSA‑compatible status words (e.g., 0x6A82 – “File not found”). |
onDeactivated |
Required override; helps you log unexpected disconnects for later analysis. |
8.3. Using FeliCaAdapter for Command Parsing
public byte[] buildReadWithoutEncryptionResponse(byte[] command) throws FeliCaException {
// Parse the incoming command
FelicaCommand cmd = felica.parseCommand(command);
if (!cmd.isReadWithoutEncryption()) {
throw new FeliCaException(FeliCaException.ERROR_COMMAND_NOT_SUPPORTED);
}
// Extract block numbers and request data from the command object
List<Integer> blockList = cmd.getBlockList();
byte[] payload = new byte[blockList.size() * 16]; // each block = 16 bytes
// Simulate reading from a secure element (in real code, call GooglePaymentsApi)
for (int i = 0; i < blockList.size(); i++) {
byte[] blockData = GooglePaymentsApi.readBlock(blockList.get(i));
System.arraycopy(blockData, 0, payload, i * 16, 16);
}
// Build the response frame (status word 0x9000 + payload)
return felica.buildResponse(payload, (short) 0x9000);
}
Why use the adapter?
- Reduced boilerplate – No manual byte‑shifting.
- Built‑in validation – The adapter checks CRC, length, and command structure, returning a typed exception if anything is malformed.
- Future‑proof – If Google adds new FeliCa extensions, the adapter will expose them without breaking your code.
8.4. Token Provisioning with Google Payments API
The Google Payments API works in three stages:
- Provisioning – The app requests a virtual card token for the user’s linked payment method.
-
Activation – Google sends the encrypted token to the device’s secure element (or to the
FeliCaAdapterfor in‑memory emulation). - Transaction – Each APDU from the POS is forwarded to the API, which signs the response using the token’s private key.
8.4.1. Provisioning flow (simplified)
public void provisionToken(String userId) {
PaymentsClient client = Payments.getPaymentsClient(context);
TokenRequest request = new TokenRequest.Builder()
.setUserId(userId)
.setCardNetwork(TokenRequest.CardNetwork.VISA) // or MASTERCARD, JCB, etc.
.setPaymentMethod(TokenRequest.PaymentMethod.FELICA)
.build();
client.provisionToken(request)
.addOnSuccessListener(token -> {
// Store the token ID locally (do NOT store the raw key)
tokenStore.saveTokenId(token.getTokenId());
})
.addOnFailureListener(e -> {
Log.e(TAG, "Token provisioning failed", e);
// Show UI error, retry, or fallback to QR‑code flow.
});
}
8.4.2. Handling a transaction APDU
public static byte[] handleFelicaCommand(byte[] apdu) throws IOException {
URL url = new URL("https://payments.googleapis.com/v1/felica/transactions");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + getAccessToken());
conn.setRequestProperty("Content-Type", "application/octet-stream");
conn.getOutputStream().write(apdu);
conn.getOutputStream().flush();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (InputStream in = conn.getInputStream()) {
byte[] buf = new byte[1024];
int read;
while ((read = in.read(buf)) != -1) {
baos.write(buf, 0, read);
}
}
return baos.toByteArray();
}
Security notes
- Never cache the private key on the device; the API returns only a token identifier.
- All calls must use TLS 1.3; the Google Payments client library enforces this automatically.
- Risk‑assessment callbacks – The API may return a
403with ariskScorefield; surface a “transaction declined” UI in that case.
8.5. UI Flow & User Prompting
A smooth onboarding experience reduces abandonment. Recommended flow:
- Welcome screen – Explain “Tap your phone to pay with FeliCa (Japanese transit & retail).”
-
Capability check – Run
FelicaCapability.isAvailable().- If false, show a greyed‑out “FeliCa not supported on this device” badge and enable a QR‑code fallback.
- If true, continue.
-
NFC & FeliCa toggle prompt – If
isNfcEnabledorisFelicaEnabledis false, show a modal with a “Open Settings” button (link toSettings.ACTION_NFC_SETTINGS). -
Permission request – Show a rationale dialog (“We need permission to use FeliCa for secure payments”) before calling
requestPermissions. - Token provisioning – After the user adds a payment method, call the provisioning API. Show a progress spinner and handle errors with retry logic.
- Ready screen – Show a “Tap to pay” illustration and a “Test with a dummy POS” button for QA.
UX tip: Keep the “Enable NFC” prompt modal (blocking) rather than a toast. Users often ignore toast messages, leading to a “NFC is off” error after the first transaction attempt.
Testing Strategies
9.1. Unit & Instrumented Tests
| Test Type | Scope | Example |
|---|---|---|
| Unit |
FeliCaAdapter parsing, error mapping |
Verify isPollCommand returns true for a known Poll byte array. |
| Instrumented | Service lifecycle, permission handling | Launch FelicaHceService and assert that processCommandApdu returns a 0x9000 status for a valid Read command. |
| Mocked Google Payments | Replace network calls with a local mock server (e.g., MockWebServer) |
Ensure that a malformed APDU yields a 403 risk‑score response. |
9.2. End‑to‑End Tests with POS Emulators
- Deploy the app to a test Pixel 11 device.
- Launch the
NfcFCardEmulationtest app (bundled with the Android SDK). - Configure the emulator to act as a transit gate: set the expected AID to
F001. - Run an automated UI script (e.g., using
UiAutomator) that:- Opens the payment screen in your app.
- Triggers a tap on the emulator’s “Tap Card” button.
- Captures the response latency via
adb shell dumpsys nfc.
Success criteria
- Latency ≤ 150 ms (JPSA benchmark).
- Response status word = 0x9000 for a successful transaction.
- No crashes when the device is rotated or when the screen is turned off during the exchange.
9.3. Performance & Power Profiling
-
Latency measurement –
adb shell dumpsys nfcprintslast_poll_time_ms. Record the value before and after the transaction. - Power draw – Use Android Studio’s Profiler → Energy tab while repeatedly tapping a POS emulator. Expect ~0.8 mW per tap.
- CPU usage – Ensure the HCE service stays under 2 % of a single core; higher usage may indicate inefficient byte‑array handling.
If you observe spikes above 120 ms, investigate:
- Excessive logging (logcat sync can add ~5 ms).
- Blocking network calls on the main thread (use
AsyncTask,ExecutorService, or Kotlin coroutines). - Unnecessary cryptographic operations on the device (offload to Google Payments API).
9.4. Automated JPSA Certification in CI/CD
Google’s JPSA Certification Portal accepts a JSON log bundle. The bundle must contain:
-
felica_adapter_version– e.g.,1.2.0. -
transaction_timings– array of{ "poll_to_response_ms": 92 }. -
error_codes– anyFeliCaExceptionoccurrences. -
device_info– model, OS version, NFC controller firmware.
CI integration steps
- Build the signed APK (
./gradlew assembleRelease). - Deploy to a device farm (e.g., Firebase Test Lab) that includes Pixel 11 devices.
- Run a test script that performs 30 consecutive tap simulations and collects the log bundle (
adb pull /data/local/tmp/felica_log.json). - Upload the bundle via
curltohttps://certification.googleapis.com/v1/submit. - Parse the JSON response; fail the pipeline if
overall_status != "PASS"or if any latency exceeds 150 ms.
Result: The pipeline automatically blocks a release if the new code path degrades performance or breaks compliance.
Deployment Checklist & Release‑Gate Considerations
| ✅ Item | Why It Matters |
|---|---|
OS version check – Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
Guarantees the FeliCaAdapter class exists. |
Feature flag – PackageManager.FEATURE_NFC_FELICA
|
Prevents crashes on the rare “no‑FeliCa” SKU. |
Permission granted – Runtime request for android.hardware.nfc.felica
|
Avoids SecurityException at runtime. |
NFC & FeliCa toggles ON – Verified via Settings.Secure
|
Guarantees the hardware is active. |
| Token provisioning success – Store token ID securely (EncryptedSharedPreferences) | Required for every transaction; missing token = immediate failure. |
| JPSA certification pass – Automated upload in CI | Mandatory for production in Japan. |
| Fallback flow – QR‑code or ISO‑DEP path enabled | Preserves user experience on unsupported devices. |
Analytics instrumentation – Log felica_supported, felica_enabled, transaction_latency_ms
|
Enables post‑release monitoring and A/B testing. |
| Crash‑free rate target – ≥ 99.5 % on FeliCa‑enabled devices | Maintains brand trust; JPSA audits look at crash logs. |
Trade‑offs & Design Decisions
| Decision | Pro | Con |
|---|---|---|
Use FeliCaAdapter (high‑level) vs. raw NfcF
|
Faster development, built‑in validation, future‑proof. | Slightly larger binary (adds the adapter library). |
| Delegate cryptography to Google Payments API | Compliance out‑of‑the‑box, no private key storage. | Requires network connectivity for every tap; offline fallback needed. |
| Host Card Emulation (HCE) vs. Secure Element (SE) provisioning | HCE works on all Pixel 11 devices, no hardware SE required. | Slightly higher latency (~ 10 ms) compared to SE; may be a concern for ultra‑high‑throughput transit gates. |
| Single‑token per user vs. multiple tokens | Simpler provisioning flow, lower token‑management overhead. | Limits ability to bundle loyalty points; may need a separate AID list later. |
| Foreground‑service requirement for background payments | Guarantees system will not kill the HCE service. | Consumes a persistent notification, which can be intrusive for users. |
Recommendation: Start with the simplest path – a single payment token, HCE only, and online‑only transactions. Once you have a stable baseline, iterate to add offline caching of the last‑known token and a secondary loyalty token using a second AID.
Common Pitfalls & How to Avoid Them
| Pitfall | Symptom | Fix |
|---|---|---|
| Assuming all Pixel 11 devices have FeliCa |
NullPointerException when calling FeliCaAdapter.getInstance(). |
Always guard with hasSystemFeature(PackageManager.FEATURE_NFC_FELICA). |
| Running HCE from a background service | Transaction blocked, log shows android.nfc.NfcAdapterService: Service not allowed in background. |
Bring the payment UI to the foreground before initiating the tap. |
Locale set to en‑US
|
30 % of transactions return 0x6985 (Conditions of use not satisfied). |
Force the device locale to ja-JP for the payment flow, or instruct the user to change it. |
| Registering ISO‑DEP AID before FeliCa AID | POS polls FeliCa but receives ISO‑DEP response → silent drop. | List the FeliCa AID first in felica_service_aid_list.xml. |
| Neglecting to request the runtime permission |
SecurityException: Missing permission android.hardware.nfc.felica. |
Prompt the permission dialog early; handle denial gracefully. |
Hard‑coding the AID (F001) in multiple places |
Inconsistent AID leads to “AID not found” errors during certification. | Centralize the AID in a constant (static final String FELICA_AID = "F001"). |
| Using synchronous network calls on the main thread | UI freezes, ANR, latency spikes > 150 ms. | Use AsyncTask, ExecutorService, or Kotlin coroutines (Dispatchers.IO). |
| Skipping JPSA timing benchmarks | App passes functional tests but fails certification due to > 150 ms latency. | Include latency measurement in every CI run; set a hard gate. |
FAQ for Mobile‑Payment Teams
Q1: Do I need to support both FeliCa and ISO‑DEP on the same device?
A: Not mandatory, but recommended. Many merchants still use ISO‑DEP cards (e.g., credit‑card only terminals). Implement a dual‑service HCE configuration and register the ISO‑DEP AID (0xA0000002471001) alongside the FeliCa AID. The system routes requests based on the POS’s first poll.
Q2: Can I store the token locally for offline transactions?
A: Google Payments API does not expose the private key, so true offline signing is impossible. You can cache the last successful transaction response and replay it in case of temporary network loss, provided you respect JPSA’s “no duplicate transaction” rule. Always fall back to QR‑code if the network is unavailable for more than 5 seconds.
Q3: How do I handle multiple user accounts on the same device?
A: Store a token ID per user in an encrypted database keyed by the Android AccountManager ID. When the user switches accounts, re‑initialize the HCE service with the appropriate token ID.
Q4: Is there a way to test on an emulator without a physical Pixel 11?
A: The Android Emulator (API 33) now includes a virtual FeliCa controller behind the android.hardware.nfc_felica feature flag. Enable it via the AVD’s Advanced Settings → NFC → Enable FeliCa. Note that emulator latency is not representative of real hardware.
Q5: What if the user disables NFC after provisioning a token?
A: Listen for NfcAdapter.ACTION_ADAPTER_STATE_CHANGED broadcasts. If NFC is turned off, show a persistent banner prompting re‑enable. Tokens remain valid; they just cannot be used until NFC is back on.
Conclusion & Next Steps
Pixel 11 finally brings native, production‑grade FeliCa support to the Android ecosystem. By following the three‑pillar approach—runtime capability detection, proper system‑level configuration, and HCE backed by the Google Payments API—you can ship a payment experience that:
- Meets JPSA certification (cryptographic compliance, ≤ 150 ms latency).
- Delivers a smooth, sub‑100 ms tap comparable to Apple Pay.
- Scales across the fragmented Android market by gracefully degrading on the few devices that lack the hardware flag.
Action checklist for your team
- Update all test devices to Android 13.2 or newer.
- Integrate the code snippets above, paying attention to manifest declarations and permission handling.
- Add automated JPSA certification to your CI pipeline.
- Run a pilot with a small user cohort (e.g., 5 % of your Japanese user base) and monitor latency, crash logs, and conversion rates.
- Iterate—if you see > 5 % transaction failures, revisit locale handling and fallback logic.
When you ship with the official FeliCaAdapter and Google Payments API, you avoid the hidden cost of custom cryptography, reduce maintenance overhead, and position your product to capture the 70 %+ market share that has been out of reach for Android apps until now.
Key Takeaways
- This topic is evolving rapidly—monitor developments closely over the next 6–12 months.
- Evaluate whether existing tooling in your stack already covers this need before adopting new solutions.
- Start with a small proof‑of‑concept before committing to a full implementation.
- Cross‑reference multiple sources before acting on any single vendor claim.
- Share findings with your team—decisions in this area benefit from diverse perspectives.
See more articles on The Looplet
Read Next
- Pixel Buds Pro 2 vs Pixel Buds 2a: which delivers better developer value
- How to Distribute Android Apps Through Third-Party Stores
- Foldable vs Traditional smartphones: Adoption and dev tradeoffs
Read next: continue with one of these related guides.
Originally published at The Looplet.
Top comments (0)