/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.samples.apps.iosched.ui; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.Ndef; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.TaskStackBuilder; import android.widget.Toast; import com.google.samples.apps.iosched.Config; import com.google.samples.apps.iosched.R; import com.google.samples.apps.iosched.provider.ScheduleContract; import com.google.samples.apps.iosched.util.AnalyticsManager; import java.util.Arrays; import static com.google.samples.apps.iosched.util.LogUtils.*; public class NfcBadgeActivity extends Activity { private static final String TAG = makeLogTag(NfcBadgeActivity.class); private static final String ATTENDEE_URL_PREFIX = "\u0004plus.google.com/"; // For debug purposes public static final String ACTION_SIMULATE = "com.google.samples.apps.iosched.ACTION_SIMULATE"; @Override public void onStart() { super.onStart(); AnalyticsManager.initializeAnalyticsTracker(getApplicationContext()); // Check for NFC data Intent i = getIntent(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(i.getAction())) { LOGI(TAG, "Badge detected"); /* [ANALYTICS:EVENT] * TRIGGER: Scan another attendee's badge. * CATEGORY: 'NFC' * ACTION: 'Read' * LABEL: 'Badge'. Badge info IS NOT collected. * [/ANALYTICS] */ AnalyticsManager.sendEvent("NFC", "Read", "Badge"); readTag((Tag) i.getParcelableExtra(NfcAdapter.EXTRA_TAG)); } else if (ACTION_SIMULATE.equals(i.getAction()) && Config.IS_DOGFOOD_BUILD) { String simulatedUrl = i.getDataString(); LOGD(TAG, "Simulating badge scanning with URL " + simulatedUrl); // replace https by Unicode character 4, as per normal badge encoding rules recordBadge(simulatedUrl.replace("https://", "\u0004")); } else { LOGW(TAG, "Invalid action in Intent to NfcBadgeActivity: " + i.getAction()); } finish(); } @Override public void onStop() { super.onStop(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } private void readTag(Tag t) { byte[] id = t.getId(); // get NDEF tag details Ndef ndefTag = Ndef.get(t); // get NDEF message details NdefMessage ndefMesg = ndefTag.getCachedNdefMessage(); if (ndefMesg == null) { return; } NdefRecord[] ndefRecords = ndefMesg.getRecords(); if (ndefRecords == null) { return; } for (NdefRecord record : ndefRecords) { short tnf = record.getTnf(); String type = new String(record.getType()); if (tnf == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(type.getBytes(), NdefRecord.RTD_URI)) { String url = new String(record.getPayload()); recordBadge(url); } } } private void recordBadge(String url) { LOGD(TAG, "Recording badge, URL " + url); if (url.startsWith(ATTENDEE_URL_PREFIX)) { addToHistory(url); Intent i = new Intent(this, PeopleIveMetActivity.class); TaskStackBuilder .create(getApplicationContext()) .addNextIntent(i) .startActivities(); return; } else { LOGD(TAG, "URL in badge (" + url + ") does not start with prefix URL (" + ATTENDEE_URL_PREFIX + ")"); LOGW(TAG, "Invalid URL in badge: " + url); } } private void addToHistory(String url) { Uri uri = Uri.parse(url); final String plusId = uri.getLastPathSegment(); if (!isValidPlusId(plusId)) { LOGE(TAG, "Unknown ID format: " + plusId); return; } if (isDummyPlusId(plusId)) { Toast.makeText(this, R.string.people_ive_met_dummy_badge, Toast.LENGTH_SHORT).show(); return; } new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { Cursor cursor = null; try { cursor = getContentResolver().query( ScheduleContract.PeopleIveMet.buildPersonUri(plusId), new String[]{ScheduleContract.PeopleIveMet.PERSON_ID}, null, null, null); if (0 < cursor.getCount()) { ContentValues values = new ContentValues(); values.put(ScheduleContract.PeopleIveMet.PERSON_TIMESTAMP, System.currentTimeMillis()); getContentResolver().update( ScheduleContract.PeopleIveMet.buildPersonUri(plusId), values, null, null); } else { ContentValues values = new ContentValues(); values.put(ScheduleContract.PeopleIveMet.PERSON_ID, plusId); values.put(ScheduleContract.PeopleIveMet.PERSON_TIMESTAMP, System.currentTimeMillis()); values.put(ScheduleContract.PeopleIveMet.PERSON_IMAGE_URL, (String) null); values.put(ScheduleContract.PeopleIveMet.PERSON_NAME, (String) null); getContentResolver().insert( ScheduleContract.PeopleIveMet.CONTENT_URI, values); } } finally { if (null != cursor) { cursor.close(); } } return null; } }.execute(); } private boolean isDummyPlusId(String plusId) { return plusId.startsWith("556655665566"); } private boolean isValidPlusId(String id) { return id.matches("^([0-9]{15,}|\\+\\w+)$"); } }