am 08ad0fde: Merge "new SaveTag activity, additional utilities" into gingerbread

Merge commit '08ad0fde5ee365133b9ac1406767f2778b0c93ea' into gingerbread-plus-aosp

* commit '08ad0fde5ee365133b9ac1406767f2778b0c93ea':
  new SaveTag activity, additional utilities
This commit is contained in:
Nick Kralevich
2010-10-05 12:29:59 -07:00
committed by Android Git Automerger
9 changed files with 269 additions and 90 deletions

View File

@@ -3,11 +3,12 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := guava
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := TagApp
# LOCAL_PROGUARD_EABLED := disabled
# LOCAL_SDK_VERSION := current

View File

@@ -31,6 +31,7 @@
<activity android:name="TagSelector"></activity>
<activity android:name="TagList"></activity>
<activity android:name="SaveTag"></activity>
<receiver android:name=".TagBroadcastReceiver">
<intent-filter>
<action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/>

View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.apps.tag;
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.primitives.Bytes;
import com.trustedlogic.trustednfc.android.NdefRecord;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charsets;
import java.util.Arrays;
/**
* Utilities for dealing with conversions to and from NdefRecords.
*
* TODO: Possibly move this class into core Android.
*/
public class NdefUtil {
private static final byte[] EMPTY = new byte[0];
/**
* NFC Forum "URI Record Type Definition"
*
* This is a mapping of "URI Identifier Codes" to URI string prefixes,
* per section 3.2.2 of the NFC Forum URI Record Type Definition document.
*/
private static final
BiMap<Byte, String> URI_PREFIX_MAP = ImmutableBiMap.<Byte, String>builder()
.put((byte) 0x00, "")
.put((byte) 0x01, "http://www.")
.put((byte) 0x02, "https://www.")
.put((byte) 0x03, "http://")
.put((byte) 0x04, "https://")
.put((byte) 0x05, "tel:")
.put((byte) 0x06, "mailto:")
.put((byte) 0x07, "ftp://anonymous:anonymous@")
.put((byte) 0x08, "ftp://ftp.")
.put((byte) 0x09, "ftps://")
.put((byte) 0x0A, "sftp://")
.put((byte) 0x0B, "smb://")
.put((byte) 0x0C, "nfs://")
.put((byte) 0x0D, "ftp://")
.put((byte) 0x0E, "dav://")
.put((byte) 0x0F, "news:")
.put((byte) 0x10, "telnet://")
.put((byte) 0x11, "imap:")
.put((byte) 0x12, "rtsp://")
.put((byte) 0x13, "urn:")
.put((byte) 0x14, "pop:")
.put((byte) 0x15, "sip:")
.put((byte) 0x16, "sips:")
.put((byte) 0x17, "tftp:")
.put((byte) 0x18, "btspp://")
.put((byte) 0x19, "btl2cap://")
.put((byte) 0x1A, "btgoep://")
.put((byte) 0x1B, "tcpobex://")
.put((byte) 0x1C, "irdaobex://")
.put((byte) 0x1D, "file://")
.put((byte) 0x1E, "urn:epc:id:")
.put((byte) 0x1F, "urn:epc:tag:")
.put((byte) 0x20, "urn:epc:pat:")
.put((byte) 0x21, "urn:epc:raw:")
.put((byte) 0x22, "urn:epc:")
.put((byte) 0x23, "urn:nfc:")
.build();
/**
* Create a new {@link NdefRecord} containing the supplied {@link URI}.
*/
public static NdefRecord toUriRecord(URI uri) {
byte[] uriBytes = uri.toString().getBytes(Charsets.UTF_8);
/*
* We prepend 0x00 to the bytes of the URI to indicate that this
* is the entire URI, and we are not taking advantage of the
* URI shortening rules in the NFC Forum URI spec section 3.2.2.
* This produces a NdefRecord which is slightly larger than
* necessary.
*
* In the future, we should use the URI shortening rules in 3.2.2
* to create a smaller NdefRecord.
*/
byte[] payload = Bytes.concat(new byte[] { 0x00 }, uriBytes);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN_TYPE,
NdefRecord.TYPE_URI, EMPTY, payload);
}
/**
* Convert {@link NdefRecord} into a {@link URI}.
*
* TODO: This class does not handle NdefRecords where the TNF
* (Type Name Format) of the class is {@link NdefRecord#TNF_ABSOLUTE_URI}.
* This should be fixed.
*
* @throws URISyntaxException if the {@code NdefRecord} contains an
* invalid URI.
* @throws IllegalArgumentException if the NdefRecord is not a
* record containing a URI.
*/
public static URI toURI(NdefRecord record) throws URISyntaxException {
Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN_TYPE);
Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.TYPE_URI));
byte[] payload = record.getPayload();
/*
* payload[0] contains the URI Identifier Code, per the
* NFC Forum "URI Record Type Definition" section 3.2.2.
*
* payload[1]...payload[payload.length - 1] contains the rest of
* the URI.
*/
String prefix = URI_PREFIX_MAP.get(payload[0]);
byte[] fullUri = Bytes.concat(
prefix.getBytes(Charsets.UTF_8),
Arrays.copyOfRange(payload, 1, payload.length - 1));
return new URI(new String(fullUri, Charsets.UTF_8));
}
public static boolean isURI(NdefRecord record) {
try {
toURI(record);
return true;
} catch (IllegalArgumentException e) {
return false;
} catch (URISyntaxException e) {
return false;
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.apps.tag;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;
/**
* @author nnk@google.com (Nick Kralevich)
*/
public class SaveTag extends Activity implements DialogInterface.OnClickListener {
@Override
protected void onStart() {
super.onStart();
showDialog(1);
String s = getIntent().getExtras().toString();
Toast.makeText(this.getBaseContext(), "SaveTag: " + s, Toast.LENGTH_SHORT).show();
}
@Override
protected Dialog onCreateDialog(int id, Bundle args) {
return new AlertDialog.Builder(this)
.setTitle("Welcome! T2000 Festival")
.setPositiveButton("Save", this)
.setNegativeButton("Cancel", this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
}

View File

@@ -19,6 +19,13 @@ package com.android.apps.tag;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import com.google.common.annotations.VisibleForTesting;
import com.trustedlogic.trustednfc.android.NdefMessage;
import com.trustedlogic.trustednfc.android.NdefRecord;
import java.net.URI;
import java.util.Date;
/**
* @author nnk@google.com (Nick Kralevich)
@@ -26,28 +33,51 @@ import android.database.sqlite.SQLiteOpenHelper;
public class TagDBHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String TABLE_CREATE = "create table Tags ("
+ "_id INTEGER PRIMARY KEY ASC, "
+ "description TEXT, "
+ "date TEXT"
private static final String NDEF_MSG = "create table NdefMessage ("
+ "_id INTEGER NOT NULL, "
+ "bytes TEXT NOT NULL, " // TODO: This should be a blob
+ "date TEXT NOT NULL, "
+ "PRIMARY KEY(_id)"
+ ")";
private static final String FAKE_DATA =
"INSERT INTO Tags (description) values ('hello world')";
private static final String FAKE_DATA2 =
"INSERT INTO Tags (description) values ('hi world')";
private static final String INSERT =
"INSERT INTO NdefMessage (bytes, date) values (?, ?)";
public TagDBHelper(Context context) {
super(context, "Tags.db", null, DATABASE_VERSION);
this(context, "Tags.db");
}
@VisibleForTesting
public TagDBHelper(Context context, String dbFile) {
super(context, dbFile, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TABLE_CREATE);
db.execSQL(FAKE_DATA);
db.execSQL(FAKE_DATA2);
db.execSQL(NDEF_MSG);
// A fake message containing 1 URL
NdefMessage msg1 = new NdefMessage(new NdefRecord[] {
NdefUtil.toUriRecord(URI.create("http://www.google.com"))
});
// A fake message containing 2 URLs
NdefMessage msg2 = new NdefMessage(new NdefRecord[] {
NdefUtil.toUriRecord(URI.create("http://www.youtube.com")),
NdefUtil.toUriRecord(URI.create("http://www.android.com"))
});
insert(db, msg1);
insert(db, msg2);
}
private void insert(SQLiteDatabase db, NdefMessage msg) {
SQLiteStatement stmt = db.compileStatement(INSERT);
stmt.bindString(1, new String(msg.toByteArray())); // TODO: This should be a blob
stmt.bindString(2, new Date().toString());
stmt.executeInsert();
}
@Override

View File

@@ -34,24 +34,24 @@ import android.widget.Toast;
*/
public class TagList extends ListActivity implements DialogInterface.OnClickListener {
private SQLiteDatabase db;
private Cursor cursor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(getBaseContext(), "entered method", Toast.LENGTH_SHORT).show();
SQLiteDatabase db = new TagDBHelper(this.getBaseContext()).getReadableDatabase();
Cursor c = db.query("Tags", new String[] { "_id", "description" }, null, null, null, null, null);
db = new TagDBHelper(getBaseContext()).getReadableDatabase();
cursor = db.query("NdefMessage", new String[] { "_id", "bytes" }, null, null, null, null, null);
SimpleCursorAdapter sca =
new SimpleCursorAdapter(this,
android.R.layout.two_line_list_item,
c,
new String[] { "description" },
cursor,
new String[] { "bytes" },
new int[] { android.R.id.text1 });
setListAdapter(sca);
registerForContextMenu(getListView());
c.close();
db.close();
Toast.makeText(getBaseContext(), "exit method", Toast.LENGTH_SHORT).show();
}
@@ -73,6 +73,17 @@ public class TagList extends ListActivity implements DialogInterface.OnClickList
.create();
}
@Override
protected void onDestroy() {
if (cursor != null) {
cursor.close();
}
if (db != null) {
db.close();
}
super.onDestroy();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
showDialog(1);

View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.apps.tag;
/**
* @author nnk@google.com (Nick Kralevich)
*/
public class TagUi {
}

View File

@@ -32,6 +32,10 @@ public class Tags extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// While we're doing development, delete the database every time we start.
getBaseContext().getDatabasePath("Tags.db").delete();
setContentView(R.layout.main);
Resources res = getResources();

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.apps.tag;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
/**
* @author nnk@google.com (Nick Kralevich)
*/
public class TagBroadcastReceiverTest extends ActivityInstrumentationTestCase2<Tags> {
/**
* Creates an {@link ActivityInstrumentationTestCase2} for the {@link Tags} activity.
*/
public TagBroadcastReceiverTest() {
super(Tags.class);
}
public void testWrongMessage() {
TagBroadcastReceiver receiver = new TagBroadcastReceiver();
Intent i = new Intent().setAction("BOGUS");
receiver.onReceive(getActivity().getBaseContext(), i);
assertDatabaseNoChange(receiver);
}
private void assertDatabaseNoChange(TagBroadcastReceiver receiver) {
// TODO: implement
}
}