/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.bluetooth; import android.bluetooth.RfcommSocket; import android.util.Log; import java.io.*; import java.util.*; /** * The Android Bluetooth API is not finalized, and *will* change. Use at your * own risk. * * A low-level API to the Service Discovery Protocol (SDP) Database. * * Allows service records to be added to the local SDP database. Once added, * these services will be advertised to remote devices when they make SDP * queries on this device. * * Currently this API is a thin wrapper to the bluez SDP Database API. See: * http://wiki.bluez.org/wiki/Database * http://wiki.bluez.org/wiki/HOWTO/ManagingServiceRecords * @hide */ public final class Database { private static Database mInstance; private static final String sLogName = "android.bluetooth.Database"; /** * Class load time initialization */ static { classInitNative(); } private native static void classInitNative(); /** * Private to enforce singleton property */ private Database() { initializeNativeDataNative(); } private native void initializeNativeDataNative(); protected void finalize() throws Throwable { try { cleanupNativeDataNative(); } finally { super.finalize(); } } private native void cleanupNativeDataNative(); /** * Singelton accessor * @return The singleton instance of Database */ public static synchronized Database getInstance() { if (mInstance == null) { mInstance = new Database(); } return mInstance; } /** * Advertise a service with an RfcommSocket. * * This adds the service the SDP Database with the following attributes * set: Service Name, Protocol Descriptor List, Service Class ID List * TODO: Construct a byte[] record directly, rather than via XML. * @param socket The rfcomm socket to advertise (by channel). * @param serviceName A short name for this service * @param uuid * Unique identifier for this service, by which clients * can search for your service * @return Handle to the new service record */ public int advertiseRfcommService(RfcommSocket socket, String serviceName, UUID uuid) throws IOException { String xmlRecord = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<record>\n" + " <attribute id=\"0x0001\">\n" + // ServiceClassIDList " <sequence>\n" + " <uuid value=\"" + uuid.toString() + // UUID for this service "\"/>\n" + " </sequence>\n" + " </attribute>\n" + " <attribute id=\"0x0004\">\n" + // ProtocolDescriptorList " <sequence>\n" + " <sequence>\n" + " <uuid value=\"0x0100\"/>\n" + // L2CAP " </sequence>\n" + " <sequence>\n" + " <uuid value=\"0x0003\"/>\n" + // RFCOMM " <uint8 value=\"" + socket.getPort() + // RFCOMM port "\" name=\"channel\"/>\n" + " </sequence>\n" + " </sequence>\n" + " </attribute>\n" + " <attribute id=\"0x0100\">\n" + // ServiceName " <text value=\"" + serviceName + "\"/>\n" + " </attribute>\n" + "</record>\n"; Log.i(sLogName, xmlRecord); return addServiceRecordFromXml(xmlRecord); } /** * Add a new service record. * @param record The byte[] record * @return A handle to the new record */ public synchronized int addServiceRecord(byte[] record) throws IOException { int handle = addServiceRecordNative(record); Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle)); return handle; } private native int addServiceRecordNative(byte[] record) throws IOException; /** * Add a new service record, using XML. * @param record The record as an XML string * @return A handle to the new record */ public synchronized int addServiceRecordFromXml(String record) throws IOException { int handle = addServiceRecordFromXmlNative(record); Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle)); return handle; } private native int addServiceRecordFromXmlNative(String record) throws IOException; /** * Update an exisiting service record. * @param handle Handle to exisiting record * @param record The updated byte[] record */ public synchronized void updateServiceRecord(int handle, byte[] record) { try { updateServiceRecordNative(handle, record); } catch (IOException e) { Log.e(getClass().toString(), e.getMessage()); } } private native void updateServiceRecordNative(int handle, byte[] record) throws IOException; /** * Update an exisiting record, using XML. * @param handle Handle to exisiting record * @param record The record as an XML string. */ public synchronized void updateServiceRecordFromXml(int handle, String record) { try { updateServiceRecordFromXmlNative(handle, record); } catch (IOException e) { Log.e(getClass().toString(), e.getMessage()); } } private native void updateServiceRecordFromXmlNative(int handle, String record) throws IOException; /** * Remove a service record. * It is only possible to remove service records that were added by the * current connection. * @param handle Handle to exisiting record to be removed */ public synchronized void removeServiceRecord(int handle) { try { removeServiceRecordNative(handle); } catch (IOException e) { Log.e(getClass().toString(), e.getMessage()); } } private native void removeServiceRecordNative(int handle) throws IOException; }