1631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo/* 2631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Copyright (C) 2016 The Android Open Source Project 3631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 4631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Licensed under the Apache License, Version 2.0 (the "License"); 5631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * you may not use this file except in compliance with the License. 6631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * You may obtain a copy of the License at 7631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 8631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * http://www.apache.org/licenses/LICENSE-2.0 9631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 10631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Unless required by applicable law or agreed to in writing, software 11631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * distributed under the License is distributed on an "AS IS" BASIS, 12631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * See the License for the specific language governing permissions and 14631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * limitations under the License. 15631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 16631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 17631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzopackage android.bluetooth; 18631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 19631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.app.PendingIntent; 20631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.content.ComponentName; 21631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.content.Context; 22631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.content.Intent; 23631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.content.ServiceConnection; 24631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.net.Uri; 25631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.os.IBinder; 26631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.os.RemoteException; 27631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport android.util.Log; 28631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 29631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport java.util.ArrayList; 30631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzoimport java.util.List; 31631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 32631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo/** 33631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * This class provides the APIs to control the Bluetooth MAP MCE Profile. 34631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 35631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @hide 36631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 37631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzopublic final class BluetoothMapClient implements BluetoothProfile { 38631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 39631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private static final String TAG = "BluetoothMapClient"; 40631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 41631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); 42631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 43631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final String ACTION_CONNECTION_STATE_CHANGED = 44631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED"; 45631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final String ACTION_MESSAGE_RECEIVED = 46631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED"; 47631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /* Actions to be used for pending intents */ 48631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY = 49631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY"; 50631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY = 51631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY"; 52631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 5386a8c1cabb7de0b7c5868fad8edb7d0df176d4e1Srinivas Visvanathan /* Extras used in ACTION_MESSAGE_RECEIVED intent. 5486a8c1cabb7de0b7c5868fad8edb7d0df176d4e1Srinivas Visvanathan * NOTE: HANDLE is only valid for a single session with the device. */ 5586a8c1cabb7de0b7c5868fad8edb7d0df176d4e1Srinivas Visvanathan public static final String EXTRA_MESSAGE_HANDLE = 5686a8c1cabb7de0b7c5868fad8edb7d0df176d4e1Srinivas Visvanathan "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE"; 57ad90338d2b26044a2606897e4444a99ac3e49eceSrinivas Visvanathan public static final String EXTRA_SENDER_CONTACT_URI = 58ad90338d2b26044a2606897e4444a99ac3e49eceSrinivas Visvanathan "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI"; 59ad90338d2b26044a2606897e4444a99ac3e49eceSrinivas Visvanathan public static final String EXTRA_SENDER_CONTACT_NAME = 60ad90338d2b26044a2606897e4444a99ac3e49eceSrinivas Visvanathan "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME"; 61ad90338d2b26044a2606897e4444a99ac3e49eceSrinivas Visvanathan 62631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private IBluetoothMapClient mService; 63631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private final Context mContext; 64631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private ServiceListener mServiceListener; 65631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private BluetoothAdapter mAdapter; 66631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 67631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** There was an error trying to obtain the state */ 68631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final int STATE_ERROR = -1; 69631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 70631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final int RESULT_FAILURE = 0; 71631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final int RESULT_SUCCESS = 1; 72631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** Connection canceled before completion. */ 73631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public static final int RESULT_CANCELED = 2; 74631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 75631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 76631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo new IBluetoothStateChangeCallback.Stub() { 77631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public void onBluetoothStateChange(boolean up) { 78631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); 79631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (!up) { 80631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (VDBG) Log.d(TAG, "Unbinding service..."); 81631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo synchronized (mConnection) { 82631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 83631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mService = null; 84631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mContext.unbindService(mConnection); 85631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (Exception re) { 86631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "", re); 87631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 88631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 89631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } else { 90631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo synchronized (mConnection) { 91631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 92631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) { 93631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (VDBG) Log.d(TAG, "Binding service..."); 94631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo doBind(); 95631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 96631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (Exception re) { 97631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "", re); 98631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 99631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 100631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 101631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 102631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo }; 103631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 104631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 105631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Create a BluetoothMapClient proxy object. 106631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 107631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /*package*/ BluetoothMapClient(Context context, ServiceListener l) { 108631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object"); 109631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mContext = context; 110631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mServiceListener = l; 111631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mAdapter = BluetoothAdapter.getDefaultAdapter(); 112631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo IBluetoothManager mgr = mAdapter.getBluetoothManager(); 113631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mgr != null) { 114631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 115631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 116631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 117631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "", e); 118631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 119631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 120631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo doBind(); 121631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 122631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 123631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo boolean doBind() { 124631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Intent intent = new Intent(IBluetoothMapClient.class.getName()); 125631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 126631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo intent.setComponent(comp); 127631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, 128631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo android.os.Process.myUserHandle())) { 129631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent); 130631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 131631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 132631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return true; 133631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 134631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 135631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo protected void finalize() throws Throwable { 136631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 137631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo close(); 138631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } finally { 139631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo super.finalize(); 140631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 141631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 142631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 143631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 144631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Close the connection to the backing service. 145631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Other public functions of BluetoothMap will return default error 146631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * results once close() has been called. Multiple invocations of close() 147631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * are ok. 148631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 149631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public void close() { 150631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo IBluetoothManager mgr = mAdapter.getBluetoothManager(); 151631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mgr != null) { 152631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 153631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 154631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (Exception e) { 155631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "", e); 156631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 157631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 158631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 159631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo synchronized (mConnection) { 160631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null) { 161631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 162631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mService = null; 163631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mContext.unbindService(mConnection); 164631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (Exception re) { 165631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, "", re); 166631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 167631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 168631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 169631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mServiceListener = null; 170631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 171631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 172631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 173631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Returns true if the specified Bluetooth device is connected. 174631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Returns false if not connected, or if this proxy object is not 175631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * currently connected to the Map service. 176631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 177631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean isConnected(BluetoothDevice device) { 178631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (VDBG) Log.d(TAG, "isConnected(" + device + ")"); 179631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null) { 180631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 181631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.isConnected(device); 182631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 183631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, e.toString()); 184631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 185631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } else { 186631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 187631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 188631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 189631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 190631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 191631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 192631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 193631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Initiate connection. Initiation of outgoing connections is not 194631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * supported for MAP server. 195631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 196631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean connect(BluetoothDevice device) { 197631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE"); 198631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null) { 199631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 200631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.connect(device); 201631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 202631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, e.toString()); 203631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 204631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } else { 205631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.w(TAG, "Proxy not attached to service"); 206631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 207631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 208631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 209631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 210631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 211631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 212631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Initiate disconnect. 213631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 214631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param device Remote Bluetooth Device 215631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return false on error, true otherwise 216631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 217631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean disconnect(BluetoothDevice device) { 218631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "disconnect(" + device + ")"); 219631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && 220631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo isValidDevice(device)) { 221631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 222631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.disconnect(device); 223631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 224631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 225631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 226631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 227631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 228631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 229631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 230631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 231631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 232631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Get the list of connected devices. Currently at most one. 233631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 234631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return list of connected devices 235631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 236631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo @Override 237631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public List<BluetoothDevice> getConnectedDevices() { 238631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "getConnectedDevices()"); 239631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled()) { 240631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 241631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.getConnectedDevices(); 242631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 243631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 244631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return new ArrayList<>(); 245631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 246631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 247631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 248631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return new ArrayList<>(); 249631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 250631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 251631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 252631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Get the list of devices matching specified states. Currently at most one. 253631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 254631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return list of matching devices 255631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 256631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo @Override 257631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 258631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "getDevicesMatchingStates()"); 259631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled()) { 260631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 261631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.getDevicesMatchingConnectionStates(states); 262631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 263631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 264631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return new ArrayList<>(); 265631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 266631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 267631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 268631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return new ArrayList<>(); 269631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 270631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 271631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 272631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Get connection state of device 273631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 274631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return device connection state 275631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 276631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo @Override 277631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public int getConnectionState(BluetoothDevice device) { 278631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "getConnectionState(" + device + ")"); 279631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && 280631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo isValidDevice(device)) { 281631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 282631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.getConnectionState(device); 283631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 284631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 285631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return BluetoothProfile.STATE_DISCONNECTED; 286631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 287631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 288631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 289631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return BluetoothProfile.STATE_DISCONNECTED; 290631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 291631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 292631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 293631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Set priority of the profile 294631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 295631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * <p> The device should already be paired. Priority can be one of {@link #PRIORITY_ON} or 296631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * {@link #PRIORITY_OFF}, 297631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 298631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param device Paired bluetooth device 299631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return true if priority is set, false on error 300631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 301631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean setPriority(BluetoothDevice device, int priority) { 302631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")"); 303631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && 304631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo isValidDevice(device)) { 305631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (priority != BluetoothProfile.PRIORITY_OFF && 306631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo priority != BluetoothProfile.PRIORITY_ON) { 307631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 308631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 309631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 310631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.setPriority(device, priority); 311631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 312631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 313631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 314631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 315631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 316631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 317631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 318631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 319631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 320631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 321631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Get the priority of the profile. 322631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 323631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * <p> The priority can be any of: 324631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, 325631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} 326631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 327631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param device Bluetooth device 328631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return priority of the device 329631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 330631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public int getPriority(BluetoothDevice device) { 331631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (VDBG) Log.d(TAG, "getPriority(" + device + ")"); 332631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && 333631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo isValidDevice(device)) { 334631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 335631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.getPriority(device); 336631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 337631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 338631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return PRIORITY_OFF; 339631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 340631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 341631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService == null) Log.w(TAG, "Proxy not attached to service"); 342631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return PRIORITY_OFF; 343631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 344631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 345631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 346631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Send a message. 347631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 348631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * Send an SMS message to either the contacts primary number or the telephone number specified. 349631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 350631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param device Bluetooth device 351631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param contacts Uri[] of the contacts 352631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param message Message to be sent 353631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param sentIntent intent issued when message is sent 354631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param deliveredIntent intent issued when message is delivered 355631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return true if the message is enqueued, false on error 356631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 357631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message, 358631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo PendingIntent sentIntent, PendingIntent deliveredIntent) { 359631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); 360631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && isValidDevice(device)) { 361631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 362631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent); 363631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 364631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 365631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 366631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 367631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 368631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 369631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 370631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 371631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo /** 372b8fc0679e84f9cadc08524ea89f6e1b28631f3e5Joseph Pirozzo * Get unread messages. Unread messages will be published via {@link #ACTION_MESSAGE_RECEIVED}. 373631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * 374631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @param device Bluetooth device 375631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo * @return true if the message is enqueued, false on error 376631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo */ 377631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public boolean getUnreadMessages(BluetoothDevice device) { 378631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")"); 379631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mService != null && isEnabled() && isValidDevice(device)) { 380631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo try { 381631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return mService.getUnreadMessages(device); 382631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } catch (RemoteException e) { 383631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo Log.e(TAG, Log.getStackTraceString(new Throwable())); 384631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 385631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 386631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 387631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 388631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 389631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 390631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private final ServiceConnection mConnection = new ServiceConnection() { 391631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public void onServiceConnected(ComponentName className, IBinder service) { 392631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "Proxy object connected"); 393631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mService = IBluetoothMapClient.Stub.asInterface(service); 394631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mServiceListener != null) { 395631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT, 396631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo BluetoothMapClient.this); 397631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 398631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 399631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 400631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo public void onServiceDisconnected(ComponentName className) { 401631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "Proxy object disconnected"); 402631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mService = null; 403631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (mServiceListener != null) { 404631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT); 405631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 406631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 407631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo }; 408631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 409631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private boolean isEnabled() { 410631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 411631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; 412631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (DBG) Log.d(TAG, "Bluetooth is Not enabled"); 413631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 414631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 415631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 416631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo private boolean isValidDevice(BluetoothDevice device) { 417631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (device == null) return false; 418631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 419631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 420631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo return false; 421631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo } 422631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 423631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo 424631768d81469f83552de05bf0ec839d1cd6eab04Joseph Pirozzo} 425