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
onCreate(Bundle savedInstanceState)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         } else {
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     /**
69      * Implementation for the CreateNdefMessageCallback interface
70      */
71     @Override
createNdefMessage(NfcEvent event)72     public NdefMessage createNdefMessage(NfcEvent event) {
73         Time time = new Time();
74         time.setToNow();
75         String text = ("Beam me up!\n\n" +
76                 "Beam Time: " + time.format("%H:%M:%S"));
77         NdefMessage msg = new NdefMessage(NdefRecord.createMime(
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
onNdefPushComplete(NfcEvent arg0)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
onResume()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
onNewIntent(Intent intent)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      */
processIntent(Intent intent)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     @Override
onCreateOptionsMenu(Menu menu)142     public boolean onCreateOptionsMenu(Menu menu) {
143         // If NFC is not available, we won't be needing this menu
144         if (mNfcAdapter == null) {
145             return super.onCreateOptionsMenu(menu);
146         }
147         MenuInflater inflater = getMenuInflater();
148         inflater.inflate(R.menu.options, menu);
149         return true;
150     }
151 
152     @Override
onOptionsItemSelected(MenuItem item)153     public boolean onOptionsItemSelected(MenuItem item) {
154         switch (item.getItemId()) {
155             case R.id.menu_settings:
156                 Intent intent = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
157                 startActivity(intent);
158                 return true;
159             default:
160                 return super.onOptionsItemSelected(item);
161         }
162     }
163 }
164