NFCSyncActivity.java 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. package de.tudarmstadt.informatik.hostage.sync.nfc;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.IOException;
  20. import java.io.ObjectInputStream;
  21. import java.io.ObjectOutputStream;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import android.annotation.TargetApi;
  26. import android.app.Activity;
  27. import android.app.PendingIntent;
  28. import android.content.Intent;
  29. import android.content.IntentFilter;
  30. import android.nfc.NdefMessage;
  31. import android.nfc.NdefRecord;
  32. import android.nfc.NfcAdapter;
  33. import android.nfc.NfcAdapter.CreateNdefMessageCallback;
  34. import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
  35. import android.nfc.NfcEvent;
  36. import android.nfc.tech.NfcF;
  37. import android.os.Build;
  38. import android.os.Bundle;
  39. import android.os.Handler;
  40. import android.os.Message;
  41. import android.os.Parcelable;
  42. import android.util.Log;
  43. import android.widget.TextView;
  44. import android.widget.Toast;
  45. import de.tudarmstadt.informatik.hostage.R;
  46. import de.tudarmstadt.informatik.hostage.logging.NetworkRecord;
  47. import de.tudarmstadt.informatik.hostage.logging.SyncInfoRecord;
  48. import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper;
  49. import de.tudarmstadt.informatik.hostage.sync.tracing.TracingSyncService;
  50. @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  51. public class NFCSyncActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback {
  52. NfcAdapter mNfcAdapter;
  53. TextView mInfoText;
  54. private static final int MESSAGE_SENT = 0x1;
  55. private static final int MESSAGE_RECEIVED = 0x3;
  56. private final Handler mHandler = new Handler() {
  57. @Override
  58. public void handleMessage(Message msg) {
  59. switch (msg.what) {
  60. case MESSAGE_SENT:
  61. runOnUiThread(new Runnable() {
  62. public void run() {
  63. Toast.makeText(NFCSyncActivity.this, "Data sent!", Toast.LENGTH_LONG).show();
  64. }
  65. });
  66. break;
  67. case MESSAGE_RECEIVED:
  68. runOnUiThread(new Runnable() {
  69. public void run() {
  70. Toast.makeText(NFCSyncActivity.this, "Data recieved!", Toast.LENGTH_LONG).show();
  71. }
  72. });
  73. break;
  74. }
  75. }
  76. };
  77. @Override
  78. public void onCreate(Bundle savedInstanceState) {
  79. super.onCreate(savedInstanceState);
  80. setContentView(R.layout.activity_nfc);
  81. mInfoText = (TextView) findViewById(R.id.nfc_text_view);
  82. // Check for available NFC Adapter
  83. mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
  84. if (mNfcAdapter == null) {
  85. mInfoText.setText("NFC is not available on this device.");
  86. } else if(!mNfcAdapter.isEnabled()){
  87. mInfoText.setText("Enable Android Beam before synchronizing.");
  88. } else {
  89. mInfoText.setText("Hold phones together to send or recieve data.");
  90. // Register callback to set NDEF message
  91. mNfcAdapter.setNdefPushMessageCallback(this, this);
  92. // Register callback to listen for message-sent success
  93. mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
  94. }
  95. }
  96. /**
  97. * Implementation for the CreateNdefMessageCallback interface
  98. */
  99. @Override
  100. public NdefMessage createNdefMessage(NfcEvent event) {
  101. // Get Networkdata
  102. HostageDBOpenHelper dbh = new HostageDBOpenHelper(this);
  103. ArrayList<NetworkRecord> localNetworkInformation = dbh.getNetworkInformation();
  104. HashMap<String, Long> devices_local = dbh.getSyncDevices();
  105. ArrayList<SyncInfoRecord> syncInfo = dbh.getSyncInfo();
  106. NdefMessage msg = null;
  107. try {
  108. NdefRecord netData = NdefRecord.createMime("application/de.tudarmstadt.informatik.hostage", serialize(localNetworkInformation));
  109. NdefRecord deviceData = NdefRecord.createMime("application/de.tudarmstadt.informatik.hostage", serialize(devices_local));
  110. NdefRecord syncData = NdefRecord.createMime("application/de.tudarmstadt.informatik.hostage", serialize(syncInfo));
  111. msg = new NdefMessage(netData, deviceData, syncData);
  112. } catch (IOException e) {
  113. e.printStackTrace();
  114. }
  115. return msg;
  116. }
  117. /**
  118. * Implementation for the OnNdefPushCompleteCallback interface
  119. */
  120. @Override
  121. public void onNdefPushComplete(NfcEvent arg0) {
  122. // A handler is needed to send messages to the activity when this
  123. // callback occurs, because it happens from a binder thread
  124. mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();
  125. }
  126. @Override
  127. public void onNewIntent(Intent intent) {
  128. // onResume gets called after this to handle the intent
  129. setIntent(intent);
  130. }
  131. // HELPER
  132. @Override
  133. public void onResume() {
  134. super.onResume();
  135. IntentFilter[] mIntentFilters = null;
  136. PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0,
  137. new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
  138. // set an intent filter for all MIME data
  139. IntentFilter ndefIntent = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
  140. try {
  141. ndefIntent.addDataType("*/*");
  142. mIntentFilters = new IntentFilter[] { ndefIntent };
  143. } catch (Exception e) {
  144. Log.e("TagDispatch", e.toString());
  145. }
  146. String[][] mNFCTechLists = new String[][] { new String[] { NfcF.class.getName() } };
  147. if (mNfcAdapter != null)
  148. mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilters, mNFCTechLists);
  149. // Check to see that the Activity started due to an Android Beam
  150. if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
  151. processIntent(getIntent());
  152. }
  153. }
  154. @Override
  155. public void onPause() {
  156. super.onPause();
  157. if (mNfcAdapter != null)
  158. mNfcAdapter.disableForegroundDispatch(this);
  159. }
  160. /**
  161. * Parses the NDEF Message from the intent and prints to the TextView
  162. */
  163. void processIntent(Intent intent) {
  164. Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
  165. // only one message sent during the beam
  166. NdefMessage msg = (NdefMessage) rawMsgs[0];
  167. try {
  168. HostageDBOpenHelper dbh = new HostageDBOpenHelper(this);
  169. ArrayList<NetworkRecord> remoteNetworkInformation = (ArrayList<NetworkRecord>) deserialize(msg.getRecords()[0].getPayload());
  170. HashMap<String, Long> devices_remote = (HashMap<String, Long>) deserialize(msg.getRecords()[1].getPayload());
  171. HashMap<String, Long> devices_local = dbh.getSyncDevices();
  172. ArrayList<SyncInfoRecord> syncInfo = (ArrayList<SyncInfoRecord>) deserialize(msg.getRecords()[2].getPayload());
  173. long tracing_timestamp = 0;
  174. if(devices_local.containsKey(TracingSyncService.REMOTE_DEVICE))
  175. tracing_timestamp = devices_local.get(TracingSyncService.REMOTE_DEVICE);
  176. for(Iterator<String> i = devices_remote.keySet().iterator(); i.hasNext(); ){
  177. String key = i.next();
  178. if((devices_local.containsKey(key) && devices_local.get(key) >= devices_remote.get(key))
  179. || (tracing_timestamp > devices_remote.get(key))){
  180. i.remove();
  181. }
  182. }
  183. for ( Iterator<SyncInfoRecord> i = syncInfo.iterator(); i.hasNext(); ){
  184. SyncInfoRecord info = i.next();
  185. if(!devices_remote.containsKey(info.getDeviceID())){
  186. i.remove();
  187. }
  188. }
  189. dbh.updateSyncDevices(devices_remote);
  190. dbh.updateSyncInfo(syncInfo);
  191. dbh.updateNetworkInformation(remoteNetworkInformation);
  192. mHandler.obtainMessage(MESSAGE_RECEIVED).sendToTarget();
  193. } catch (ClassNotFoundException e) {
  194. e.printStackTrace();
  195. } catch (IOException e) {
  196. e.printStackTrace();
  197. }
  198. }
  199. private static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
  200. ByteArrayInputStream in = new ByteArrayInputStream(data);
  201. ObjectInputStream is = new ObjectInputStream(in);
  202. return is.readObject();
  203. }
  204. private static byte[] serialize(Object obj) throws IOException {
  205. ByteArrayOutputStream out = new ByteArrayOutputStream();
  206. ObjectOutputStream os = new ObjectOutputStream(out);
  207. os.writeObject(obj);
  208. return out.toByteArray();
  209. }
  210. }