Enabling CardEmulation on Android ICS with NFC_EXTRAS

I need help with NFC and Android.

After doing a lot of research to enable Mifare 4K emulation on Android, I found that the only patch that exists was made for 2.3.4. Here at StackOverFlow, NFCGuy was telling us because the Android API 14 does not require ROM fixing, so we can enable map emulation using the hidden Nfc_extras package.

I compiled the APK using NFC_EXTRAS with reflection, and added my signature and package to the nfcee_access.xml file.

After I set cardEmulationRoute to ON_WHEN_SCREEN_ON, I get output in logcat telling me that NFCEE is on and NFC_CC is on, but when I find my Nexus S close to ACR122, it does not detect Emulated Mifare 4K, which is 2.3.4 manufacturers patches could get. I can get an unrecognized smart card (I believe that it acts like a smart card), but I need to use an emulated Mifare.

Do I need to modify lib-nfc since it was changed in patch 2.3.4 to get this applet working (Mifare Manager)? Or with my application that the package should have?

I am downloading an Android source to port patch 2.3.4 to 4.1, but looking at the difference they posted, there is only a difference in the lib-nfc library. (A define is commented, used to emulate a map in theory)

It may not be necessary to recompile the modified ROM, and I skipped a small step to get an emulated Mifare 4k.

Thanks for helping all the people here at StackOverFlow

Hi

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()); } } 
+7
source share
2 answers

I think the problem may be in Object routeOn = c.newInstance(2, embebbed) . This object seems to be of the wrong type (although I'm not an expert on reading reflection code).

Here's how I do it, without reflection, and it works great (both the ISO 14443-4A card and the MIFARE Classic card are emulated by the device at the same time):

 Context mContext; // initialize this NfcAdapterExtras mAdapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(mContext)); NfcExecutionEnvironment mEe = mAdapterExtras.getEmbeddedExecutionEnvironment(); mAdapterExtras.setCardEmulationRoute( new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, mEe)); 

No need to modify libnfc-nxp for this.

+3
source

It seems that your code should correctly enable the card emulation mode. I also tried to do the same and ran into a similar problem when I couldn’t find the phone using the MIFARE compatible RFID reader.

Which turned out to be the reason that the phone I was working with supported NFC, but did not have a built-in secure element. The protected element was located on the SIM card, and the built-in NFC support in ICS 4.0.3 could not find and use this protected element.

The same make / model of the phone has a built-in secure element when sold through some mobile providers, but not through my provider.

I got my first hint that this was the reason when I tried to "open" in my NfcExecutionEnvironment instance, and the following result appeared in my logarithm:

 D/NFC JNI ( 911): phLibNfc_SE_GetSecureElementList() D/NFC JNI ( 911): D/NFC JNI ( 911): > Number of Secure Element(s) : 0 E/NFC JNI ( 911): phLibNfc_SE_GetSecureElementList(): No SMX detected 
+3
source

All Articles