Android Bluetooth SDP не распознает сервис, рекламируемый в JAVAME - PullRequest
5 голосов
/ 23 февраля 2012

Я занимаюсь разработкой приложения Bluetooth для моего MSc. Завершить проект. Он включает в себя сервер, реализованный в JAVA ME, и клиент, написанный в Android.

Проблема в том, что Android SDP не может распознать ServiceRecord моего сервера JAVA ME.

Если я использую методы BluetoothDevice.getUuids() и BluetoothDevice.fetchUuidsWithSdp() в моем клиенте, они возвращают набор UUIDs, но моего сервиса UUID нет среди них, поэтому я не могу подключиться к нему.

Это код для JAVAME примера сервера:

/*IMPORTS*/

public class StackOverFlowServer extends MIDlet {
    Display mDisplay;
    Form mForm;
    LocalDevice local;
    StreamConnectionNotifier server;
    ServiceRecord sr;
    String conURL;
    StreamConnection conn;
    public StackOverFlowServer() {
        mDisplay = Display.getDisplay(this);
        mDisplay.setCurrent(mForm);
        mForm = new Form(null);
        conURL = "btspp://localhost:68EE141812D211D78EED00B0D03D76EC;"
                + "authenticate=false;encrypt=false;name=MySampleApp";
    }

    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
        // TODO Auto-generated method stub

    }

    protected void pauseApp() {
        // TODO Auto-generated method stub

    }

    protected void startApp() throws MIDletStateChangeException {
        try {
            local = LocalDevice.getLocalDevice();
        } catch (BluetoothStateException e) {
            // Error handling code here
        }
        /*
        * When creating a StreamConnectionNotifier a service record
        * will automatically be created for us, describing the new
        * service. The service will have the Serial Port (0x1101)
        * value in the ServiceClassIDList (id 0x0001) attribute. The
        * service record will also have both the L2CAP (0x0100) and
        * RFCOMM (0x0003) values in the ProtocolDescriptorList (id
        * 0x0004) attribute. Other mandatory attributes will be set
        * automatically by the JABWT implementation. The optional
        * ServiceName (id 0x100) attribute will be set to the name
        * parameter, "BTDemoApp" in this case.
        */
        try {
            server = (StreamConnectionNotifier)
                    Connector.open(conURL);
        } catch (IOException e1) {
            // Error handling code here
        }
        /*
        * The automatically created service record can be obtained
        * from the LocalDevice object, using the reference to the
        * StreamConnectionNotifier.
        */
        try {
            sr = local.getRecord(server);
        }
        catch (IllegalArgumentException iae){
            // Error handling code here
        }
        /*
        * We create a new DataElement and set its content correctly.
        */
        DataElement elm = null;
        /*
        * Setting public browse root in the browsegrouplist
        * attribute. The BrowseGroupList (id 0x0005) attribute
        * contains a DataElement sequence, which in turn contains
        * DataElements with UUIDs. The DataElement sequence must be
        * created before we can add DataElements to it.
        */
        elm = new DataElement(DataElement.DATSEQ);
        elm.addElement(new DataElement(
        DataElement.UUID,new UUID(0x1002)));
        /*
        * The DataElement is now prepared. It must be added to the
        * appropriate attribute ID, in this case the
        * BrowseGroupList.
        */
        sr.setAttributeValue(0x0005,elm);
        /*
        * Finally, the service record must be updated in our
        * LocalDevice.
        */
        try {
            local.updateRecord(sr);
        } catch (ServiceRegistrationException e3) {
            // Error handling code here
        }
        try {
        conn = server.acceptAndOpen();
        } catch (ServiceRegistrationException sre){
            // Error handling code here
        } catch (IOException e2) {
            // Error handling code here
        }
        /*
        * At this point a client is connected. input and output
        * streams can be obtained from the conn object,
        * communication can begin.
        */
    }
}

И это часть Android-клиента:

package com.exampleproyect.stackoverflowclient;

import java.lang.reflect.InvocationTargetException;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.os.Parcelable;

public class StackOverFlowClientActivity extends Activity {
    BluetoothAdapter mBluetoothAdapter;
    BluetoothDevice C702;
    BroadcastReceiver mReceiver;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        C702 = mBluetoothAdapter.getRemoteDevice("00:23:F1:27:16:DA");
        C702.fetchUuidsWithSdp();
        mReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context arg0, Intent intent) {
              String action = intent.getAction();
              if (BluetoothDevice.ACTION_UUID.equals(action)){
                  Parcelable[] uuidExtra =                    intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");
                  /*uuidExtra should contain my service's UUID among his files, but it doesn't!!*/
              }
          }
      };
      // Register the BroadcastReceiver
      IntentFilter filter1 = new IntentFilter(BluetoothDevice.ACTION_UUID);
      registerReceiver(mReceiver, filter1); // Don't forget to unregister during onDestroy
    }
}

Что меня больше всего беспокоит, так это то, что мой компьютер видит, что мой сервер JAVAME правильно объявлен: enter image description here

Что я делаю не так ?? :( Почему мой ПК Bluetooth видит, что мой сервис правильно объявлен в JAVAME, но Android не может ?? Может ли Android подключаться через Bluetooth к JAVAME серверам?

Я прочитал множество других подобных вопросов здесь, в StackOverFlow, но мне не удалось найти работающее решение. (

Я использую Sony Ericsson C702 (Java Platform 8) в качестве тестового сервера. И Samsung Galaxy S (ICS 4.0.3, команда ICSSGS RC4.2)


EDIT1

OK.

Я знаю, в чем проблема.

Я хочу, чтобы сервер JAVAME объявил мой сервис с UUID (например): "68EE1418-12D2-11D7-8EED-00B0D03D76EC", но, похоже, код:

        conURL = "btspp://localhost:68EE141812D211D78EED00B0D03D76EC;"
                + "authenticate=false;encrypt=false;name=MySampleApp";
        server = (StreamConnectionNotifier)
                Connector.open(conURL);

Добавляет UUID службы последовательного порта по умолчанию «00001101-0000-1000-8000-00805F9B34FB» в качестве атрибута ServiceClassIDList:

enter image description here

Теперь забавно то, что в Android метод BluetoothDevice.fetchUuidsWithSdp (); Похоже, что он извлекает UUID по умолчанию «00001101-0000-1000-8000-00805F9B34FB» вместо моего UUID «68EE1418-12D2-11D7-8EED-00B0D03D76EC», перекрывая мою службу со службой серийного порта по умолчанию мобильного телефона.

Что-то похожее на средневековый сетевой сканер Bluetooth, он распознает мой сервис, но рекламируется как "00001101-0000-1000-8000-00805F9B34FB":

enter image description here

Что я могу сделать, чтобы удалить лишние UUID, которые JAVAME автоматически добавляют к моему сервису?

Пожалуйста, помогите, спасибо!

EDIT2

ОК, проблема возникает с телефонами Sony Ericsson. Очевидно, они вставляют стандартный последовательный порт UUID {0x1101} перед моим пользовательским UUID, в то время как телефоны Samsung и Nokia, например, вставляют этот стандартный UUID позади моего собственного в служебной записи. Похоже, что Android извлекает только первое значение атрибута 0x001 в служебной записи, поэтому путает мой сервис со стандартным последовательным портом, который поставляется с некоторыми устройствами.

Так что решение будет:

Есть ли способ с текущим API Android, чтобы получить больше servicerecord атрибутов, кроме ServiceClassID (0x001)?

или

Есть ли способ обновить servicerecord, хранящийся в базе данных обнаружения служб (SDDB), после вызова метода acceptAndOpen -JAVAME-? -Я использовал LocalDevice.updateRecord после создания сервиса на SDDB, он работает на эмуляторе, но выдает исключение и ничего не делает на реальных устройствах.

...