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:
@@ -3,11 +3,12 @@ include $(CLEAR_VARS)
|
|||||||
|
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
|
||||||
|
LOCAL_STATIC_JAVA_LIBRARIES := guava
|
||||||
|
|
||||||
# Only compile source java files in this apk.
|
# Only compile source java files in this apk.
|
||||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||||
|
|
||||||
LOCAL_PACKAGE_NAME := TagApp
|
LOCAL_PACKAGE_NAME := TagApp
|
||||||
# LOCAL_PROGUARD_EABLED := disabled
|
|
||||||
|
|
||||||
# LOCAL_SDK_VERSION := current
|
# LOCAL_SDK_VERSION := current
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
<activity android:name="TagSelector"></activity>
|
<activity android:name="TagSelector"></activity>
|
||||||
<activity android:name="TagList"></activity>
|
<activity android:name="TagList"></activity>
|
||||||
|
<activity android:name="SaveTag"></activity>
|
||||||
<receiver android:name=".TagBroadcastReceiver">
|
<receiver android:name=".TagBroadcastReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/>
|
<action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/>
|
||||||
|
|||||||
150
apps/Tag/src/com/android/apps/tag/NdefUtil.java
Normal file
150
apps/Tag/src/com/android/apps/tag/NdefUtil.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
apps/Tag/src/com/android/apps/tag/SaveTag.java
Normal file
52
apps/Tag/src/com/android/apps/tag/SaveTag.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,13 @@ package com.android.apps.tag;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
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)
|
* @author nnk@google.com (Nick Kralevich)
|
||||||
@@ -26,28 +33,51 @@ import android.database.sqlite.SQLiteOpenHelper;
|
|||||||
public class TagDBHelper extends SQLiteOpenHelper {
|
public class TagDBHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
private static final int DATABASE_VERSION = 1;
|
private static final int DATABASE_VERSION = 1;
|
||||||
private static final String TABLE_CREATE = "create table Tags ("
|
|
||||||
+ "_id INTEGER PRIMARY KEY ASC, "
|
private static final String NDEF_MSG = "create table NdefMessage ("
|
||||||
+ "description TEXT, "
|
+ "_id INTEGER NOT NULL, "
|
||||||
+ "date TEXT"
|
+ "bytes TEXT NOT NULL, " // TODO: This should be a blob
|
||||||
|
+ "date TEXT NOT NULL, "
|
||||||
|
+ "PRIMARY KEY(_id)"
|
||||||
+ ")";
|
+ ")";
|
||||||
|
|
||||||
private static final String FAKE_DATA =
|
private static final String INSERT =
|
||||||
"INSERT INTO Tags (description) values ('hello world')";
|
"INSERT INTO NdefMessage (bytes, date) values (?, ?)";
|
||||||
|
|
||||||
private static final String FAKE_DATA2 =
|
|
||||||
"INSERT INTO Tags (description) values ('hi world')";
|
|
||||||
|
|
||||||
|
|
||||||
public TagDBHelper(Context context) {
|
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
|
@Override
|
||||||
public void onCreate(SQLiteDatabase db) {
|
public void onCreate(SQLiteDatabase db) {
|
||||||
db.execSQL(TABLE_CREATE);
|
db.execSQL(NDEF_MSG);
|
||||||
db.execSQL(FAKE_DATA);
|
|
||||||
db.execSQL(FAKE_DATA2);
|
// 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
|
@Override
|
||||||
|
|||||||
@@ -34,24 +34,24 @@ import android.widget.Toast;
|
|||||||
*/
|
*/
|
||||||
public class TagList extends ListActivity implements DialogInterface.OnClickListener {
|
public class TagList extends ListActivity implements DialogInterface.OnClickListener {
|
||||||
|
|
||||||
|
private SQLiteDatabase db;
|
||||||
|
private Cursor cursor;
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
Toast.makeText(getBaseContext(), "entered method", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getBaseContext(), "entered method", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
SQLiteDatabase db = new TagDBHelper(this.getBaseContext()).getReadableDatabase();
|
db = new TagDBHelper(getBaseContext()).getReadableDatabase();
|
||||||
Cursor c = db.query("Tags", new String[] { "_id", "description" }, null, null, null, null, null);
|
cursor = db.query("NdefMessage", new String[] { "_id", "bytes" }, null, null, null, null, null);
|
||||||
SimpleCursorAdapter sca =
|
SimpleCursorAdapter sca =
|
||||||
new SimpleCursorAdapter(this,
|
new SimpleCursorAdapter(this,
|
||||||
android.R.layout.two_line_list_item,
|
android.R.layout.two_line_list_item,
|
||||||
c,
|
cursor,
|
||||||
new String[] { "description" },
|
new String[] { "bytes" },
|
||||||
new int[] { android.R.id.text1 });
|
new int[] { android.R.id.text1 });
|
||||||
|
|
||||||
setListAdapter(sca);
|
setListAdapter(sca);
|
||||||
registerForContextMenu(getListView());
|
registerForContextMenu(getListView());
|
||||||
c.close();
|
|
||||||
db.close();
|
|
||||||
Toast.makeText(getBaseContext(), "exit method", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getBaseContext(), "exit method", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +73,17 @@ public class TagList extends ListActivity implements DialogInterface.OnClickList
|
|||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
if (db != null) {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
showDialog(1);
|
showDialog(1);
|
||||||
|
|||||||
@@ -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 {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -32,6 +32,10 @@ public class Tags extends TabActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(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);
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
Resources res = getResources();
|
Resources res = getResources();
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user