Проблема отправки Android NFC переднего плана - PullRequest
2 голосов
/ 10 мая 2011

Я совершенно новичок в разработке для Android и должен написать простое приложение для чтения тега NFC (с Nexus S) для университета.

Моя проблема в том, что когда Nexus обнаруживает тег, мое приложениеотсутствует в списке «выберите действие».цель состоит в том, чтобы прочитать теги, используя метод переднего плана, как описано в http://developer.android.com/guide/topics/nfc/index.html и http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html

Я думаю, что в манифесте чего-то не хватает, но я не знаю, что.вот манифест:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.iforge.android.nfc"
>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
>
<activity android:name=".simulator.FakeTagsActivity"
    android:theme="@android:style/Theme.NoTitleBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

</activity>

    <activity android:name="TagViewer"
        android:theme="@android:style/Theme.NoTitleBar"
    >
        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
            <data android:mimeType="mime/type" />
        </intent-filter>

        <intent-filter>
            <action android:name="android.nfc.action.TECH_DISCOVERED"/>

        </intent-filter>

        <intent-filter>
            <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        </intent-filter>
    </activity>
</application>
<uses-sdk android:minSdkVersion="10" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />

вот код действия, которое следует вызывать при обнаружении тега (который создается из android NFCDemo, а также из примера ForegroundDispatch):

public class TagViewer extends Activity 
{

WebView webView;
private NfcAdapter mAdapter;
private PendingIntent mPendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    mAdapter = NfcAdapter.getDefaultAdapter(this);
    mPendingIntent = PendingIntent.getActivity(
            this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    try {
        ndef.addDataType("*/*");    /* Handles all MIME based dispatches. 
                                       You should specify only the ones that you need. */
    }
    catch (MalformedMimeTypeException e) {
        throw new RuntimeException("fail", e);
    }

    mFilters = new IntentFilter[] {
            ndef,
    };

    mTechLists = new String[][] { new String[] { NfcF.class.getName() } };


    setContentView(R.layout.tag_viewer);
    webView = (WebView) findViewById(R.id.webView1);
    webView.getSettings().setJavaScriptEnabled(true); 
    webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
    webView.getSettings().setPluginsEnabled(false);
    webView.getSettings().setSupportMultipleWindows(false);
    webView.getSettings().setSupportZoom(false);
    webView.setVerticalScrollBarEnabled(false);
    webView.setHorizontalScrollBarEnabled(false);

    resolveIntent(getIntent());
}

@Override
public void onResume() {
    super.onResume();
    mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}

@Override
public void onPause() {
    super.onPause();
    mAdapter.disableForegroundDispatch(this);
}

void resolveIntent(Intent intent) 
{
    // Parse the intent
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) 
    {
        // When a tag is discovered we send it to the service to be save. We
        // include a PendingIntent for the service to call back onto. This
        // will cause this activity to be restarted with onNewIntent(). At
        // that time we read it from the database and view it.
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        NdefMessage[] msgs;
        if (rawMsgs != null) 
        {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++) 
            {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        } 
        else 
        {
            // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
            msgs = new NdefMessage[] {msg};
        }
        // Setup the web-view
        setUpWebView(msgs);
    } 
    else 
    {
        Log.e("ViewTag", "Unknown intent " + intent);
        finish();
        return;
    }
}

void setUpWebView(NdefMessage[] msgs) 
{
    if (msgs == null || msgs.length == 0) return;

    String urlToLoad = MessageParser.parseMessage(msgs[0]);
    if(!urlToLoad.matches("")) webView.loadUrl(urlToLoad);

}

@Override
public void onNewIntent(Intent intent) 
{
    setIntent(intent);
    resolveIntent(intent);
    Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
}
}

Я много пробовал, но ничего не работает.было бы замечательно, если бы кто-нибудь мог сказать мне, чего мне не хватает.у меня заканчивается время: - (

пожалуйста

спасибо

Ответы [ 4 ]

4 голосов
/ 29 июня 2012

Для отправки на передний план явно требуется использование правильно настроенного действия: похоже, вы не можете использовать IntentFilter s, настроенный в AndroidManifest.xml для отправки на передний план (ваше приложение должно быть на переднем плане, т.е.Бег).Код ниже, кажется, работает правильно (я только что проверил), если вы все еще заинтересованы (ACTION_TAG_DISCOVERED был то, что я искал):

private NfcAdapter mAdapter;
    private PendingIntent pendingIntent;
    private IntentFilter[] mFilters;
    private String[][] mTechLists;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.main);

        mAdapter = NfcAdapter.getDefaultAdapter(this);
        pendingIntent = PendingIntent.getActivity(
          this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

     // Setup an intent filter for all MIME based dispatches
        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
        IntentFilter td = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        mFilters = new IntentFilter[] {
                ndef, td
        };

        // Setup a tech list for all NfcF tags
        mTechLists = new String[][] { new String[] { 
                NfcV.class.getName(),
                NfcF.class.getName(),
                NfcA.class.getName(),
                NfcB.class.getName()
            } };
    }

@Override
    public void onResume()
    {
        super.onResume();

        mAdapter.enableForegroundDispatch(this, pendingIntent, mFilters, mTechLists);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        mAdapter.disableForegroundDispatch(this);
    }

    @Override
    public void onNewIntent(Intent intent){
        // fetch the tag from the intent
        Tag t = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String tlist = getTechList(t);
        android.util.Log.v("NFC", "Discovered tag ["+tlist+"]["+t+"] with intent: " + intent);
        android.util.Log.v("NFC", "{"+t+"}");
}
4 голосов
/ 31 мая 2011

Ваш файл манифеста должен обрабатывать обнаруженные технические намерения в отдельном техническом фильтре xml, например:

<intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
     </intent-filter>
     <intent-filter>
        <action android:name="android.nfc.action.TECH_DISCOVERED"/>
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                               android:resource="@xml/nfc_tech_filter" />
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
            </intent-filter>

Тогда ваш файл res / xml / nfc_tech_filter.xml должен обрабатывать нужные вам nfc-технологии следующим образом:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
</resources>

Каждый технический узел действует как AND, тогда как узел технического списка действует как и OR. Я рекомендую вам сначала отсканировать ваши теги с помощью такого инструмента, как NFC Tag Reader, чтобы узнать ваши технологии.

Затем в java-коде вы можете включить / отключить вашу систему рассылки переднего плана, как на других сайтах, уже являющихся техническими специалистами. Я настроил те же технологии, что и в xml, например:

private void setUpForegroundDispatchSystem()
    {
        this.nfcAdapter = NfcAdapter.getDefaultAdapter(this);

        this.pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");    /* Handles all MIME based dispatches. 
                                           You should specify only the ones that you need. */
          ndef.addDataScheme("http");
        }
        catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
        this.intentFiltersArray = new IntentFilter[] {ndef};
        this.techListsArray = new String[][] { new String[] { MifareUltralight.class.getName(), Ndef.class.getName(), NfcA.class.getName()},
                                               new String[] { MifareClassic.class.getName(), Ndef.class.getName(), NfcA.class.getName()}};

    }

Вы должны включить и отключить это в методах Pause и Resume. Надеюсь, что эта информация поможет вам.

0 голосов
/ 11 мая 2011

Если вы запустили Activity и зарегистрировали отправленную ранее отправку, все, что вам нужно сделать, это зарегистрировать фильтр намерений для ACTION_TAG_DISCOVERED - это самый низкий фильтр, который соответствует всем обнаруженным тегам. Если вы хотите быть более конкретным, вы должны зарегистрировать фильтр намерений для технологии тегов или для тега, который содержит ndef.

Но если вы хотите запустить свое приложение с домашнего экрана, используя метку, нажмите, чтобы сделать это по-другому. Я успешно поместил сообщение MIME в тег и зарегистрировал этот тип MIME в своей деятельности. Другой способ - поместить URL в тег, а затем зарегистрировать фильтр намерений, который объединяет схему и хост. Для MIME это то, что вам нужно:

Чтобы сделать это соответствие, тег должен иметь сообщение MIME NDEF с mime, как описано.

0 голосов
/ 10 мая 2011

Элемент категории отсутствует в элементе фильтра намерений?См.

Android NFC: можем ли мы использовать фильтр намерений с типом mime?(Android 2.3.3)

Вы также можете попробовать вообще не использовать IntentFilter в своем коде.

...