Включение Кардемуляции на Android ICS с помощью NFC EXTRAS

Мне нужна помощь с NFC и Android.

после проведения большого количества исследований, чтобы включить эмуляцию Mifare 4K на Android, я обнаружил, что единственный патч, который существует, был сделан для 2.3.4. Здесь, в StackOverFlow, NFCGuy сказал нам, так как API 14 Android не обязательно исправлять ПЗУ, поэтому мы можем включить эмуляцию карт с помощью скрытого пакета Nfc_extras.

я скомпилировал APK, используя NFC_EXTRAS с отражением, и добавил свою подпись и пакет в nfcee_access.XML.

после того, как я установил cardEmulationRoute в ON_WHEN_SCREEN_ON, я получаю вывод в logcat, сообщающий мне, что NFCEE включен, а NFC_CC включен, но когда я получаю свой Nexus S близко к ACR122, он не обнаруживает эмулированный Mifare 4K, который могут получить производители патчей 2.3.4. Я могу получить непризнанную смарт-карту (я полагаю, что это SE, действующий как смарт-карта), но мне нужно использовать эмулированный Mifare.

мне нужно изменить lib-nfc, как это было изменено в патче 2.3.4, чтобы заставить этот апплет работать (Mifare Manager)? Или с моим приложением accesing, что пакет должен быть достаточно?

я загружаю источник android для переноса патча 2.3.4 на 4.1, но, глядя на разницу, которую они опубликовали, есть только разница с 4.1 в библиотеке lib-nfc. (Определение прокомментировано, используется для эмуляции карт в теории)

возможно, нет необходимости перекомпилировать измененный ПЗУ, и мне не хватает небольшого шага, чтобы получить эмулированный 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());
    }
}

2 ответов


Я думаю, что проблема может быть в 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 для этого.


Кажется, что ваш код должен правильно включать режим эмуляции карты. Я также пытался то же самое и столкнулся с аналогичной проблемой, где я не мог обнаружить телефон с моим Mifare совместимым RFID-считывателем.

оказалось, что причиной было то, что телефон, с которым я работал, имел поддержку NFC, но не имел встроенного безопасного элемента. Вместо этого Безопасный элемент находился на SIM-карте, а встроенная поддержка NFC в ICS 4.0.3 не смогла найдите и используйте этот безопасный элемент.

этот же бренд / модель телефона имеет встроенный Безопасный элемент при продаже через некоторых поставщиков сотовых, но не через моего провайдера.

Я получил свой первый намек, что это было причиной, когда я попытался сделать "open" на моем экземпляре 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