Mit Android 4.0 wurde Android Beam eingeführt, welches die Nutzung von NFC für P2P-Verbindungen stark vereinfachen soll.  Benutzer erhalten eine App übergreifende einheitliche Bedienung und für Entwickler ist der dafür nötige Code als übersichtliche Demo auf Android Developers zu finden. Für frühere Versionen von Android ist das jedoch nicht ganz so einfach. Es gibt eine Reihe von Tutorials im Netz, die sich bereits mit diesem Thema befassen:

Beides sehr gute Anleitungen, die auch von mir verwendet wurden, allerdings sind sie zum Teil sehr speziell und bieten kein Minimalbeispiel. Aus diesem Grund soll das folgende Beispiel die Lücke füllen. Ich poste den Quellcode ohne externe Beschreibung, da der Code ausreichend kommentiert sein sollte. An dieser Stelle der Hinweis, dass die Kommentare zwar in Deutsch sind, da es sich hier um einen deutschen Blog handelt, aber im allgemeinen Fall präferiere ich englische Kommentare. Außerdem sollten mehrzeilige Kommentare mit

/* Ein mehrzeiliger...
...Kommentar */

umschlossen werden und nicht aus mehreren einzeiligen Kommentaren mit

// Ein mehrzeiliger...
// ...Kommentar

bestehen. Leider versagt das Sourcecode Plugin von wordpress bei der ersten Variante.

Die Demo besteht aus nur zwei Dateien. Dem Manifest und der entsprechenden Activity. Es sollte auf jedem Smartphone mit Unterstützung des SDK ab Version 10 lauffähig sein. Das entspricht Android 2.3.3 und folgende.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="my.nfc.demo"
    android:versionCode="1"
    android:versionName="1.0" >

    <!-- Für NFC ist SDK Version 10 oder höher nötig. -->
    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".NfcActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            
            <!-- Damit NDEF Nachrichten mit beliebigen Payload empfangen 
            	 werden können, ist folgender Filter nötig. -->
            <intent-filter>
		    	<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
		      	<category android:name="android.intent.category.DEFAULT"/>
		      	<data android:mimeType="text/plain" />
		    </intent-filter>
                
        </activity>
    </application>

    <!-- Für den Zugriff auf NFC wird die entsprechende 
    	 Permission benötigt. -->
    <uses-permission android:name="android.permission.NFC" />
        
</manifest>

NfcActivity.java

package my.nfc.demo;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.Toast;

public class NfcActivity extends Activity 
{
    // ================================ Member =================================
    // Speichert den NFC Adapter.
    private NfcAdapter mNfcAdapter = null;
    
    // Speichert das Intent, welches von Android mit erkannten Tags gefüllt 
    // und an die Activity weitergeleitet wird.
    private PendingIntent mNfcPendingIntent = null;
    
    private static final String LOG_TAG = "NFC Demo";
	
    // ================================ Public =================================
    /** 
     * Called when the activity is first created. 
     */
    @Override
    public void onCreate( Bundle savedInstanceState ) 
    {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.main );
        
        // Zugriff auf den NFC Adapter erhalten.
        mNfcAdapter = NfcAdapter.getDefaultAdapter( this );
        
        // Bei Geräten ohne NFC liefert getDefaultAdapter() null.
        if ( mNfcAdapter == null ) 
        {
        	logError( "Kein NFC Adapter gefunden. App wird beendet." );
            finish();
            return;
        }
        
        // Das Intent für Ergebnisse. Es wird von Android automatisch 
        // mit erkannten Tags gefüllt und an die Activity weitergereicht.
        // Das Flag verhindert, dass eine weitere Instanz der Activity gestartet 
        // wird. Die bestehende wird jeweils weiter verwendet.
        Intent intent =  new Intent( this, getClass() );
        intent.addFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP );
        mNfcPendingIntent = PendingIntent.getActivity( this, 0, intent, 0 );
    }
    
    // =============================== Protected ===============================
    @Override
    protected void onNewIntent( Intent intent ) 
    {
    	// Nur Intents mit NFC Nachrichten bearbeiten.
        if ( !NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) )
        {
        	logError( "Unbekanntes Intent: " + intent.getAction() );
            return;
        }
        
        // Nutzdaten des Intent auslesen.
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra( 
            NfcAdapter.EXTRA_NDEF_MESSAGES 
        );
        if ( rawMsgs == null ) 
        {
            logError( "Keine Nutzdaten in Intent enthalten." );
            return;
        }

        // Die einzelnen Nachrichten parsen.
        for ( int i = 0; i < rawMsgs.length; ++i ) 
        {
            NdefMessage msg = (NdefMessage) rawMsgs[i];
            NdefRecord[] records = msg.getRecords();
            
            for ( NdefRecord record : records )
            {
            	// Empfangene Nachrichten anzeigen.
                String text = new String( record.getPayload() );
                Toast.makeText( 
            		this, 
            		"Nachricht empfangen: " + text, 
    				Toast.LENGTH_LONG 
				).show();
            }
        }
    }
    
    @Override
    protected void onResume()
    {
        super.onResume();
        
        // Nachrichtenempfang aktivieren.
        mNfcAdapter.enableForegroundDispatch(
            this, 
            mNfcPendingIntent,
            null, 
            null
        );
        
        // Nachricht vorbereiten.
        String text = "Hello NFC World!";
        NdefRecord record = new NdefRecord(
            NdefRecord.TNF_MIME_MEDIA,
            "application/my.nfc.demo".getBytes(),
            new byte[0], 
            text.getBytes()
        );
        NdefRecord[] records = { record };
        NdefMessage msg = new NdefMessage( records );
        
        // Nachrichtenversand aktivieren.
        mNfcAdapter.enableForegroundNdefPush( this, msg );
    }
    
    @Override
	protected void onPause() 
    {
		super.onPause();
		
		// Nachrichtenempfang deaktivieren.
		mNfcAdapter.disableForegroundDispatch( this );
		
		// Nachrichtenversand deaktivieren.
		mNfcAdapter.disableForegroundNdefPush( this );
	}

	// ================================ Private ================================
    /**
     * Loggt Fehler und zeigt sie gleichzeitig an.
     * @param String msg Die Fehlermeldung.
     */
    private void logError( String msg )
    {
    	Toast.makeText( this, msg, Toast.LENGTH_LONG ).show();
    	Log.v( LOG_TAG, msg );
    }
    
}

Download des kompletten Projekts: mediafire.com

Advertisements