Update NFC samples.
o Remove NFCDemo sample app. It's janky and is mostly parsing code that isn't needed anymore. o Use new NDEF APIs for parsing and creating records o Use nicer setNdefPushMessage() API o Delete helper NDEF code that is not needed any more o Use URL instead of Text for the foreground push demo o Mark AndroidBeamDemo a test so it gets installed in data not system Change-Id: I75eda84019c2075956688e26f2598f126d5659a2
This commit is contained in:
@@ -169,7 +169,6 @@ development/samples/JetBoy samples/${PLATFORM_NAME}/JetBoy
|
|||||||
development/samples/LunarLander samples/${PLATFORM_NAME}/LunarLander
|
development/samples/LunarLander samples/${PLATFORM_NAME}/LunarLander
|
||||||
development/samples/MultiResolution samples/${PLATFORM_NAME}/MultiResolution
|
development/samples/MultiResolution samples/${PLATFORM_NAME}/MultiResolution
|
||||||
development/samples/NotePad samples/${PLATFORM_NAME}/NotePad
|
development/samples/NotePad samples/${PLATFORM_NAME}/NotePad
|
||||||
development/samples/NFCDemo samples/${PLATFORM_NAME}/NFCDemo
|
|
||||||
development/samples/RandomMusicPlayer samples/${PLATFORM_NAME}/RandomMusicPlayer
|
development/samples/RandomMusicPlayer samples/${PLATFORM_NAME}/RandomMusicPlayer
|
||||||
development/samples/SpellChecker/SampleSpellCheckerService samples/${PLATFORM_NAME}/SpellChecker/SampleSpellCheckerService
|
development/samples/SpellChecker/SampleSpellCheckerService samples/${PLATFORM_NAME}/SpellChecker/SampleSpellCheckerService
|
||||||
development/samples/SpellChecker/HelloSpellChecker samples/${PLATFORM_NAME}/SpellChecker/HelloSpellChecker
|
development/samples/SpellChecker/HelloSpellChecker samples/${PLATFORM_NAME}/SpellChecker/HelloSpellChecker
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
LOCAL_PATH:= $(call my-dir)
|
LOCAL_PATH:= $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_MODULE_TAGS := samples
|
LOCAL_MODULE_TAGS := samples tests
|
||||||
|
|
||||||
# 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)
|
||||||
|
|||||||
@@ -73,8 +73,7 @@ public class Beam extends Activity implements CreateNdefMessageCallback,
|
|||||||
time.setToNow();
|
time.setToNow();
|
||||||
String text = ("Beam me up!\n\n" +
|
String text = ("Beam me up!\n\n" +
|
||||||
"Beam Time: " + time.format("%H:%M:%S"));
|
"Beam Time: " + time.format("%H:%M:%S"));
|
||||||
NdefMessage msg = new NdefMessage(
|
NdefMessage msg = new NdefMessage(NdefRecord.createMime(
|
||||||
new NdefRecord[] { createMimeRecord(
|
|
||||||
"application/com.example.android.beam", text.getBytes())
|
"application/com.example.android.beam", text.getBytes())
|
||||||
/**
|
/**
|
||||||
* The Android Application Record (AAR) is commented out. When a device
|
* The Android Application Record (AAR) is commented out. When a device
|
||||||
@@ -85,7 +84,7 @@ public class Beam extends Activity implements CreateNdefMessageCallback,
|
|||||||
* uses the tag dispatch system.
|
* uses the tag dispatch system.
|
||||||
*/
|
*/
|
||||||
//,NdefRecord.createApplicationRecord("com.example.android.beam")
|
//,NdefRecord.createApplicationRecord("com.example.android.beam")
|
||||||
});
|
);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,18 +137,6 @@ public class Beam extends Activity implements CreateNdefMessageCallback,
|
|||||||
mInfoText.setText(new String(msg.getRecords()[0].getPayload()));
|
mInfoText.setText(new String(msg.getRecords()[0].getPayload()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a custom MIME type encapsulated in an NDEF record
|
|
||||||
*
|
|
||||||
* @param mimeType
|
|
||||||
*/
|
|
||||||
public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
|
|
||||||
byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
|
|
||||||
NdefRecord mimeRecord = new NdefRecord(
|
|
||||||
NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
|
|
||||||
return mimeRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// If NFC is not available, we won't be needing this menu
|
// If NFC is not available, we won't be needing this menu
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import android.nfc.NfcAdapter;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example of how to use the NFC foreground NDEF push APIs.
|
* An example of how to use the NFC foreground NDEF push APIs.
|
||||||
*/
|
*/
|
||||||
@@ -36,51 +33,23 @@ public class ForegroundNdefPush extends Activity {
|
|||||||
private TextView mText;
|
private TextView mText;
|
||||||
private NdefMessage mMessage;
|
private NdefMessage mMessage;
|
||||||
|
|
||||||
public static NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) {
|
|
||||||
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
|
|
||||||
|
|
||||||
Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
|
|
||||||
byte[] textBytes = text.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);
|
|
||||||
|
|
||||||
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedState) {
|
public void onCreate(Bundle savedState) {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
|
|
||||||
mAdapter = NfcAdapter.getDefaultAdapter(this);
|
mAdapter = NfcAdapter.getDefaultAdapter(this);
|
||||||
|
|
||||||
|
// Create an NDEF message a URL
|
||||||
|
mMessage = new NdefMessage(NdefRecord.createUri("http://www.android.com"));
|
||||||
|
|
||||||
setContentView(R.layout.foreground_dispatch);
|
setContentView(R.layout.foreground_dispatch);
|
||||||
mText = (TextView) findViewById(R.id.text);
|
mText = (TextView) findViewById(R.id.text);
|
||||||
|
|
||||||
if (mAdapter != null) {
|
if (mAdapter != null) {
|
||||||
mText.setText("Tap another Android phone with NFC to push 'NDEF Push Sample'");
|
mAdapter.setNdefPushMessage(mMessage, this);
|
||||||
|
mText.setText("Tap another Android phone with NFC to push a URL");
|
||||||
} else {
|
} else {
|
||||||
mText.setText("This phone is not NFC enabled.");
|
mText.setText("This phone is not NFC enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an NDEF message with some sample text
|
|
||||||
mMessage = new NdefMessage(
|
|
||||||
new NdefRecord[] { newTextRecord("NDEF Push Sample", Locale.ENGLISH, true)});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
if (mAdapter != null) mAdapter.enableForegroundNdefPush(this, mMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
if (mAdapter != null) mAdapter.disableForegroundNdefPush(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
LOCAL_PATH:= $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
LOCAL_MODULE_TAGS := samples tests
|
|
||||||
|
|
||||||
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 := NFCDemo
|
|
||||||
|
|
||||||
LOCAL_SDK_VERSION := current
|
|
||||||
|
|
||||||
include $(BUILD_PACKAGE)
|
|
||||||
|
|
||||||
# Use the following include to make our test apk.
|
|
||||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Declare the contents of this Android application. The namespace
|
|
||||||
attribute brings in the Android platform namespace, and the package
|
|
||||||
supplies a unique name for the application. When writing your
|
|
||||||
own application, the package name must be changed from "com.example.*"
|
|
||||||
to come from a domain that you own or have control over. -->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.example.android.nfc"
|
|
||||||
>
|
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
|
||||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
|
||||||
<application
|
|
||||||
android:icon="@drawable/icon"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
>
|
|
||||||
<activity android:name=".simulator.FakeTagsActivity"
|
|
||||||
android:theme="@android:style/Theme.NoTitleBar">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name="TagViewer"
|
|
||||||
android:theme="@android:style/Theme.NoTitleBar"
|
|
||||||
>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
<uses-sdk android:minSdkVersion="9" />
|
|
||||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
|
||||||
</manifest>
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
|
|
||||||
Copyright (c) 2010-2011, 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
This product also includes the following third-party components:
|
|
||||||
|
|
||||||
* Guava (libs/guava-10.0.1.jar)
|
|
||||||
http://code.google.com/p/guava-libraries/
|
|
||||||
|
|
||||||
Copyright 2004-2011 The Guava Authors
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
<p>
|
|
||||||
Near-field Communication or NFC is a standard defined by the
|
|
||||||
<a href=http://www.nfc-forum.org/home>NFC Forum
|
|
||||||
</a>.
|
|
||||||
NFC Data Exchange Format (NDEF) defines a common data format between NFC-compliant devices and tags.
|
|
||||||
This demo application shows how to read a NDEF Tags using using Android 2.3 SDK APIs.
|
|
||||||
The NFC Tags consist of data encoded in NDEF Message format specified by NFC Forum Type 2 Specification.
|
|
||||||
Each NDEF message consists of one or more NDEF Records.
|
|
||||||
|
|
||||||
You need a NFC compliant device and a NFC compliant Tag to use this sample app. Or else, you could use
|
|
||||||
the FakeTagsActivity displayed at launch of this sample app, to generate fake Tag broadcasts from the emulator.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The application includes:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/TagViewer.html">
|
|
||||||
<code>TagViewer
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— an
|
|
||||||
<code>Activity
|
|
||||||
</code> that handles a broadcast of a new tag that the device
|
|
||||||
just discovered, parses it, and displays its record contents in a
|
|
||||||
<code>ListActivity
|
|
||||||
</code>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/NdefMessageParser.html">
|
|
||||||
<code> NdefMessageParser
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— parses the record type of records within the NDEF message.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/record/ParsedNdefRecord.html">
|
|
||||||
<code>ParsedNdefRecord
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— an interface implemented by all parsed NdefRecord types.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/record/SmartPoster.html">
|
|
||||||
<code>SmartPoster
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— a representation of an NFC Forum Smart Poster Record Type.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/record/TextRecord.html">
|
|
||||||
<code>TextRecord
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— a representation of an NFC Forum Text Record Type.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/record/UriRecord.html">
|
|
||||||
<code>UriRecord
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— a representation of an NFC Forum Uri Record Type.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/simulator/FakeTagsActivity.html">
|
|
||||||
<code>FakeTagsActivity
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— A activity that launches tags as if they had been scanned.
|
|
||||||
This is useful if you don't have access to NFC enabled device or tag.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="src/com/example/android/nfc/simulator/MockNdefMessages.html">
|
|
||||||
<code>MockNdefMessages
|
|
||||||
</code>
|
|
||||||
</a>
|
|
||||||
— this class provides a list of fake NFC Ndef format Tags.
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<p>If you are developing an application that uses the NFC API, remember that the feature
|
|
||||||
is supported only on Android 2.3 (API level 9) and higher versions of the platform. Also,
|
|
||||||
among devices running Android 2.3 (API level 9) or higher, not all devices will offer NFC
|
|
||||||
support. To ensure that your application can only be installed on devices that are capable
|
|
||||||
of supporting NFC, remember to add the following to the application's manifest before
|
|
||||||
publishing to Android Market:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code><uses-sdk android:minSdkVersion="9" />
|
|
||||||
</code>,
|
|
||||||
which indicates to Android Market and the platform that your application requires
|
|
||||||
Android 2.3 or higher. For more information, see
|
|
||||||
<a href="../../../guide/appendix/api-levels.html">API Levels
|
|
||||||
</a>
|
|
||||||
and the documentation for the
|
|
||||||
<a href="../../../guide/topics/manifest/uses-sdk-element.html">
|
|
||||||
<code><uses-sdk>
|
|
||||||
</code>
|
|
||||||
</a> element.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>To control how Android Market filters your application
|
|
||||||
from devices that do not support NFC, remember to add the following to the application's manifest
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code><uses-feature android:name="android.hardware.nfc" />
|
|
||||||
</code>,
|
|
||||||
which tells Android Market that your application uses the NFC API. The declaration
|
|
||||||
should include an
|
|
||||||
<code>android:required
|
|
||||||
</code> attribute that indicates whether you want
|
|
||||||
Android Market to filter the application from devices that do not offer NFC support. Other
|
|
||||||
<code><uses-feature>
|
|
||||||
</code> declarations may also be needed, depending on your
|
|
||||||
implementation. For more information, see the documentation for the
|
|
||||||
<a href="../../../guide/topics/manifest/uses-feature-element.html">
|
|
||||||
<code><uses-feature>
|
|
||||||
</code>
|
|
||||||
</a> element.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>For more information about using the NFC API, see the
|
|
||||||
<a href="../../../reference/android/nfc/package-summary.html">
|
|
||||||
<code>android.nfc</code>
|
|
||||||
</a>
|
|
||||||
documentation.
|
|
||||||
</p>
|
|
||||||
<img alt="" src="../images/NfcDemo.png"/>
|
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/listDivider"
|
|
||||||
/>
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="4dip"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:maxLines="5"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
/>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<!-- Title -->
|
|
||||||
<TextView android:id="@+id/title" android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" android:singleLine="true"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:textStyle="bold" android:shadowColor="#BB000000"
|
|
||||||
android:shadowRadius="2.75" android:gravity="center_vertical" />
|
|
||||||
<!-- Content -->
|
|
||||||
<ScrollView android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dip" android:layout_weight="1">
|
|
||||||
<LinearLayout android:id="@+id/list" android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" android:orientation="vertical" />
|
|
||||||
</ScrollView>
|
|
||||||
</LinearLayout>
|
|
||||||
Binary file not shown.
@@ -1,28 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
|
||||||
|
|
||||||
<!-- The title of the NFC tag application -->
|
|
||||||
<string name="app_name">NFCDemo</string>
|
|
||||||
|
|
||||||
<!-- The title for the activity that shows a tag that was just scanned -->
|
|
||||||
<string name="title_scanned_tag">New tag collected</string>
|
|
||||||
|
|
||||||
<!-- Heading for the text of the content in the "my tag" feature. -->
|
|
||||||
<string name="tag_text">Text</string>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -1,57 +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.example.android.nfc;
|
|
||||||
|
|
||||||
import android.nfc.NdefMessage;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
|
|
||||||
import com.example.android.nfc.record.ParsedNdefRecord;
|
|
||||||
import com.example.android.nfc.record.SmartPoster;
|
|
||||||
import com.example.android.nfc.record.TextRecord;
|
|
||||||
import com.example.android.nfc.record.UriRecord;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class for creating {@link ParsedNdefMessage}s.
|
|
||||||
*/
|
|
||||||
public class NdefMessageParser {
|
|
||||||
|
|
||||||
// Utility class
|
|
||||||
private NdefMessageParser() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse an NdefMessage */
|
|
||||||
public static List<ParsedNdefRecord> parse(NdefMessage message) {
|
|
||||||
return getRecords(message.getRecords());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<ParsedNdefRecord> getRecords(NdefRecord[] records) {
|
|
||||||
List<ParsedNdefRecord> elements = new ArrayList<ParsedNdefRecord>();
|
|
||||||
for (NdefRecord record : records) {
|
|
||||||
if (UriRecord.isUri(record)) {
|
|
||||||
elements.add(UriRecord.parse(record));
|
|
||||||
} else if (TextRecord.isText(record)) {
|
|
||||||
elements.add(TextRecord.parse(record));
|
|
||||||
} else if (SmartPoster.isPoster(record)) {
|
|
||||||
elements.add(SmartPoster.parse(record));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +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.example.android.nfc;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.nfc.NdefMessage;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
import android.nfc.NfcAdapter;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.example.android.nfc.record.ParsedNdefRecord;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link Activity} which handles a broadcast of a new tag that the device
|
|
||||||
* just discovered.
|
|
||||||
*/
|
|
||||||
public class TagViewer extends Activity {
|
|
||||||
|
|
||||||
static final String TAG = "ViewTag";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This activity will finish itself in this amount of time if the user
|
|
||||||
* doesn't do anything.
|
|
||||||
*/
|
|
||||||
static final int ACTIVITY_TIMEOUT_MS = 1 * 1000;
|
|
||||||
|
|
||||||
TextView mTitle;
|
|
||||||
|
|
||||||
LinearLayout mTagContent;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.tag_viewer);
|
|
||||||
mTagContent = (LinearLayout) findViewById(R.id.list);
|
|
||||||
mTitle = (TextView) findViewById(R.id.title);
|
|
||||||
resolveIntent(getIntent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void resolveIntent(Intent intent) {
|
|
||||||
// Parse the intent
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (NfcAdapter.ACTION_TAG_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.
|
|
||||||
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
|
|
||||||
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};
|
|
||||||
}
|
|
||||||
// Setup the views
|
|
||||||
setTitle(R.string.title_scanned_tag);
|
|
||||||
buildTagViews(msgs);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Unknown intent " + intent);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildTagViews(NdefMessage[] msgs) {
|
|
||||||
if (msgs == null || msgs.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(this);
|
|
||||||
LinearLayout content = mTagContent;
|
|
||||||
// Clear out any old views in the content area, for example if you scan
|
|
||||||
// two tags in a row.
|
|
||||||
content.removeAllViews();
|
|
||||||
// Parse the first message in the list
|
|
||||||
// Build views for all of the sub records
|
|
||||||
List<ParsedNdefRecord> records = NdefMessageParser.parse(msgs[0]);
|
|
||||||
final int size = records.size();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
ParsedNdefRecord record = records.get(i);
|
|
||||||
content.addView(record.getView(this, inflater, content, i));
|
|
||||||
inflater.inflate(R.layout.tag_divider, content, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewIntent(Intent intent) {
|
|
||||||
setIntent(intent);
|
|
||||||
resolveIntent(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTitle(CharSequence title) {
|
|
||||||
mTitle.setText(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +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.example.android.nfc.record;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
|
|
||||||
public interface ParsedNdefRecord {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a view to display this record.
|
|
||||||
*/
|
|
||||||
public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent,
|
|
||||||
int offset);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,222 +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.example.android.nfc.record;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.nfc.FormatException;
|
|
||||||
import android.nfc.NdefMessage;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.ViewGroup.LayoutParams;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import com.example.android.nfc.NdefMessageParser;
|
|
||||||
import com.example.android.nfc.R;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A representation of an NFC Forum "Smart Poster".
|
|
||||||
*/
|
|
||||||
public class SmartPoster implements ParsedNdefRecord {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NFC Forum Smart Poster Record Type Definition section 3.2.1.
|
|
||||||
*
|
|
||||||
* "The Title record for the service (there can be many of these in
|
|
||||||
* different languages, but a language MUST NOT be repeated). This record is
|
|
||||||
* optional."
|
|
||||||
*/
|
|
||||||
private final TextRecord mTitleRecord;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NFC Forum Smart Poster Record Type Definition section 3.2.1.
|
|
||||||
*
|
|
||||||
* "The URI record. This is the core of the Smart Poster, and all other
|
|
||||||
* records are just metadata about this record. There MUST be one URI record
|
|
||||||
* and there MUST NOT be more than one."
|
|
||||||
*/
|
|
||||||
private final UriRecord mUriRecord;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NFC Forum Smart Poster Record Type Definition section 3.2.1.
|
|
||||||
*
|
|
||||||
* "The Action record. This record describes how the service should be
|
|
||||||
* treated. For example, the action may indicate that the device should save
|
|
||||||
* the URI as a bookmark or open a browser. The Action record is optional.
|
|
||||||
* If it does not exist, the device may decide what to do with the service.
|
|
||||||
* If the action record exists, it should be treated as a strong suggestion;
|
|
||||||
* the UI designer may ignore it, but doing so will induce a different user
|
|
||||||
* experience from device to device."
|
|
||||||
*/
|
|
||||||
private final RecommendedAction mAction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NFC Forum Smart Poster Record Type Definition section 3.2.1.
|
|
||||||
*
|
|
||||||
* "The Type record. If the URI references an external entity (e.g., via a
|
|
||||||
* URL), the Type record may be used to declare the MIME type of the entity.
|
|
||||||
* This can be used to tell the mobile device what kind of an object it can
|
|
||||||
* expect before it opens the connection. The Type record is optional."
|
|
||||||
*/
|
|
||||||
private final String mType;
|
|
||||||
|
|
||||||
private SmartPoster(UriRecord uri, TextRecord title, RecommendedAction action, String type) {
|
|
||||||
mUriRecord = Preconditions.checkNotNull(uri);
|
|
||||||
mTitleRecord = title;
|
|
||||||
mAction = Preconditions.checkNotNull(action);
|
|
||||||
mType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UriRecord getUriRecord() {
|
|
||||||
return mUriRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the title of the smart poster. This may be {@code null}.
|
|
||||||
*/
|
|
||||||
public TextRecord getTitle() {
|
|
||||||
return mTitleRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SmartPoster parse(NdefRecord record) {
|
|
||||||
Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN);
|
|
||||||
Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_SMART_POSTER));
|
|
||||||
try {
|
|
||||||
NdefMessage subRecords = new NdefMessage(record.getPayload());
|
|
||||||
return parse(subRecords.getRecords());
|
|
||||||
} catch (FormatException e) {
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SmartPoster parse(NdefRecord[] recordsRaw) {
|
|
||||||
try {
|
|
||||||
Iterable<ParsedNdefRecord> records = NdefMessageParser.getRecords(recordsRaw);
|
|
||||||
UriRecord uri = Iterables.getOnlyElement(Iterables.filter(records, UriRecord.class));
|
|
||||||
TextRecord title = getFirstIfExists(records, TextRecord.class);
|
|
||||||
RecommendedAction action = parseRecommendedAction(recordsRaw);
|
|
||||||
String type = parseType(recordsRaw);
|
|
||||||
return new SmartPoster(uri, title, action, type);
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isPoster(NdefRecord record) {
|
|
||||||
try {
|
|
||||||
parse(record);
|
|
||||||
return true;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset) {
|
|
||||||
if (mTitleRecord != null) {
|
|
||||||
// Build a container to hold the title and the URI
|
|
||||||
LinearLayout container = new LinearLayout(activity);
|
|
||||||
container.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
container.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
||||||
LayoutParams.WRAP_CONTENT));
|
|
||||||
container.addView(mTitleRecord.getView(activity, inflater, container, offset));
|
|
||||||
inflater.inflate(R.layout.tag_divider, container);
|
|
||||||
container.addView(mUriRecord.getView(activity, inflater, container, offset));
|
|
||||||
return container;
|
|
||||||
} else {
|
|
||||||
// Just a URI, return a view for it directly
|
|
||||||
return mUriRecord.getView(activity, inflater, parent, offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first element of {@code elements} which is an instance of
|
|
||||||
* {@code type}, or {@code null} if no such element exists.
|
|
||||||
*/
|
|
||||||
private static <T> T getFirstIfExists(Iterable<?> elements, Class<T> type) {
|
|
||||||
Iterable<T> filtered = Iterables.filter(elements, type);
|
|
||||||
T instance = null;
|
|
||||||
if (!Iterables.isEmpty(filtered)) {
|
|
||||||
instance = Iterables.get(filtered, 0);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum RecommendedAction {
|
|
||||||
UNKNOWN((byte) -1), DO_ACTION((byte) 0), SAVE_FOR_LATER((byte) 1), OPEN_FOR_EDITING(
|
|
||||||
(byte) 2);
|
|
||||||
|
|
||||||
private static final ImmutableMap<Byte, RecommendedAction> LOOKUP;
|
|
||||||
static {
|
|
||||||
ImmutableMap.Builder<Byte, RecommendedAction> builder = ImmutableMap.builder();
|
|
||||||
for (RecommendedAction action : RecommendedAction.values()) {
|
|
||||||
builder.put(action.getByte(), action);
|
|
||||||
}
|
|
||||||
LOOKUP = builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final byte mAction;
|
|
||||||
|
|
||||||
private RecommendedAction(byte val) {
|
|
||||||
this.mAction = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte getByte() {
|
|
||||||
return mAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NdefRecord getByType(byte[] type, NdefRecord[] records) {
|
|
||||||
for (NdefRecord record : records) {
|
|
||||||
if (Arrays.equals(type, record.getType())) {
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final byte[] ACTION_RECORD_TYPE = new byte[] {'a', 'c', 't'};
|
|
||||||
|
|
||||||
private static RecommendedAction parseRecommendedAction(NdefRecord[] records) {
|
|
||||||
NdefRecord record = getByType(ACTION_RECORD_TYPE, records);
|
|
||||||
if (record == null) {
|
|
||||||
return RecommendedAction.UNKNOWN;
|
|
||||||
}
|
|
||||||
byte action = record.getPayload()[0];
|
|
||||||
if (RecommendedAction.LOOKUP.containsKey(action)) {
|
|
||||||
return RecommendedAction.LOOKUP.get(action);
|
|
||||||
}
|
|
||||||
return RecommendedAction.UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final byte[] TYPE_TYPE = new byte[] {'t'};
|
|
||||||
|
|
||||||
private static String parseType(NdefRecord[] records) {
|
|
||||||
NdefRecord type = getByType(TYPE_TYPE, records);
|
|
||||||
if (type == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new String(type.getPayload(), Charsets.UTF_8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +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.example.android.nfc.record;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import com.example.android.nfc.R;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An NFC Text Record
|
|
||||||
*/
|
|
||||||
public class TextRecord implements ParsedNdefRecord {
|
|
||||||
|
|
||||||
/** ISO/IANA language code */
|
|
||||||
private final String mLanguageCode;
|
|
||||||
|
|
||||||
private final String mText;
|
|
||||||
|
|
||||||
private TextRecord(String languageCode, String text) {
|
|
||||||
mLanguageCode = Preconditions.checkNotNull(languageCode);
|
|
||||||
mText = Preconditions.checkNotNull(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset) {
|
|
||||||
TextView text = (TextView) inflater.inflate(R.layout.tag_text, parent, false);
|
|
||||||
text.setText(mText);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
return mText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ISO/IANA language code associated with this text element.
|
|
||||||
*/
|
|
||||||
public String getLanguageCode() {
|
|
||||||
return mLanguageCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: deal with text fields which span multiple NdefRecords
|
|
||||||
public static TextRecord parse(NdefRecord record) {
|
|
||||||
Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN);
|
|
||||||
Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT));
|
|
||||||
try {
|
|
||||||
byte[] payload = record.getPayload();
|
|
||||||
/*
|
|
||||||
* payload[0] contains the "Status Byte Encodings" field, per the
|
|
||||||
* NFC Forum "Text Record Type Definition" section 3.2.1.
|
|
||||||
*
|
|
||||||
* bit7 is the Text Encoding Field.
|
|
||||||
*
|
|
||||||
* if (Bit_7 == 0): The text is encoded in UTF-8 if (Bit_7 == 1):
|
|
||||||
* The text is encoded in UTF16
|
|
||||||
*
|
|
||||||
* Bit_6 is reserved for future use and must be set to zero.
|
|
||||||
*
|
|
||||||
* Bits 5 to 0 are the length of the IANA language code.
|
|
||||||
*/
|
|
||||||
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
|
|
||||||
int languageCodeLength = payload[0] & 0077;
|
|
||||||
String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
|
|
||||||
String text =
|
|
||||||
new String(payload, languageCodeLength + 1,
|
|
||||||
payload.length - languageCodeLength - 1, textEncoding);
|
|
||||||
return new TextRecord(languageCode, text);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
// should never happen unless we get a malformed tag.
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isText(NdefRecord record) {
|
|
||||||
try {
|
|
||||||
parse(record);
|
|
||||||
return true;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,159 +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.example.android.nfc.record;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
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.example.android.nfc.R;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A parsed record containing a Uri.
|
|
||||||
*/
|
|
||||||
public class UriRecord implements ParsedNdefRecord {
|
|
||||||
|
|
||||||
private static final String TAG = "UriRecord";
|
|
||||||
|
|
||||||
public static final String RECORD_TYPE = "UriRecord";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
|
|
||||||
private final Uri mUri;
|
|
||||||
|
|
||||||
private UriRecord(Uri uri) {
|
|
||||||
this.mUri = Preconditions.checkNotNull(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset) {
|
|
||||||
TextView text = (TextView) inflater.inflate(R.layout.tag_text, parent, false);
|
|
||||||
text.setText(mUri.toString());
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri getUri() {
|
|
||||||
return mUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert {@link android.nfc.NdefRecord} into a {@link android.net.Uri}.
|
|
||||||
* This will handle both TNF_WELL_KNOWN / RTD_URI and TNF_ABSOLUTE_URI.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the NdefRecord is not a record
|
|
||||||
* containing a URI.
|
|
||||||
*/
|
|
||||||
public static UriRecord parse(NdefRecord record) {
|
|
||||||
short tnf = record.getTnf();
|
|
||||||
if (tnf == NdefRecord.TNF_WELL_KNOWN) {
|
|
||||||
return parseWellKnown(record);
|
|
||||||
} else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) {
|
|
||||||
return parseAbsolute(record);
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Unknown TNF " + tnf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse and absolute URI record */
|
|
||||||
private static UriRecord parseAbsolute(NdefRecord record) {
|
|
||||||
byte[] payload = record.getPayload();
|
|
||||||
Uri uri = Uri.parse(new String(payload, Charset.forName("UTF-8")));
|
|
||||||
return new UriRecord(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Parse an well known URI record */
|
|
||||||
private static UriRecord parseWellKnown(NdefRecord record) {
|
|
||||||
Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_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(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1,
|
|
||||||
payload.length));
|
|
||||||
Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8")));
|
|
||||||
return new UriRecord(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isUri(NdefRecord record) {
|
|
||||||
try {
|
|
||||||
parse(record);
|
|
||||||
return true;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final byte[] EMPTY = new byte[0];
|
|
||||||
}
|
|
||||||
@@ -1,108 +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.example.android.nfc.simulator;
|
|
||||||
|
|
||||||
import android.app.ListActivity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.nfc.NdefMessage;
|
|
||||||
import android.nfc.NdefRecord;
|
|
||||||
import android.nfc.NfcAdapter;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.primitives.Bytes;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A activity that launches tags as if they had been scanned.
|
|
||||||
*/
|
|
||||||
public class FakeTagsActivity extends ListActivity {
|
|
||||||
|
|
||||||
static final String TAG = "FakeTagsActivity";
|
|
||||||
|
|
||||||
static final byte[] UID = new byte[] {0x05, 0x00, 0x03, 0x08};
|
|
||||||
|
|
||||||
ArrayAdapter<TagDescription> mAdapter;
|
|
||||||
|
|
||||||
public static NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) {
|
|
||||||
Preconditions.checkNotNull(text);
|
|
||||||
Preconditions.checkNotNull(locale);
|
|
||||||
final byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);
|
|
||||||
final Charset utfEncoding = encodeInUtf8 ? Charsets.UTF_8 : Charset.forName("UTF-16");
|
|
||||||
final byte[] textBytes = text.getBytes(utfEncoding);
|
|
||||||
final int utfBit = encodeInUtf8 ? 0 : (1 << 7);
|
|
||||||
final char status = (char) (utfBit + langBytes.length);
|
|
||||||
final byte[] data = Bytes.concat(new byte[] {(byte) status}, langBytes, textBytes);
|
|
||||||
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NdefRecord newMimeRecord(String type, byte[] data) {
|
|
||||||
Preconditions.checkNotNull(type);
|
|
||||||
Preconditions.checkNotNull(data);
|
|
||||||
final byte[] typeBytes = type.getBytes(Charsets.US_ASCII);
|
|
||||||
return new NdefRecord(NdefRecord.TNF_MIME_MEDIA, typeBytes, new byte[0], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class TagDescription {
|
|
||||||
|
|
||||||
public String title;
|
|
||||||
|
|
||||||
public NdefMessage[] msgs;
|
|
||||||
|
|
||||||
public TagDescription(String title, byte[] bytes) {
|
|
||||||
this.title = title;
|
|
||||||
try {
|
|
||||||
msgs = new NdefMessage[] {new NdefMessage(bytes)};
|
|
||||||
} catch (final Exception e) {
|
|
||||||
throw new RuntimeException("Failed to create tag description", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedState) {
|
|
||||||
super.onCreate(savedState);
|
|
||||||
final ArrayAdapter<TagDescription> adapter = new ArrayAdapter<TagDescription>(
|
|
||||||
this, android.R.layout.simple_list_item_1, android.R.id.text1);
|
|
||||||
adapter.add(
|
|
||||||
new TagDescription("Broadcast NFC Text Tag", MockNdefMessages.ENGLISH_PLAIN_TEXT));
|
|
||||||
adapter.add(new TagDescription(
|
|
||||||
"Broadcast NFC SmartPoster URL & text", MockNdefMessages.SMART_POSTER_URL_AND_TEXT));
|
|
||||||
adapter.add(new TagDescription(
|
|
||||||
"Broadcast NFC SmartPoster URL", MockNdefMessages.SMART_POSTER_URL_NO_TEXT));
|
|
||||||
setListAdapter(adapter);
|
|
||||||
mAdapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
|
||||||
final TagDescription description = mAdapter.getItem(position);
|
|
||||||
final Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED);
|
|
||||||
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, description.msgs);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +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.example.android.nfc.simulator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class provides a list of fake NFC Ndef format Tags.
|
|
||||||
*/
|
|
||||||
public class MockNdefMessages {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Smart Poster containing a URL and no text.
|
|
||||||
*/
|
|
||||||
public static final byte[] SMART_POSTER_URL_NO_TEXT =
|
|
||||||
new byte[] {(byte) 0xd1, (byte) 0x02, (byte) 0x0f, (byte) 0x53, (byte) 0x70, (byte) 0xd1,
|
|
||||||
(byte) 0x01, (byte) 0x0b, (byte) 0x55, (byte) 0x01, (byte) 0x67, (byte) 0x6f,
|
|
||||||
(byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2e, (byte) 0x63,
|
|
||||||
(byte) 0x6f, (byte) 0x6d};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A plain text tag in english.
|
|
||||||
*/
|
|
||||||
public static final byte[] ENGLISH_PLAIN_TEXT =
|
|
||||||
new byte[] {(byte) 0xd1, (byte) 0x01, (byte) 0x1c, (byte) 0x54, (byte) 0x02, (byte) 0x65,
|
|
||||||
(byte) 0x6e, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x20,
|
|
||||||
(byte) 0x72, (byte) 0x61, (byte) 0x6e, (byte) 0x64, (byte) 0x6f, (byte) 0x6d,
|
|
||||||
(byte) 0x20, (byte) 0x65, (byte) 0x6e, (byte) 0x67, (byte) 0x6c, (byte) 0x69,
|
|
||||||
(byte) 0x73, (byte) 0x68, (byte) 0x20, (byte) 0x74, (byte) 0x65, (byte) 0x78,
|
|
||||||
(byte) 0x74, (byte) 0x2e};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Smart Poster containing a URL and Text.
|
|
||||||
*/
|
|
||||||
public static final byte[] SMART_POSTER_URL_AND_TEXT =
|
|
||||||
new byte[] {(byte) 0xd1, (byte) 0x02, (byte) 0x1c, (byte) 0x53, (byte) 0x70, (byte) 0x91,
|
|
||||||
(byte) 0x01, (byte) 0x09, (byte) 0x54, (byte) 0x02, (byte) 0x65, (byte) 0x6e,
|
|
||||||
(byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65,
|
|
||||||
(byte) 0x51, (byte) 0x01, (byte) 0x0b, (byte) 0x55, (byte) 0x01, (byte) 0x67,
|
|
||||||
(byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
|
|
||||||
(byte) 0x63, (byte) 0x6f, (byte) 0x6d};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All the mock Ndef tags.
|
|
||||||
*/
|
|
||||||
public static final byte[][] ALL_MOCK_MESSAGES =
|
|
||||||
new byte[][] {SMART_POSTER_URL_NO_TEXT, ENGLISH_PLAIN_TEXT, SMART_POSTER_URL_AND_TEXT};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user