public abstract class HostApduService
extends Service
| java.lang.Object | ||||
| android.content.Context | ||||
| android.content.ContextWrapper | ||||
| android.app.Service | ||||
| android.nfc.cardemulation.HostApduService | ||||
HostApduService是一个便利的 Service类,可以扩展为模拟Android服务组件内的NFC卡。
该类仿真的卡基于NFC-Forum ISO-DEP协议(基于ISO / IEC 14443-4),并支持ISO / IEC 7816-4规范中定义的处理命令应用协议数据单元(APDU)。
当远程NFC设备想要与您的服务通话时,它会发送ISO / IEC 7816-4规范中定义的所谓“SELECT AID”APDU。 AID是ISO / IEC 7816-4中定义的应用程序标识符。
AID的注册程序在ISO / IEC 7816-5规范中定义。 如果您不想注册AID,则可以在专有范围内自由使用AID:第一个字节的第8-5位必须各设置为“1”。 例如,“0xF00102030405”是专有的AID。 如果确实使用专有AID,则建议选择至少6个字节的AID,以降低与可能使用专有AID的其他应用程序发生冲突的风险。
在某些情况下,服务可能需要注册多个AID来实现某个应用程序,并且需要确定它是所有这些AID的默认处理程序(而不是组中的某些AID转到其他服务)。
一个AID组是应该被OS视为一起归属的AID列表。 对于AID组中的所有AID,操作系统将保证以下之一:
每个AID组都可以与一个类别关联。 这允许Android OS对服务进行分类,并允许用户在类别级别而不是AID级别设置默认值。
您可以使用 isDefaultServiceForCategory(android.content.ComponentName, String)来确定您的服务是否是某个类别的默认处理程序。
在这个版本的平台中,唯一已知的类别是CATEGORY_PAYMENT和CATEGORY_OTHER 。 没有类别的AID组或者当前平台版本无法识别的类别将自动分组到CATEGORY_OTHER类别中。
为了告知平台哪些AIDs组被这个服务请求,一个SERVICE_META_DATA条目必须包含在服务声明中。 HostApduService清单声明的示例如下所示:
<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_ervice" android:resource="@xml/apduservice"/>
</service> This meta-data tag points to an apduservice.xml file. An example of this file with a single AID group declaration is shown below:
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc" android:requireDeviceUnlock="false">
<aid-group android:description="@string/aiddescription" android:category="other">
<aid-filter android:name="F0010203040506"/>
<aid-filter android:name="F0394148148100"/>
</aid-group>
</host-apdu-service>
<host-apdu-service>需要包含<android:description>属性,其中包含可能在UI中显示的用户友好的服务说明。 可以使用<requireDeviceUnlock>属性指定在调用此服务来处理APDU之前必须先解锁设备。
<host-apdu-service>必须包含一个或多个<aid-group>标签。 每个<aid-group>必须包含一个或多个<aid-filter>标签,每个标签包含一个AID。 AID必须以十六进制格式指定,并且包含偶数个字符。
getSelectionModeForCategory(String).
一旦平台将“SELECT AID”命令APDU解析为特定服务组件,“SELECT AID”命令APDU和所有后续命令APDU将通过 processCommandApdu(byte[], Bundle)发送到该服务,直到:
onDeactivated(int).
使用此类需要 FEATURE_NFC_HOST_CARD_EMULATION在设备上。
常量(Constants) |
|
|---|---|
int |
DEACTIVATION_DESELECTED 原因为 |
int |
DEACTIVATION_LINK_LOSS 原因为 |
String |
SERVICE_INTERFACE 必须声明为由服务处理的 |
String |
SERVICE_META_DATA 包含有关此服务的更多信息的元数据元素的名称。 |
Inherited constants |
|---|
android.app.Service
|
android.content.Context
|
android.content.ComponentCallbacks2
|
Public constructors |
|
|---|---|
HostApduService() |
|
公共方法(Public methods) |
|
|---|---|
final void |
notifyUnhandled() 调用此方法允许服务告诉操作系统它将无法完成此事务 - 例如,因为它需要当时不存在的数据连接。 |
final IBinder |
onBind(Intent intent) 将通信信道返回给服务。 |
abstract void |
onDeactivated(int reason) 这种方法将在两种可能的情况下被调用: |
abstract byte[] |
processCommandApdu(byte[] commandApdu, Bundle extras) 当从远程设备接收到命令APDU时,将调用此方法。 |
final void |
sendResponseApdu(byte[] responseApdu) 将响应APDU发送回远程设备。 |
继承方法(Inherited methods) |
|
|---|---|
android.app.Service
|
|
android.content.ContextWrapper
|
|
android.content.Context
|
|
java.lang.Object
|
|
android.content.ComponentCallbacks2
|
|
android.content.ComponentCallbacks
|
|
int DEACTIVATION_DESELECTED
原因为 onDeactivated(int) 。
指示取消激活是由于选择了不同的AID(隐式取消选择当前在逻辑通道上激活的AID)。
请注意,这个下一个AID仍然可以解析为此服务,在这种情况下 processCommandApdu(byte[], Bundle)将再次被调用。
常数值:1(0x00000001)
int DEACTIVATION_LINK_LOSS
原因为onDeactivated(int) 。 表示取消激活是由于NFC链路丢失。
常量值:0(0x00000000)
String SERVICE_INTERFACE
Intent必须声明为由服务处理的操作。
常量值:“android.nfc.cardemulation.action.HOST_APDU_SERVICE”
String SERVICE_META_DATA
包含有关此服务的更多信息的元数据元素的名称。
常量值:“android.nfc.cardemulation.host_apdu_service”
void notifyUnhandled ()
调用此方法允许服务告诉操作系统它将无法完成此事务 - 例如,因为它需要当时不存在的数据连接。 操作系统可以使用该指示为用户提供可以处理所选择的最后AID的替代应用程序的列表。 如果用户从列表中选择应用程序,则该操作本身不会导致默认值被更改; 所选的应用程序将只为下一次点击而被调用。 如果没有其他应用程序可以处理此事务,则操作系统将显示一个错误对话框,指出您的服务无法完成该事务。
注意:可以在第一个 processCommandApdu(byte[], Bundle)调用和 onDeactivated(int)调用之间的任何地方调用此方法。
IBinder onBind (Intent intent)
将通信信道返回给服务。 如果客户端无法绑定到服务,可能会返回null。 返回的IBinder通常用于一个复杂的接口described using aidl 。
请注意,与其他应用程序组件不同,此处返回的IBinder接口调用可能不会发生在进程的主线程上 。 有关主线程的更多信息可以在Processes and Threads中找到。
| 参数(Parameters) | |
|---|---|
intent |
Intent: The Intent that was used to bind to this service, as given to Context.bindService. Note that any extras that were included with the Intent at that point will not be seen here. |
| 返回(Returns) | |
|---|---|
IBinder |
Return an IBinder through which clients can call on to the service. |
void onDeactivated (int reason)
这种方法将在两种可能的情况下被调用:
| 参数(Parameters) | |
|---|---|
reason |
int: Either DEACTIVATION_LINK_LOSS or DEACTIVATION_DESELECTED |
byte[] processCommandApdu (byte[] commandApdu,
Bundle extras)
当从远程设备接收到命令APDU时,将调用此方法。 响应APDU可以通过在此方法中返回字节数组直接提供。 请注意,一般来说,响应APDU必须尽可能快地发送,因为当调用此方法时,用户可能将他的设备通过NFC读取器。
如果有多个服务在其元数据条目中注册了相同的AID,则只有在用户明确选择了服务时才会被调用,无论是默认还是仅用于下一次点击。
此方法在您的应用程序的主线程上运行。 如果您无法立即返回响应APDU,请返回null并稍后使用sendResponseApdu(byte[])方法。
| 参数(Parameters) | |
|---|---|
commandApdu |
byte: The APDU that was received from the remote device |
extras |
Bundle: A bundle containing extra data. May be null. |
| 返回(Returns) | |
|---|---|
byte[] |
a byte-array containing the response APDU, or null if no response APDU can be sent at this point. |
void sendResponseApdu (byte[] responseApdu)
将响应APDU发送回远程设备。
注意:这个方法可以从任何线程调用并且不会被阻塞。
| 参数(Parameters) | |
|---|---|
responseApdu |
byte: A byte-array containing the reponse APDU. |