18bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen/* 28bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * Copyright (C) 2011 The Android Open Source Project 38bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * 48bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 58bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * you may not use this file except in compliance with the License. 68bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * You may obtain a copy of the License at 78bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * 88bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 98bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * 108bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * Unless required by applicable law or agreed to in writing, software 118bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 128bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * See the License for the specific language governing permissions and 148bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen * limitations under the License. 158bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen */ 168bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 178bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenpackage com.android.contacts; 188bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 198bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.app.Activity; 208bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.content.ContentResolver; 218bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.net.Uri; 228bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.nfc.NdefMessage; 238bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.nfc.NdefRecord; 248bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.nfc.NfcAdapter; 25a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pellyimport android.nfc.NfcEvent; 268bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.provider.ContactsContract.Contacts; 2792165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenenimport android.provider.ContactsContract.Profile; 288bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport android.util.Log; 298bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 30e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailFragment; 31e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 328bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport java.io.ByteArrayOutputStream; 338bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport java.io.IOException; 348bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenenimport java.io.InputStream; 358bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 36194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen/** 37194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * This class implements sharing the currently displayed 38194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * contact to another device using NFC. NFC sharing is only 39194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * enabled when the activity is in the foreground and resumed. 40194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * When an NFC link is established, {@link #createMessage} 41194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * will be called to create the data to be sent over the link, 42194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen * which is a vCard in this case. 43194cdd3b71e3fdb1a77a4fa5435a6b6319407e91Martijn Coenen */ 44a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pellypublic class NfcHandler implements NfcAdapter.CreateNdefMessageCallback { 458bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 4692165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen private static final String TAG = "ContactNfcHandler"; 4792165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen private static final String PROFILE_LOOKUP_KEY = "profile"; 4892165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen private final ContactDetailFragment mContactFragment; 49a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly 50a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly public static void register(Activity activity, ContactDetailFragment contactFragment) { 51a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly NfcAdapter adapter = NfcAdapter.getDefaultAdapter(activity.getApplicationContext()); 52a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly if (adapter == null) { 53a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly return; // NFC not available on this device 548bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 55a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly adapter.setNdefPushMessageCallback(new NfcHandler(contactFragment), activity); 568bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 578bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 58a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly public NfcHandler(ContactDetailFragment contactFragment) { 59a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly mContactFragment = contactFragment; 608bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 618bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 628bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen @Override 63a3364bc45b73c6a3bb0e0ec4586110f962ddf8c2Nick Pelly public NdefMessage createNdefMessage(NfcEvent event) { 648bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen // Get the current contact URI 658bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen Uri contactUri = mContactFragment.getUri(); 668bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen ContentResolver resolver = mContactFragment.getActivity().getContentResolver(); 678bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen if (contactUri != null) { 688bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen final String lookupKey = Uri.encode(contactUri.getPathSegments().get(2)); 6992165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen final Uri shareUri; 7092165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen // TODO find out where to get this constant from, or find another way 7192165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen // of determining this. 7292165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen if (lookupKey.equals(PROFILE_LOOKUP_KEY)) { 7392165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen shareUri = Profile.CONTENT_VCARD_URI.buildUpon(). 7492165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true"). 7592165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen build(); 7692165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen } else { 7792165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen shareUri = Contacts.CONTENT_VCARD_URI.buildUpon(). 7892165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen appendPath(lookupKey). 7992165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true"). 8092165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen build(); 8192165c6938a6d62205c97ec8f7195117362a8d62Martijn Coenen } 828bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen ByteArrayOutputStream ndefBytes = new ByteArrayOutputStream(); 838bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen byte[] buffer = new byte[1024]; 848bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen int r; 858bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen try { 868bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen InputStream vcardInputStream = resolver.openInputStream(shareUri); 878bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen while ((r = vcardInputStream.read(buffer)) > 0) { 888bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen ndefBytes.write(buffer, 0, r); 898bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 908bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen 91cd564c953280182b64b2391c49e36a8c858f1e0dNick Pelly NdefRecord record = NdefRecord.createMime("text/x-vcard", ndefBytes.toByteArray()); 92cd564c953280182b64b2391c49e36a8c858f1e0dNick Pelly return new NdefMessage(record); 938bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } catch (IOException e) { 948bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen Log.e(TAG, "IOException creating vcard."); 958bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen return null; 968bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 978bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } else { 988bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen Log.w(TAG, "No contact URI to share."); 998bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen return null; 1008bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 1018bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen } 1028bd4065141c64a4ab249aec46e5f32d25a862f64Martijn Coenen} 103