Reputation: 161
I want to write a program that can store a unique ID and then send it as NFC tag to another NFC reader devices. How can I send my code (nfcTag
) to the NFC reader? Can I do this without having an AID for my application?
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PackageManager pm = this.getPackageManager();
String nfcTag="123456789"; //the code wants to work as NFC tag
TextView msg = (TextView) findViewById(R.id.txtShow);
byte[] t2 = new byte[9]; //t2 return from processCommandApdu
t2 = nfcTag.getBytes();
@Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
msg.setText(nfcTag);
return t2; //return nfcTag too read with NFC tag reader devices
}
@Override
public void onDeactivated(int reason) {
msg.setText("Your phone does not has HCE hardware.");
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
// HCE is not available on the device.
Toast.makeText(this, "The device does not has HCE hardware.",
Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this, "HCE supported on your device.",
Toast.LENGTH_SHORT).show();
}
}
}
}
and here is AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Upvotes: 1
Views: 4612
Reputation: 40821
For Android HCE, you will first need to create a service component (that's a separate class and not part of your activity):
public class MyHostApduService extends HostApduService {
@Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
// TODO: process the incoming APDU command(s) and give reasonable responses
}
@Override
public void onDeactivated(int reason) {
}
}
Smartcard readers (actually the software that accesses cards through them) use ISO/IEC 7816-4 APDU command sequences to communicate with (emulated) contactless smartcards. Therefore, your HCE service needs to process these APDUs and create proper respondes for the reader. This command sequence will consist of at least the SELECT (by AID) command that was used to select your HCE service. You should respond to that SELECT command with status word 9000
(i.e. new byte[] { (byte)0x90, (byte)0x00 }
) and, optionally, a file control information structure.
You further need to define an AID filter for your HCE service:
<service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
And in res/xml/apduservice.xml
:
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="My HCE Service"
android:requireDeviceUnlock="false">
<aid-group android:description="My HCE Service" android:category="other">
<aid-filter android:name="F0010203040506"/>
</aid-group>
</host-apdu-service>
Replace the AID F0010203040506
with whatever your reader (software) uses to access the application on your (emulated) smartcard.
What you cannot do with Android HCE:
Upvotes: 3