Android 代码实现启动HostApduService
时间: 2023-08-15 13:05:52 浏览: 165
以下是一个简单的示例代码,展示如何在 Android 应用程序中启动 HostApduService:
1. 在 AndroidManifest.xml 文件中声明 HostApduService。
```xml
<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>
```
2. 创建一个继承自 HostApduService 的类,并重写其 onDeactivated() 和 processCommandApdu() 方法。
```java
public class MyHostApduService extends HostApduService {
private static final String TAG = "MyHostApduService";
private static final String SELECT_APDU_HEADER = "00A40400";
private static final String SELECT_OK_SW = "9000";
private static final String UNKNOWN_CMD_SW = "0000";
@Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
Log.d(TAG, "Received APDU: " + ByteArrayToHexString(commandApdu));
if (Arrays.equals(commandApdu, HexStringToByteArray(SELECT_APDU_HEADER))) {
Log.d(TAG, "Application selected");
return HexStringToByteArray(SELECT_OK_SW);
} else {
return HexStringToByteArray(UNKNOWN_CMD_SW);
}
}
@Override
public void onDeactivated(int reason) {
Log.d(TAG, "Deactivated: " + reason);
}
private static String ByteArrayToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for(byte b: bytes) {
sb.append(String.format("%02X", b & 0xff));
}
return sb.toString();
}
private static byte[] HexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for(int i = 0; i < len; i += 2){
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}
```
3. 在应用程序的主活动中,使用 startActivity() 方法启动一个新的 Activity 并传递 ACTION_REQUEST_ENABLE_NFC 的 intent。这将提示用户启用 NFC。
```java
private static final int ACTION_REQUEST_ENABLE_NFC = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "NFC is not available on this device", Toast.LENGTH_LONG).show();
finish();
return;
}
if (!nfcAdapter.isEnabled()) {
Intent enableNfcIntent = new Intent(NfcAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableNfcIntent, ACTION_REQUEST_ENABLE_NFC);
}
}
```
4. 当用户启用 NFC 后,使用 CardEmulation.getInstance(NfcAdapter.getDefaultAdapter(context)) 获取 CardEmulation 实例,并使用 setDefaultServiceForCategory() 方法设置默认的 HostApduService。
```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ACTION_REQUEST_ENABLE_NFC) {
if (resultCode == RESULT_OK) {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
CardEmulation cardEmulation = CardEmulation.getInstance(nfcAdapter);
ComponentName component = new ComponentName(this, MyHostApduService.class);
cardEmulation.setDefaultServiceForCategory(component, CardEmulation.CATEGORY_OTHER);
Toast.makeText(this, "NFC is enabled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "NFC must be enabled to use this app", Toast.LENGTH_LONG).show();
finish();
}
}
}
```
现在,当读卡器与设备建立连接时,系统将自动启动您的 HostApduService,并调用其 processCommandApdu() 方法。
阅读全文