Potrzebuję pomocy z NFC i Androidem.

Po przeprowadzeniu wielu badań, aby umożliwić emulację Mifare 4K na Androidzie, odkryłem, że jedyna istniejąca łatka została stworzona dla wersji 2.3.4. Tutaj, w StackOverFlow, NFCGuy powiedział nam, że od API 14 Androida nie jest konieczne łatanie ROM-u, więc możemy włączyć emulację karty za pomocą ukrytego pakietu Nfc_extras.

Skompilowałem APK przy użyciu NFC_EXTRAS z odbiciem i dodałem swój podpis i pakiet do nfcee_access.xml.

Po ustawieniu cardEmulationRoute na ON_WHEN_SCREEN_ON otrzymuję w logcat informację, że NFCEE jest WŁĄCZONE, a NFC_CC jest WŁĄCZONE, ale gdy zbliżam się do mojego Nexusa S zbliżonego do ACR122, nie wykrywa on emulowanego Mifare 4K, który mogliby stworzyć twórcy łatek 2.3.4 dostwać. Mogę uzyskać nierozpoznaną kartę inteligentną (przypuszczam, że to SE działa jak karta inteligentna), ale muszę użyć emulowanego Mifare.

Czy muszę zmodyfikować lib-nfc tak, jak została zmodyfikowana w łatce 2.3.4, aby ten aplet działał (Mifare Manager)? A może z moją aplikacją dostęp do tego pakietu powinien wystarczyć?

Pobieram źródło Androida, aby przenieść łatkę 2.3.4 do 4.1, ale patrząc na opublikowaną przez nich różnicę, jest tylko różnica z 4.1 w bibliotece lib-nfc. (Określenie skomentowane, używane w teorii do emulacji karty)

Może nie jest konieczna rekompilacja zmodyfikowanej pamięci ROM i brakuje mi małego kroku, aby uzyskać emulowany Mifare 4k.

Dziękuję za pomoc wszystkim ludziom w StackOverFlow

Pozdrowienia

    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
noni 18 październik 2012, 17:32

2 odpowiedzi

Najlepsza odpowiedź

Myślę, że problem może być w Object routeOn = c.newInstance(2, embebbed). Wygląda na to, że ten obiekt jest złego typu (nie jestem jednak ekspertem w odczytywaniu kodu odbicia).

Tak to robię, bez refleksji i działa dobrze (zarówno karta ISO 14443-4A, jak i karta MIFARE Classic są emulowane przez urządzenie jednocześnie):

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

Nie ma potrzeby modyfikowania w tym celu libnfc-nxp.

3
NFC guy 19 październik 2012, 01:26

Wygląda na to, że Twój kod powinien poprawnie włączać tryb emulacji karty. Próbowałem również tego samego i napotkałem podobny problem, w którym nie mogłem wykryć telefonu za pomocą mojego czytnika RFID zgodnego z MIFARE.

Przyczyną okazało się to, że telefon, z którym pracowałem, miał obsługę NFC, ale nie miał zainstalowanego wbudowanego bezpiecznego elementu. Bezpieczny element znajdował się na karcie SIM, a wbudowana obsługa NFC w ICS 4.0.3 nie była w stanie zlokalizować i użyć tego zabezpieczonego elementu.

Ta sama marka/model telefonu ma wbudowany bezpieczny element, gdy jest sprzedawany przez niektórych dostawców komórkowych, ale nie przez mojego dostawcę.

Dostałem pierwszą wskazówkę, że to była przyczyna, gdy próbowałem wykonać „otwarcie” w moim wystąpieniu NfcExecutionEnvironment, a w moim logcat pojawiły się następujące dane wyjściowe:

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
Patrick 6 grudzień 2012, 05:52