I need help with NFC and Android.
After making a lot of research to enable the emulation of a Mifare 4K on Android, I’ve found that the only patch that exists was made for 2.3.4. Here in StackOverFlow, NFCGuy told us since API 14 of Android it’s not neccesary patch the ROM, so we can turn on card emulation using the hidden Nfc_extras package.
I’ve compiled an APK using NFC_EXTRAS with reflection, and added my signature and package to the nfcee_access.xml.
After I set cardEmulationRoute to ON_WHEN_SCREEN_ON, I get an output in logcat telling me that NFCEE is ON and NFC_CC is ON, but when I get my Nexus S close to a ACR122 it does not detect the Emulated Mifare 4K that 2.3.4 patch makers could get. I can get an unrecognized Smart Card (I suppose that it’s the SE acting like a smartcard) but i need to use the emulated Mifare.
Do I need to modify lib-nfc as it was modify in 2.3.4 patch to get that applet working (Mifare Manager)? Or with my app accesing that package should be enought?
I’m downloading the android source to port the 2.3.4 patch to 4.1, but looking at the diff they’ve posted, there is only a difference with 4.1 on lib-nfc library. (A define commented, used for card emulation in theory)
Maybe it’s not necesary to recompile a modified ROM and I’m missing a small step to get the emulated Mifare 4k.
Thanks for your help to all people here in StackOverFlow
Regards
private void getSecureElement(){
try{
//Obtenemos la clase NFCAdapterExtras
Class nfcExtrasClazz = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
if (nfcExtrasClazz == null){
Log.w("EnableCardEmu", "No existe la clase Extras");
return;
}
Log.w("EnableCardEmu", "Existe la clase");
//Obtenemos el método "get" de dicha clase
Method getMethod = nfcExtrasClazz.getMethod("get", Class.forName("android.nfc.NfcAdapter"));
if (getMethod == null) {
Log.w("EnableCardEmu", "No existe el método");
} else {
Log.w("EnableCardEmu", "Existe el método");
//Obtenemos el manager del componente NFC del dispositivo
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
if (adapter == null)
Log.w("EnableCardEmu", "Adapter es null");
else {
//Instancia del SecureElement
Log.w("EnableCardEmu", "Adapter NO es null");
nfcExtras = getMethod.invoke(null, adapter);
Method getEEMethod = nfcExtras.getClass().getMethod("getEmbeddedExecutionEnvironment",
(Class[]) null);
embebbed = getEEMethod.invoke(nfcExtras , (Object[]) null);
}
}
} catch (InvocationTargetException ee){
Log.w("EnableCardEmu", ee.getTargetException());
}
catch (Exception e){
Log.w("EnableCardEmu", e.getClass().getName() + " / " + e.getMessage());
StackTraceElement[] a = e.getStackTrace();
for (StackTraceElement aa : a){
Log.w("EnableCardEmu", aa.toString());
}
}
}
private void deactivateCardEmulation(){
try{
Class clss = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
Class[] cs = clss.getDeclaredClasses();
/*
for (Class cc : cs){
Log.w("EnableCardEmu", cc.getName();)
}*/
//Class route = Class.forName("com.android.nfc_extras.NfcAdapterExtras$CardEmulationRoute");
Constructor c = cs[0].getConstructor(Integer.TYPE, Class.forName("com.android.nfc_extras.NfcExecutionEnvironment"));
Object routeOn = c.newInstance(1, null);
Class cls = nfcExtras.getClass();
Method mtd = cls.getMethod("setCardEmulationRoute", cs[0]);
mtd.invoke(nfcExtras, routeOn);
} catch (InvocationTargetException ee){
Log.w("EnableCardEmu", ee.getTargetException());
} catch (Exception e){
Log.w("EnableCardEmu", e.getClass().getName() + " / " + e.getMessage());
}
}
private void activateCardEmulation(){
try{
Class clss = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
Class[] cs = clss.getDeclaredClasses();
/*
for (Class cc : cs){
Log.w("EnableCardEmu", cc.getName();)
}*/
//Class route = Class.forName("com.android.nfc_extras.NfcAdapterExtras$CardEmulationRoute");
Constructor c = cs[0].getConstructor(Integer.TYPE, Class.forName("com.android.nfc_extras.NfcExecutionEnvironment"));
Object routeOn = c.newInstance(2, embebbed);
Class cls = nfcExtras.getClass();
Method mtd = cls.getMethod("setCardEmulationRoute", cs[0]);
mtd.invoke(nfcExtras, routeOn);
} catch (InvocationTargetException ee){
Log.w("EnableCardEmu", ee.getTargetException());
} catch (Exception e){
Log.w("EnableCardEmu", e.getClass().getName() + " / " + e.getMessage());
}
}
I think the problem could be in
Object routeOn = c.newInstance(2, embebbed). It looks like this object is of the wrong type (I am not an expert on reading reflection code, though).This is how I do it, without reflection, and it works fine (both an ISO 14443-4A card and a MIFARE Classic card are emulated by the device simultaneously):
No need to modify libnfc-nxp for this.