2014-07-09 54 views
4

我已經提出過這個問題here但它被標記爲重複 - 但是我沒有找到任何解決方法有助於在評論中提到。 在這裏,我有更多的細節再次問...如何與活動中的HostApduService進行通信

我上HCE做一個示例應用程序(POC),並使用HostApduService按照Android的用戶指南。我已經創建了兩個應用
1)ReaderApp - 充當讀卡器 2)HCEApp - 模擬一個卡

在HCEApp,我已經創建了一個類 '爲MyService' 延伸HostApduService

public class MyService extends HostApduService { 

private int messageCounter; 
private final String TAG = "MyService"; 

Intent mIntent; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    Log.i(TAG, "onCreate"); 

    mIntent = new Intent(this, MyActivity.class); 
    mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    startActivity(mIntent); 
} 

/** 
* returned bytes will be sent as response. This method runs in Main thread 
* so return ASAP. 
*/ 

@Override 
public byte[] processCommandApdu(byte[] apdu, Bundle extras) { 
    if (selectAidApdu(apdu)) { 
     Log.i(TAG, "Application selected"); 
     return getWelcomeMessage(); 
    } else { 
     Log.i(TAG, "Received: " + new String(apdu)); 
     return getNextMessage(); 
    } 
} 

private byte[] getWelcomeMessage() { 
    return "Hello Desktop!".getBytes(); 
} 

private byte[] getNextMessage() { 
    return ("Message from android: " + messageCounter++).getBytes(); 
} 

private boolean selectAidApdu(byte[] apdu) { 

    if (apdu != null) { 
     for (byte b : apdu) { 
      System.out.printf("0x%02X", b); 
     } 
    } 

    return apdu.length >= 2 && apdu[0] == (byte) 0 
      && apdu[1] == (byte) 0xa4; 
} 

@Override 
public void onDeactivated(int reason) { 
    Log.i(TAG, "Deactivated: " + reason); 
} 

@Override 
public boolean onUnbind(Intent intent) { 
    return super.onUnbind(intent); 
} 

}

正如您在onCreate()中看到的,我將啓動MyActivity爲用戶提供了一些信息並需要發送回MyServic e

我想我不能用綁定爲「onBind()」聲明最後在HostApduService如下

@Override 
public final IBinder onBind(Intent intent) { 
    return mMessenger.getBinder(); 
} 

請讓我知道如果我正確understading它。感謝任何幫助。

感謝
iuq

+0

我已經添加了一個鏈接到HostApduService。你能解釋一下(鏈接到)什麼PoC,pos和HCE是什麼? – k3b

+0

@ k3b我已添加鏈接到HCE,並用示例應用和POS讀卡器替換了PoC。希望在上下文中更容易理解! – iuq

+0

那麼......你的問題是什麼?即使它被聲明爲final,你也可以使用'onBind'。 – Manu

回答

1

是否可以使用onBind或不是我不知道,但我最近從我開始的服務的廣播接收器的工作。你不能bind一個來自BroadcastReceiver的服務根據文檔,你只能start它。我需要稍後從我的BroadcastReceiver發送一些數據到服務中,由於綁定器技術不適用於我,因此我必須找到與服務進行通信的不同方式,就像您的情況不一樣有一個參考。

我做了一些研究,但找不到任何解決方案,但後來我記得您可以通過startService(intent)調用傳遞intent數據。我在onCreate中開始我的服務工作,因爲onCreate僅在創建服務時調用一次。

在你的活動

public void sendDataToService(){ 
    Intent intent = new Intent(context, MyService.class); 
    intent.putExtra("message", SOME_DATA); 
    context.startService(intent); 
} 

在服務

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    // Check if intent has extras 
    if(intent.getExtras() != null){ 

     // Get message 
     int message = intent.getExtras().getInt("message"); 
    } 

    return START_NOT_STICKY; 
} 

這可能是某種形式的黑客攻擊的是什麼,因爲「startService」聽起來並不像它應該被用來發送郵件,我不確定這是否正是您需要的,但它對我有用,所以我希望它適合您。歡呼聲

編輯:BTW。我用它來告訴LocationService某個活動不再需要位置更新。

+0

在我的情況下,當手機(有我的應用程序)帶到「NFC讀卡器」附近時,服務由Android OS啓動。 NFC閱讀器是另一款在另一款Android Kitkat設備上運行的應用程序。而服務依次啓動一個活動供用戶輸入一些需要發送回服務的數據。這就是問題的所在 - 我無法弄清楚這個Activity to Service的通信。 ...謝謝。 – iuq

+0

那麼活動到服務的溝通可以按照我剛剛描述的完成。從您的活動中調用startService並持有您的數據。 – Jakob

+0

我接受你的文章作爲答案,因爲我沒有找到任何其他方式來解決問題。雖然我認爲必須有一些更好的方法來做到這一點!謝謝。 – iuq

0

我最終採取了不同的方法來解決這個相同的問題。當我綁定到我的HostApduService子類時,我抓取接口的句柄,該接口由HostApduServiceonBind實現返回。

下面是一些示例代碼。這將全部用於您的活動實施(在此稱其爲MyActivity,與MyHostApduServiceSubclass通信)。下面是MyActivity需要包括:

private Messenger mAPDUMessenger; 
... 
@Override 
protected void onStart() { 
    super.onStart(); 
    Context context = getApplicationContext(); 
    Intent apduIntent = new Intent(montext, ContactlessApduService.class); 
    context.bindService(apduIntent, mAPDUConnection, Context.BIND_AUTO_CREATE); 
} 
... 
private ServiceConnection mAPDUConnection = new ServiceConnection() { 
    @Override 
    public void onServiceConnected(ComponentName className, IBinder service) { 
     // The HostApduService has a final override on the onBind() service method that returns 
     // an IMessageHandler interface that we can grab and use to send messages back to the 
     // terminal - would be better to get a handle to the running instance of the service so 
     // that we could make use of the HostApduService#sendResponseApdu public method 
     mAPDUMessenger = new Messenger(service); 
     registerAPDUMessengerIntentFilters(); 
     //^This method sets up my handlers for local broadcast messages my BroadcastReceiver processes. 
    } 
... 
} 
... 
private void registerAPDUMessengerIntentFilters() { 
    LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(MyActivity.this); 

    IntentFilter intentFilter = new IntentFilter(MyHostApduServiceSubclass.ACTION_PPSE_APDU_SELECT); 
    lbm.registerReceiver(apduMessageBroadcastReceiver, intentFilter); 
} 
... 
BroadcastReceiver apduMessageBroadcastReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getAction().equals(MyHostApduServiceSubclass.ACTION_PPSE_APDU_SELECT)) { 
      sendResponseApdu(MyActivity.PPSE_APDU_SELECT_RESPONSE_BYTES); 
     } 
    } 
}; 
... 
public final void sendResponseApdu(byte[] responseApdu) { 
    Message responseMsg = Message.obtain(null, MyHostApduServiceSubclass.MSG_RESPONSE_APDU); 
    //^Note here that because MSG_RESPONSE_APDU is the message type 
    // defined in the abstract HostApduService class, I had to override 
    // the definition in my subclass to expose it for use from MyActivity. 
    // Same with the KEY_DATA constant value below. 
    Bundle dataBundle = new Bundle(); 
    dataBundle.putByteArray(MyHostApduServiceSubclass.KEY_DATA, responseApdu); 
    responseMsg.setData(dataBundle); 
    try { 
     mAPDUMessenger.send(responseMsg); 
    } catch (RemoteException e) { 
     // Do something with the failed message 
    } 
} 

然後你HostApduService子就只需要廣播發送到您的活動,其指示收到什麼APDU命令。這裏是需要包含在MyHostApduServiceSubclass

public static final String ACTION_PPSE_APDU_SELECT = "ACTION_PPSE_APDU_SELECT"; 

// Abstract super class constant overrides 
public static final String KEY_DATA = "data"; 
public static final int MSG_RESPONSE_APDU = 1; 

@Override 
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) { 
    Context context = getApplicationContext(); 
    LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context); 
    if (Arrays.equals(MyHostApduServiceSubclass.PPSE_APDU_SELECT_BYTES, commandApdu)) { 
     lbm.sendBroadcast(new Intent(ACTION_PPSE_APDU_SELECT)); 
    } 
    return null; 
    //^Note the need to return null so that the other end waits for the 
    // activity to send the response via the Messenger handle 
} 
相關問題