Home | History | Annotate | Download | only in beam
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.beam;
     18 
     19 import android.app.Activity;
     20 import android.content.Intent;
     21 import android.nfc.NdefMessage;
     22 import android.nfc.NdefRecord;
     23 import android.nfc.NfcAdapter;
     24 import android.nfc.NfcAdapter.CreateNdefMessageCallback;
     25 import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
     26 import android.nfc.NfcEvent;
     27 import android.os.Bundle;
     28 import android.os.Handler;
     29 import android.os.Message;
     30 import android.os.Parcelable;
     31 import android.provider.Settings;
     32 import android.text.format.Time;
     33 import android.view.Menu;
     34 import android.view.MenuInflater;
     35 import android.view.MenuItem;
     36 import android.widget.TextView;
     37 import android.widget.Toast;
     38 
     39 import java.nio.charset.Charset;
     40 
     41 
     42 public class Beam extends Activity implements CreateNdefMessageCallback,
     43         OnNdefPushCompleteCallback {
     44     NfcAdapter mNfcAdapter;
     45     TextView mInfoText;
     46     private static final int MESSAGE_SENT = 1;
     47 
     48     @Override
     49     public void onCreate(Bundle savedInstanceState) {
     50         super.onCreate(savedInstanceState);
     51         setContentView(R.layout.main);
     52 
     53         mInfoText = (TextView) findViewById(R.id.textView);
     54         // Check for available NFC Adapter
     55         mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
     56         if (mNfcAdapter == null) {
     57             mInfoText = (TextView) findViewById(R.id.textView);
     58             mInfoText.setText("NFC is not available on this device.");
     59         }
     60         // Register callback to set NDEF message
     61         mNfcAdapter.setNdefPushMessageCallback(this, this);
     62         // Register callback to listen for message-sent success
     63         mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
     64     }
     65 
     66 
     67     /**
     68      * Implementation for the CreateNdefMessageCallback interface
     69      */
     70     @Override
     71     public NdefMessage createNdefMessage(NfcEvent event) {
     72         Time time = new Time();
     73         time.setToNow();
     74         String text = ("Beam me up!\n\n" +
     75                 "Beam Time: " + time.format("%H:%M:%S"));
     76         NdefMessage msg = new NdefMessage(
     77                 new NdefRecord[] { createMimeRecord(
     78                         "application/com.example.android.beam", text.getBytes())
     79          /**
     80           * The Android Application Record (AAR) is commented out. When a device
     81           * receives a push with an AAR in it, the application specified in the AAR
     82           * is guaranteed to run. The AAR overrides the tag dispatch system.
     83           * You can add it back in to guarantee that this
     84           * activity starts when receiving a beamed message. For now, this code
     85           * uses the tag dispatch system.
     86           */
     87           //,NdefRecord.createApplicationRecord("com.example.android.beam")
     88         });
     89         return msg;
     90     }
     91 
     92     /**
     93      * Implementation for the OnNdefPushCompleteCallback interface
     94      */
     95     @Override
     96     public void onNdefPushComplete(NfcEvent arg0) {
     97         // A handler is needed to send messages to the activity when this
     98         // callback occurs, because it happens from a binder thread
     99         mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();
    100     }
    101 
    102     /** This handler receives a message from onNdefPushComplete */
    103     private final Handler mHandler = new Handler() {
    104         @Override
    105         public void handleMessage(Message msg) {
    106             switch (msg.what) {
    107             case MESSAGE_SENT:
    108                 Toast.makeText(getApplicationContext(), "Message sent!", Toast.LENGTH_LONG).show();
    109                 break;
    110             }
    111         }
    112     };
    113 
    114     @Override
    115     public void onResume() {
    116         super.onResume();
    117         // Check to see that the Activity started due to an Android Beam
    118         if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
    119             processIntent(getIntent());
    120         }
    121     }
    122 
    123     @Override
    124     public void onNewIntent(Intent intent) {
    125         // onResume gets called after this to handle the intent
    126         setIntent(intent);
    127     }
    128 
    129     /**
    130      * Parses the NDEF Message from the intent and prints to the TextView
    131      */
    132     void processIntent(Intent intent) {
    133         Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
    134                 NfcAdapter.EXTRA_NDEF_MESSAGES);
    135         // only one message sent during the beam
    136         NdefMessage msg = (NdefMessage) rawMsgs[0];
    137         // record 0 contains the MIME type, record 1 is the AAR, if present
    138         mInfoText.setText(new String(msg.getRecords()[0].getPayload()));
    139     }
    140 
    141     /**
    142      * Creates a custom MIME type encapsulated in an NDEF record
    143      *
    144      * @param mimeType
    145      */
    146     public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
    147         byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
    148         NdefRecord mimeRecord = new NdefRecord(
    149                 NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
    150         return mimeRecord;
    151     }
    152 
    153     @Override
    154     public boolean onCreateOptionsMenu(Menu menu) {
    155         // If NFC is not available, we won't be needing this menu
    156         if (mNfcAdapter == null) {
    157             return super.onCreateOptionsMenu(menu);
    158         }
    159         MenuInflater inflater = getMenuInflater();
    160         inflater.inflate(R.menu.options, menu);
    161         return true;
    162     }
    163 
    164     @Override
    165     public boolean onOptionsItemSelected(MenuItem item) {
    166         switch (item.getItemId()) {
    167             case R.id.menu_settings:
    168                 Intent intent = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
    169                 startActivity(intent);
    170                 return true;
    171             default:
    172                 return super.onOptionsItemSelected(item);
    173         }
    174     }
    175 }
    176