NFC
Darek Zoń
piątek, 28 czerwca 13
https://bitbucket.org/darek/nfc-by-example
https://play.google.com/store/apps/details?id=com.darekzon.nfc_by_example
piątek, 28 czerwca 13
co to jest?
• Near Field Communication
(komunikacja bliskiego zasięgu)
• Rozwinięcie technologi RFID
(radio-frequency identification)
• Stworzono by umożliwić bezpieczną wymianę
prywatnych i służbowych danych na
niewielkie odległości
piątek, 28 czerwca 13
nfc a rfid
RFID NFC
pasmo
125-134kHz
13,56MHz
300-930 MHz
2,5GHz, 5GHz
13,56MHz
prędkość 1-200 Kbps 102; 212; 424; 848 Kbps
zasięg
<=20cm – pasywny
<=400cm – aktywny
0-4 cm
pojemność do 128 kB
1 MB
zwyczajowo 144 B
piątek, 28 czerwca 13
nfc jak działa
Tag NDEF
*Inny tag
NDEF_DISCOVERED
TECH_DISCOVERED
TAG_DISCOVERED
Aktywność zarejestrowana do
obsługi TECH_DISCOVERED
Aktywność zarejestrowana do
obsługi NDEF_DISCOVERED
Aktywność zarejestrowana do
obsługi TAG_DISCOVERED
Przekaż Intent
do aktywności
nie
nie
tak
tak
tak
* tag niesformatowany do formatu Ndef
piątek, 28 czerwca 13
obsługa po stronie Androida
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc"
android:required="true" />
umożliwiamy naszej aplikacji korzystanie z NFC
ustawiamy widoczność naszej aplikacji w sklepie Google Play tylko dla
urządzeń z NFC
piątek, 28 czerwca 13
implementacja: Odczytywanie
NfcAdapter nfcAdapter =
NfcAdapter.getDefaultAdapter(this.getApplicationContext());
1. Pobieramy adapter NFC dla naszego kontekstu
2. W przypadku deaktywacji aplikacji, oddajemy obsługę NFC systemowi
@Override
protected void onPause() {
this.nfcAdapter.disableForegroundDispatch(this);
}
piątek, 28 czerwca 13
implementacja: Odczytywanie
3. Przekazujemy systemowi, że teraz nasza aplikacja odpowiada za obsługę NFC
@Override
protected void onResume() {
nfcAdapter.enableForegroundDispatch(this,
PendingIntent.getActivity(this, 0, new Intent(this,this.getClass()), 0),
new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)},
new String[][]{new String[]{Ndef.class.getName()}});
}
odczytujemy wszystkie tagi
niezależnie od wartości MIMEodczytujemy tylko tagi typu Ndef
ACTION_NDEF_DISCOVERED
ACTION_TECH_DISCOVERED
odczytuje po wartości MIME lub URI
odczytuje po typie tagu
piątek, 28 czerwca 13
implementacja: Odczytywanie
4. Odczytywany tag jest przekazywany jako Intent
public static String handleTagReceive(Intent intent) {
Tag tagFromIntent =
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef tag = Ndef.get(tagFromIntent);
tag.connect();
NdefMessage ndefM = tag.getNdefMessage();
NdefRecord[] nrec = ndefM.getRecords();
StringBuilder sb = new StringBuilder();
for (NdefRecord rec : nrec) {
sb.append(new String(rec.getPayload()));
}
return sb.toString();
}
Odczytujemy zawartość
strona po stronie
piątek, 28 czerwca 13
implementacja: Zapisywanie
1. Przekazujemy systemowi, że teraz nasza aplikacja odpowiada za obsługę NFC*
@Override
protected void onResume() {
nfcAdapter.enableForegroundDispatch(this,
PendingIntent.getActivity(this, 0, new Intent(this,this.getClass()), 0),
new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)},
new String[][]{new String[]{Ndef.class.getName()}});
}
*Identycznie jak przy odczytywaniu tagów
@Override
protected void onPause() {
super.onPause();
this.adapter.disableForegroundDispatch(this);
}
2. W przypadku pauzy oddajemy obsługę NFC systemowi*
piątek, 28 czerwca 13
implementacja: Zapisywanie
3. Gdy zostanie wykryty tag, tworzymy wiadomość Ndef i przekazujemy do nowego wątku
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] text = this.valueToWrite.getBytes(Charset.forName("UTF-8"));
NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
Nfc.MIME_TYPE.getBytes(Charset.forName("UTF-8")), new byte[0], text);
NdefMessage msg = new NdefMessage(new NdefRecord[] { record });
new WriteTask(this, msg, tag).execute();
}
}
*Nfc.MIME_TYPE - Nasz typ MIME (np. application/com.darekzon.nfc_by_example)
*NdefRecord.TNF_MIME_MEDIA - zapisuje
piątek, 28 czerwca 13
implementacja: Zapisywanie
4. Zapisujemy tag w nowym wątku
@Override
protected void doInBackground(Void... nop) {
Ndef ndef = Ndef.get(this.tag);
NdefFormatable formatable = NdefFormatable.get(this.tag);
formatable.connect();
formatable.format(this.msg);
formatable.close();
ndef.connect();
ndef.writeNdefMessage(this.msg);
ndef.close();
} Tag przekazany
przez Activity
Formatowanie tagu
koniecznie wywoływać
w nowym wątku
Zapisywanie tagu
piątek, 28 czerwca 13
implementacja: Odczyt tagu aplikacji
1. Konfigurujemy filtry naszej aktywności aby rozpoznawały tagi z naszym typem MIME
<activity android:name="Init"
android:label="@string/app_name">
<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.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/com.darekzon.nfc_by_example" />
</intent-filter>
</activity>
Wskazujemy typ MIME jaki ma być obsługiwany
piątek, 28 czerwca 13
implementacja: Zapisywanie
2. Przekazujemy, że nasza aplikacja obsługuje odczyt tagów NFC o określonym typie
@Override
protected void onPause() {
super.onPause();
this.adapter.disableForegroundDispatch(this);
}
3. W przypadku pauzy oddajemy obsługę NFC systemowi
@Override
protected void onResume() {
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndef.addDataType(Nfc.MIME_TYPE);
this.nfcAdapter.enableForegroundDispatch(this,
PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()), 0),
new IntentFilter[]{ndef},
new String[][]{new String[]{Ndef.class.getName()}});
}
Wskazujemy nasz typ MIME
piątek, 28 czerwca 13
implementacja: Zapisywanie
4. Odczytujemy tag w onCreate oraz onNewIntent
@Override
public void onCreate(Bundle savedInstanceState)
{
Nfc.handleTagReceive(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
Nfc.handleTagReceive(intent);
}
Nasza metoda odczytu tagu
Identyczna jak przy odczycie
normalnych tagów
piątek, 28 czerwca 13
implementacja: Beam!
1. Konfigurujemy filtry naszej aktywności aby rozpoznawały tag dla Beam-a
Wskazujemy typ MIME jaki ma być obsługiwany
<activity android:name=".activity.BeamActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/
com.darekzon.nfc_by_example_beam" />
</intent-filter>
</activity>
piątek, 28 czerwca 13
implementacja: Beam!
2. Podczas tworzenia aktywności tworzymy wiadomość push
Wiadomość którą chcemy zapisać
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
Nfc.BEAM_MIME_TYPE.getBytes(Charset.forName("UTF-8")),
new byte[0],
messageToBeam.getBytes());
NdefMessage message = new NdefMessage(new NdefRecord[]{record});
this.nfcAdapter = NfcAdapter.getDefaultAdapter(this.getApplicationContext());
this.nfcAdapter.setNdefPushMessage(message,this);
}
Nasz typ MIME dla wiadomości Beam
piątek, 28 czerwca 13
implementacja: Beam!
3. Odczytujemy wiadomość
void processIntent(Intent intent) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage msg = (NdefMessage) rawMsgs[0];
return new String(msg.getRecords()[0].getPayload();
}
piątek, 28 czerwca 13
dziękuję
piątek, 28 czerwca 13

Android NFC

  • 1.
  • 2.
  • 3.
    co to jest? •Near Field Communication (komunikacja bliskiego zasięgu) • Rozwinięcie technologi RFID (radio-frequency identification) • Stworzono by umożliwić bezpieczną wymianę prywatnych i służbowych danych na niewielkie odległości piątek, 28 czerwca 13
  • 4.
    nfc a rfid RFIDNFC pasmo 125-134kHz 13,56MHz 300-930 MHz 2,5GHz, 5GHz 13,56MHz prędkość 1-200 Kbps 102; 212; 424; 848 Kbps zasięg <=20cm – pasywny <=400cm – aktywny 0-4 cm pojemność do 128 kB 1 MB zwyczajowo 144 B piątek, 28 czerwca 13
  • 5.
    nfc jak działa TagNDEF *Inny tag NDEF_DISCOVERED TECH_DISCOVERED TAG_DISCOVERED Aktywność zarejestrowana do obsługi TECH_DISCOVERED Aktywność zarejestrowana do obsługi NDEF_DISCOVERED Aktywność zarejestrowana do obsługi TAG_DISCOVERED Przekaż Intent do aktywności nie nie tak tak tak * tag niesformatowany do formatu Ndef piątek, 28 czerwca 13
  • 6.
    obsługa po stronieAndroida <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> umożliwiamy naszej aplikacji korzystanie z NFC ustawiamy widoczność naszej aplikacji w sklepie Google Play tylko dla urządzeń z NFC piątek, 28 czerwca 13
  • 7.
    implementacja: Odczytywanie NfcAdapter nfcAdapter= NfcAdapter.getDefaultAdapter(this.getApplicationContext()); 1. Pobieramy adapter NFC dla naszego kontekstu 2. W przypadku deaktywacji aplikacji, oddajemy obsługę NFC systemowi @Override protected void onPause() { this.nfcAdapter.disableForegroundDispatch(this); } piątek, 28 czerwca 13
  • 8.
    implementacja: Odczytywanie 3. Przekazujemysystemowi, że teraz nasza aplikacja odpowiada za obsługę NFC @Override protected void onResume() { nfcAdapter.enableForegroundDispatch(this, PendingIntent.getActivity(this, 0, new Intent(this,this.getClass()), 0), new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)}, new String[][]{new String[]{Ndef.class.getName()}}); } odczytujemy wszystkie tagi niezależnie od wartości MIMEodczytujemy tylko tagi typu Ndef ACTION_NDEF_DISCOVERED ACTION_TECH_DISCOVERED odczytuje po wartości MIME lub URI odczytuje po typie tagu piątek, 28 czerwca 13
  • 9.
    implementacja: Odczytywanie 4. Odczytywanytag jest przekazywany jako Intent public static String handleTagReceive(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); Ndef tag = Ndef.get(tagFromIntent); tag.connect(); NdefMessage ndefM = tag.getNdefMessage(); NdefRecord[] nrec = ndefM.getRecords(); StringBuilder sb = new StringBuilder(); for (NdefRecord rec : nrec) { sb.append(new String(rec.getPayload())); } return sb.toString(); } Odczytujemy zawartość strona po stronie piątek, 28 czerwca 13
  • 10.
    implementacja: Zapisywanie 1. Przekazujemysystemowi, że teraz nasza aplikacja odpowiada za obsługę NFC* @Override protected void onResume() { nfcAdapter.enableForegroundDispatch(this, PendingIntent.getActivity(this, 0, new Intent(this,this.getClass()), 0), new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)}, new String[][]{new String[]{Ndef.class.getName()}}); } *Identycznie jak przy odczytywaniu tagów @Override protected void onPause() { super.onPause(); this.adapter.disableForegroundDispatch(this); } 2. W przypadku pauzy oddajemy obsługę NFC systemowi* piątek, 28 czerwca 13
  • 11.
    implementacja: Zapisywanie 3. Gdyzostanie wykryty tag, tworzymy wiadomość Ndef i przekazujemy do nowego wątku @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); byte[] text = this.valueToWrite.getBytes(Charset.forName("UTF-8")); NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, Nfc.MIME_TYPE.getBytes(Charset.forName("UTF-8")), new byte[0], text); NdefMessage msg = new NdefMessage(new NdefRecord[] { record }); new WriteTask(this, msg, tag).execute(); } } *Nfc.MIME_TYPE - Nasz typ MIME (np. application/com.darekzon.nfc_by_example) *NdefRecord.TNF_MIME_MEDIA - zapisuje piątek, 28 czerwca 13
  • 12.
    implementacja: Zapisywanie 4. Zapisujemytag w nowym wątku @Override protected void doInBackground(Void... nop) { Ndef ndef = Ndef.get(this.tag); NdefFormatable formatable = NdefFormatable.get(this.tag); formatable.connect(); formatable.format(this.msg); formatable.close(); ndef.connect(); ndef.writeNdefMessage(this.msg); ndef.close(); } Tag przekazany przez Activity Formatowanie tagu koniecznie wywoływać w nowym wątku Zapisywanie tagu piątek, 28 czerwca 13
  • 13.
    implementacja: Odczyt taguaplikacji 1. Konfigurujemy filtry naszej aktywności aby rozpoznawały tagi z naszym typem MIME <activity android:name="Init" android:label="@string/app_name"> <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.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="application/com.darekzon.nfc_by_example" /> </intent-filter> </activity> Wskazujemy typ MIME jaki ma być obsługiwany piątek, 28 czerwca 13
  • 14.
    implementacja: Zapisywanie 2. Przekazujemy,że nasza aplikacja obsługuje odczyt tagów NFC o określonym typie @Override protected void onPause() { super.onPause(); this.adapter.disableForegroundDispatch(this); } 3. W przypadku pauzy oddajemy obsługę NFC systemowi @Override protected void onResume() { IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); ndef.addDataType(Nfc.MIME_TYPE); this.nfcAdapter.enableForegroundDispatch(this, PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()), 0), new IntentFilter[]{ndef}, new String[][]{new String[]{Ndef.class.getName()}}); } Wskazujemy nasz typ MIME piątek, 28 czerwca 13
  • 15.
    implementacja: Zapisywanie 4. Odczytujemytag w onCreate oraz onNewIntent @Override public void onCreate(Bundle savedInstanceState) { Nfc.handleTagReceive(getIntent()); } @Override protected void onNewIntent(Intent intent) { Nfc.handleTagReceive(intent); } Nasza metoda odczytu tagu Identyczna jak przy odczycie normalnych tagów piątek, 28 czerwca 13
  • 16.
    implementacja: Beam! 1. Konfigurujemyfiltry naszej aktywności aby rozpoznawały tag dla Beam-a Wskazujemy typ MIME jaki ma być obsługiwany <activity android:name=".activity.BeamActivity"> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/ com.darekzon.nfc_by_example_beam" /> </intent-filter> </activity> piątek, 28 czerwca 13
  • 17.
    implementacja: Beam! 2. Podczastworzenia aktywności tworzymy wiadomość push Wiadomość którą chcemy zapisać @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, Nfc.BEAM_MIME_TYPE.getBytes(Charset.forName("UTF-8")), new byte[0], messageToBeam.getBytes()); NdefMessage message = new NdefMessage(new NdefRecord[]{record}); this.nfcAdapter = NfcAdapter.getDefaultAdapter(this.getApplicationContext()); this.nfcAdapter.setNdefPushMessage(message,this); } Nasz typ MIME dla wiadomości Beam piątek, 28 czerwca 13
  • 18.
    implementacja: Beam! 3. Odczytujemywiadomość void processIntent(Intent intent) { Parcelable[] rawMsgs = intent.getParcelableArrayExtra( NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage msg = (NdefMessage) rawMsgs[0]; return new String(msg.getRecords()[0].getPayload(); } piątek, 28 czerwca 13
  • 19.