Java tutorial
/* * Copyright (C) 2010 The Android Open Source Project * Copyright (C) 2011 Adam Nybck * * 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 se.anyro.nfc_reader; import java.io.BufferedInputStream; import java.io.BufferedWriter; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.Charset; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import android.net.Uri; import android.util.Log; import android.util.Pair; import android.view.*; import se.anyro.nfc_reader.record.ParsedNdefRecord; import android.app.Activity; import android.app.AlertDialog; import android.app.PendingIntent; import android.content.DialogInterface; import android.content.Intent; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.MifareClassic; import android.nfc.tech.MifareUltralight; import android.os.Bundle; import android.os.Parcelable; import android.provider.Settings; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import org.json.JSONObject; /** * An {@link Activity} which handles a broadcast of a new tag that the device just discovered. */ public class TagViewer extends Activity { private static final DateFormat TIME_FORMAT = SimpleDateFormat.getDateTimeInstance(); private LinearLayout mTagContent; private NfcAdapter mAdapter; private PendingIntent mPendingIntent; private NdefMessage mNdefPushMessage; private AlertDialog mDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tag_viewer); mTagContent = (LinearLayout) findViewById(R.id.list); resolveIntent(getIntent()); mDialog = new AlertDialog.Builder(this).setNeutralButton("Ok", null).create(); mAdapter = NfcAdapter.getDefaultAdapter(this); if (mAdapter == null) { showMessage(R.string.error, R.string.no_nfc); finish(); return; } mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); mNdefPushMessage = new NdefMessage( new NdefRecord[] { newTextRecord("Message from NFC Reader :-)", Locale.ENGLISH, true) }); } private void showMessage(int title, int message) { mDialog.setTitle(title); mDialog.setMessage(getText(message)); mDialog.show(); } private 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 protected void onResume() { super.onResume(); if (mAdapter != null) { if (!mAdapter.isEnabled()) { showWirelessSettingsDialog(); } mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); mAdapter.enableForegroundNdefPush(this, mNdefPushMessage); } } @Override protected void onPause() { super.onPause(); if (mAdapter != null) { mAdapter.disableForegroundDispatch(this); mAdapter.disableForegroundNdefPush(this); } } private void showWirelessSettingsDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.nfc_disabled); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS); startActivity(intent); } }); builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { finish(); } }); builder.create().show(); return; } private void resolveIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { 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]; // magic happens here processReadTag((NdefMessage) rawMsgs[i]); } } else { // Unknown tag type byte[] empty = new byte[0]; byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); Parcelable tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); byte[] payload = dumpTagData(tag).getBytes(); NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, id, payload); NdefMessage msg = new NdefMessage(new NdefRecord[] { record }); msgs = new NdefMessage[] { msg }; } // Setup the views buildTagViews(msgs); } } private String dumpTagData(Parcelable p) { StringBuilder sb = new StringBuilder(); Tag tag = (Tag) p; byte[] id = tag.getId(); sb.append("Tag ID (hex): ").append(getHex(id)).append("\n"); sb.append("Tag ID (dec): ").append(getDec(id)).append("\n"); sb.append("ID (reversed): ").append(getReversed(id)).append("\n"); String prefix = "android.nfc.tech."; sb.append("Technologies: "); for (String tech : tag.getTechList()) { sb.append(tech.substring(prefix.length())); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); for (String tech : tag.getTechList()) { if (tech.equals(MifareClassic.class.getName())) { sb.append('\n'); MifareClassic mifareTag = MifareClassic.get(tag); String type = "Unknown"; switch (mifareTag.getType()) { case MifareClassic.TYPE_CLASSIC: type = "Classic"; break; case MifareClassic.TYPE_PLUS: type = "Plus"; break; case MifareClassic.TYPE_PRO: type = "Pro"; break; } sb.append("Mifare Classic type: "); sb.append(type); sb.append('\n'); sb.append("Mifare size: "); sb.append(mifareTag.getSize() + " bytes"); sb.append('\n'); sb.append("Mifare sectors: "); sb.append(mifareTag.getSectorCount()); sb.append('\n'); sb.append("Mifare blocks: "); sb.append(mifareTag.getBlockCount()); } if (tech.equals(MifareUltralight.class.getName())) { sb.append('\n'); MifareUltralight mifareUlTag = MifareUltralight.get(tag); String type = "Unknown"; switch (mifareUlTag.getType()) { case MifareUltralight.TYPE_ULTRALIGHT: type = "Ultralight"; break; case MifareUltralight.TYPE_ULTRALIGHT_C: type = "Ultralight C"; break; } sb.append("Mifare Ultralight type: "); sb.append(type); } } return sb.toString(); } private String getHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (int i = bytes.length - 1; i >= 0; --i) { int b = bytes[i] & 0xff; if (b < 0x10) sb.append('0'); sb.append(Integer.toHexString(b)); if (i > 0) { sb.append(" "); } } return sb.toString(); } private long getDec(byte[] bytes) { long result = 0; long factor = 1; for (int i = 0; i < bytes.length; ++i) { long value = bytes[i] & 0xffl; result += value * factor; factor *= 256l; } return result; } private long getReversed(byte[] bytes) { long result = 0; long factor = 1; for (int i = bytes.length - 1; i >= 0; --i) { long value = bytes[i] & 0xffl; result += value * factor; factor *= 256l; } return result; } void buildTagViews(NdefMessage[] msgs) { if (msgs == null || msgs.length == 0) { return; } LayoutInflater inflater = LayoutInflater.from(this); LinearLayout content = mTagContent; // Parse the first message in the list // Build views for all of the sub records Date now = new Date(); List<ParsedNdefRecord> records = NdefMessageParser.parse(msgs[0]); final int size = records.size(); for (int i = 0; i < size; i++) { TextView timeView = new TextView(this); timeView.setText(TIME_FORMAT.format(now)); content.addView(timeView, 0); ParsedNdefRecord record = records.get(i); content.addView(record.getView(this, inflater, content, i), 1 + i); content.addView(inflater.inflate(R.layout.tag_divider, content, false), 2 + i); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.menu_main_clear: menuMainClearClick(); default: return super.onOptionsItemSelected(item); } } private void menuMainClearClick() { for (int i = mTagContent.getChildCount() - 1; i >= 0; i--) { View view = mTagContent.getChildAt(i); if (view.getId() != R.id.tag_viewer_text) { mTagContent.removeViewAt(i); } } } @Override public void onNewIntent(Intent intent) { setIntent(intent); resolveIntent(intent); } // magic happens here public void processReadTag(NdefMessage ndef) { final String tag_content = new String(ndef.getRecords()[0].getPayload()); //setContentView(R.layout.tag_viewer); //? EditText twitterHandleEditText = (EditText) findViewById(R.id.txtTwitterHandle); final String twitter_handle = twitterHandleEditText.getText().toString(); Log.i(">>> NDEF:", tag_content); Log.i(">>> TWITTER:", twitter_handle); // THIS DOESN'T GET PRINTED?! // this doesn't seem like the proper way to do this #yolo Thread thread = new Thread(new Runnable() { @Override public void run() { try { // build request URL url = new URL("http://10.2.2.147:8666/"); //URL url = new URL("http://httpbin.org/post"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-type", "application/json"); conn.setDoInput(true); conn.setDoOutput(true); /* // create POST body and send it over Uri.Builder builder = new Uri.Builder() .appendQueryParameter("ndef", tag_content) .appendQueryParameter("twitter_handle", "omerk"); String query = builder.build().getEncodedQuery(); */ OutputStream os = conn.getOutputStream(); //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); JSONObject json = new JSONObject(); json.put("ndef", tag_content); json.put("twitter", twitter_handle); os.write(json.toString().getBytes("UTF-8")); os.flush(); os.close(); conn.connect(); // read the response Log.i(">>> ResponseCode: ", "" + conn.getResponseCode()); InputStream in = new BufferedInputStream(conn.getInputStream()); java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A"); String r = s.hasNext() ? s.next() : ""; Log.i(">>> ResponseBody: ", r); } catch (Exception e) { Log.i(">>> OOPS: ", e.toString()); } } }); thread.start(); } }