7

我需要 NFC 和 Android 方面的帮助。

在进行了大量研究以在 Android 上模拟 Mifare 4K 之后,我发现唯一存在的补丁是为 2.3.4 制作的。在 StackOverFlow 中,NFCGuy 告诉我们,从 Android 的 API 14 开始,不需要修补 ROM,因此我们可以使用隐藏的 Nfc_extras 包打开卡模拟。

我已经使用带有反射的 NFC_EXTRAS 编译了一个 APK,并将我的签名和包添加到 nfcee_access.xml。

在我将 cardEmulationRoute 设置为 ON_WHEN_SCREEN_ON 后,我在 logcat 中得到一个输出,告诉我 NFCEE 已打开且 NFC_CC 已打开,但是当我将 Nexus S 靠近 ACR122 时,它没有检测到 2.3.4 补丁制造商可以检测到的 Emulated Mifare 4K得到。我可以得到一张无法识别的智能卡(我想它是 SE 像智能卡一样),但我需要使用模拟的 Mifare。

我是否需要像在 2.3.4 补丁中那样修改 lib-nfc 才能使该小程序正常工作(Mifare Manager)?或者我的应用程序访问该包应该足够了?

我正在下载 android 源以将 2.3.4 补丁移植到 4.1,但查看他们发布的差异,lib-nfc 库上与 4.1 仅存在差异。(定义注释,理论上用于卡模拟)

也许不需要重新编译修改后的 ROM,我错过了获得模拟 Mifare 4k 的一小步。

感谢您对 StackOverFlow 中所有人的帮助

问候

    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());
    }
}
4

2 回答 2

3

您的代码似乎应该正确启用卡模拟模式。我也在尝试同样的事情并遇到了类似的问题,我无法使用与 MIFARE 兼容的 RFID 阅读器检测到手机。

原来的原因是我正在使用的手机支持 NFC,但没有安装嵌入式安全元件。安全元件位于 SIM 卡上,而 ICS 4.0.3 中的内置 NFC 支持无法定位和使用该安全元件。

当通过某些手机供应商而不是通过我的供应商销售时,同一品牌/型号的手机具有嵌入式安全元件。

当我尝试对我的 NfcExecutionEnvironment 实例进行“打开”时,我得到了第一个提示,这就是原因,并且在我的 logcat 中显示了以下输出:

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
于 2012-12-06T01:52:37.527 回答
3

我认为问题可能出在Object routeOn = c.newInstance(2, embebbed). 看起来这个对象的类型错误(不过,我不是阅读反射代码的专家)。

我就是这样做的,没有反射,并且工作正常(设备同时模拟 ISO 14443-4A 卡和 MIFARE Classic 卡):

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));

无需为此修改 libnfc-nxp。

于 2012-10-18T21:26:47.980 回答