// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the Apache License, Version 2.0 // http://www.apache.org/licenses/LICENSE-2.0 package com.google.appinventor.components.runtime.util; import android.app.Activity; import android.content.Intent; import android.content.Context; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.Ndef; import android.nfc.tech.NdefFormatable; import android.os.Parcelable; import android.util.Log; import com.google.appinventor.components.runtime.NearField; import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookieStore; import java.io.IOException; import java.nio.charset.Charset; import java.util.Locale; /** * Helper methods for calling methods added in Gingerbread (2.3, API level 9). * * @author lizlooney@google.com (Liz Looney) */ public class GingerbreadUtil { private GingerbreadUtil() { } /** * Creates a new CookieManager instance. */ public static CookieHandler newCookieManager() { return new CookieManager(); } /** * Clears the cookies in the given cookie handler. Cookies can only be cleared if the * cookieHandler is a CookieManager with a non-null CookieStore. * * @param cookieHandler the cookie handler where cookies should be cleared * @return true if cookies were cleared; false otherwise */ public static boolean clearCookies(CookieHandler cookieHandler) { if (cookieHandler instanceof CookieManager) { CookieManager cookieManager = (CookieManager) cookieHandler; CookieStore cookieStore = cookieManager.getCookieStore(); if (cookieStore != null) { cookieStore.removeAll(); return true; } } return false; } /** * Creates a new NfcAdapter instance. */ public static NfcAdapter newNfcAdapter(Context context) { return NfcAdapter.getDefaultAdapter(context); } public static void enableNFCWriteMode(Activity activity, NfcAdapter nfcAdapter, String textToWrite){ NdefRecord textRecord = createTextRecord(textToWrite,true); NdefMessage msg = new NdefMessage(new NdefRecord[] { textRecord }); nfcAdapter.enableForegroundNdefPush(activity, msg); } public static void disableNFCAdapter(Activity activity, NfcAdapter nfcAdapter){ nfcAdapter.disableForegroundNdefPush(activity); } public static NdefRecord createTextRecord(String payload, boolean encodeInUtf8) { byte[] langBytes = Locale.getDefault().getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; } public static void resolveNFCIntent(Intent intent, NearField nfc){ String action = intent.getAction(); //activity.setIntent(new Intent()); // Consume this intent. Is this the right thing? if (NfcAdapter.ACTION_NDEF_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. // We'll keep this database code in here for now, but it's useless, because we // can use AppInventor higher level operations to manipulate the tag data. if (nfc.ReadMode()) { 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 // For now, just ignore it. Later we might want to signal an error to the // app user. 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}; } byte[] payload = msgs[0].getRecords()[0].getPayload(); //the substring chops off the two language encoding bits at the beginning String message = new String(payload).substring(3); nfc.TagRead(message); } else { Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); NdefMessage msg = null; if(nfc.WriteType() == 1) { NdefRecord textRecord = createTextRecord(nfc.TextToWrite(),true); msg = new NdefMessage(new NdefRecord[] { textRecord }); } if (writeNFCTag(msg, detectedTag)) { nfc.TagWritten(); } } } else { Log.e("nearfield", "Unknown intent " + intent); } } /* * Writes an NdefMessage to a NFC tag */ public static boolean writeNFCTag(NdefMessage message, Tag tag) { int size = message.toByteArray().length; try { Ndef ndef = Ndef.get(tag); if (ndef != null) { ndef.connect(); if (!ndef.isWritable()) { return false; } if (ndef.getMaxSize() < size) { return false; } ndef.writeNdefMessage(message); return true; } else { NdefFormatable format = NdefFormatable.get(tag); if (format != null) { try { format.connect(); format.format(message); return true; } catch (IOException e) { return false; } } else { return false; } } } catch (Exception e) { return false; } } }