Проблемы с обнаружением Bluetooth в Samsung Galaxy Tab с использованием Android Bluetooth API

У меня проблема с обнаружением устройств Bluetooth нулевого класса с помощью планшета Galaxy Tab с помощью Android Bluetooth API. Он просто не «видит» некоторые устройства, хотя я могу обнаружить их с помощью телефона или компьютера. Кто-нибудь сталкивался с этой проблемой? Я пишу приложение, которое зависит от сопряжения с устройством через Bluetooth, и некоторая помощь в этом отношении была бы очень признательна.


person Guðrún Hauksdóttir    schedule 16.05.2011    source источник


Ответы (1)


Примечание. Это решение будет работать только со старыми ОС Android, так как для этого требуется доступ к журналам устройства.

Да! У меня точно такая же проблема, но на Samsung Galaxy S и LG Optimus One. Я написал класс, который вы можете использовать повторно, чтобы исправить это, не знаю, будет ли он работать на вкладке Galaxy Tab, но вы можете попробовать:

package com.yourpackagename;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;

// This class exists due to a bug in the Broadcomm bluetooth stack, which is
// used by many Android smart-phone manufacturers (LG, Samsung HTC etc.).  That
// bug prevents discovery of ALL bluetooth devices that report their Class of Device (CoD)
// code as 0x00, which prevent many SPP (Serial Port Profile) devices from working.
// 
// See: http://www.google.com/codesearch/p?hl=en#4hzE-Xyu5Wo/vendor/brcm/adaptation/dtun/dtunc_bz4/dtun_hcid.c&q=%22Device%20[%25s]%20class%20is%200x00%20-%20skip%20it.%22&sa=N&cd=1&ct=rc
// And: http://stackoverflow.com/questions/4215398/bluetooth-device-not-discoverable
// And: http://www.reddit.com/r/Android/comments/hao6p/my_experience_with_htc_support_eu_anyone_has/
//
// How to use (from your Activity class):
// 
//  (new BluetoothClassZeroDiscoveryTask(this, new BluetoothDiscoveryCallback())).execute();
//
// Where BluetoothDiscoveryCallback is a class defined e.g. in your Activity.  The call method
// will be called after the discovery task completes, and is passed the complete list
// of paired bluetooth devices, including those that are undiscoverable due to the above bug.
//
//  private class BluetoothDiscoveryCallback implements Action<ArrayList<BluetoothDevice>>
//  {
//      public void call(ArrayList<BluetoothDevice> devices)
//      {
//          // Now you have the list of ALL available devices, 
//          // including those that report class 0x00.
//      }
//  }
//
//  // Java equivalent of the built-in Action from C#.
//  public interface Action<T>
//  {
//      void call(T target);
//  }
//
public class BluetoothClassZeroDiscoveryTask extends AsyncTask<Void, Void, Void>
{
    // This is the well-known ID for bluetooth serial port profile (SPP) devices.
    public static final UUID BluetoothSerialUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private Activity _parent;
    private boolean _discoveryComplete = false;
    private Action<ArrayList<BluetoothDevice>> _callback;
    private ArrayList<BluetoothDevice> _devices = new ArrayList<BluetoothDevice>();
    private Calendar _discoveryStartTime;
    private SimpleDateFormat _logDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
    private BluetoothAdapter _adapter;
    private ProgressDialog _progressDialog;

    public BluetoothClassZeroDiscoveryTask(Activity parent, Action<ArrayList<BluetoothDevice>> callback)
    {
        _callback = callback;
        _parent = parent;
        _adapter = BluetoothAdapter.getDefaultAdapter();

        IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        _parent.registerReceiver(mReceiver, foundFilter);
        IntentFilter finishedFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        _parent.registerReceiver(mReceiver, finishedFilter);

        // This task performs a scan for bluetooth devices, which 
        // takes ~ 12 seconds, so show an indeterminate progress bar.
        _progressDialog = ProgressDialog.show(_parent, "", "Discovering bluetooth devices...", true);
    }

    // Kicks off bluetooth discovery.
    @Override
    protected Void doInBackground(Void... params)
    {
        _discoveryStartTime = Calendar.getInstance();
        _adapter.startDiscovery();

        while (!_discoveryComplete)
        {
            try
            {
                Thread.sleep(500);
            }
            catch (InterruptedException e) { }
        }

        _adapter.cancelDiscovery();
        return null;
    }

    // Provide notification of results to client.
    @Override
    protected void onPostExecute(Void result)
    {
        _progressDialog.dismiss();
        _parent.unregisterReceiver(mReceiver);
        _callback.call(_devices);
    }

    // Handler for bluetooth discovery events.
    private final BroadcastReceiver mReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action))
            {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                // If it's already paired, skip it, (we'll add it after the scan completes).
                if (device.getBondState() != BluetoothDevice.BOND_BONDED)
                {
                    _devices.add(device);
                }
            }
            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
            {
                // Add all already-paired devices to the list.
                for (BluetoothDevice device : _adapter.getBondedDevices())
                {
                    _devices.add(device);
                }

                // Trawl through the logs to find any devices that were skipped >:(
                try
                {
                    Process process = Runtime.getRuntime().exec("logcat -d -v time *:E");
                    BufferedReader bufferedReader = new BufferedReader(
                            new InputStreamReader(process.getInputStream()));

                    String line;
                    Pattern pattern = Pattern.compile("(.{18}).*\\[(.+)\\] class is 0x00 - skip it.");
                    while ((line = bufferedReader.readLine()) != null)
                    {
                        Matcher matcher = pattern.matcher(line);
                        if (matcher.find())
                        {
                            // Found a blocked device, check if it was newly discovered.
                            // Android log timestamps don't contain the year!?
                            String logTimeStamp = Integer.toString(_discoveryStartTime.get(Calendar.YEAR)) + "-" + matcher.group(1);
                            Date logTime = null;
                            try
                            {
                                logTime = _logDateFormat.parse(logTimeStamp);
                            }
                            catch (ParseException e) { }

                            if (logTime != null)
                            {
                                if (logTime.after(_discoveryStartTime.getTime()))
                                {
                                    // Device was discovered during this scan,
                                    // now we want to get the name of the device.
                                    String deviceAddress = matcher.group(2);
                                    BluetoothDevice device = _adapter.getRemoteDevice(deviceAddress);

                                    // In order to get the name, we must attempt to connect to the device.
                                    // This will attempt to pair with the device, and will ask the user
                                    // for a PIN code if one is required.
                                    try
                                    {
                                        BluetoothSocket socket = device.createRfcommSocketToServiceRecord(BluetoothSerialUuid);
                                        socket.connect();
                                        socket.close();
                                        _devices.add(device);
                                    }
                                    catch (IOException e) { }
                                }
                            }
                        }
                    }
                }
                catch (IOException e) {}

                _discoveryComplete = true;
            }
        }
    };
}

См. Также: http://zornsoftware.codenature.info/blog/pairing-spp-bluetooth-devices-with-android-phones.html.

person Mr. Bungle    schedule 30.05.2011
comment
Спасибо за помощь, вы действительно решили мою проблему. Возможно, это не идеальное решение, но это единственное, с чем я столкнулся. Знаете ли вы, является ли эта фильтрация устройств класса 0x00 частью стека Android Bluetooth или это связано с оборудованием (реализация таких поставщиков, как Samsung, LC и т. Д., И, следовательно, зависит от устройства)? - person Guðrún Hauksdóttir; 23.06.2011
comment
Я считаю, что стек bluetooth различается между поставщиками, например, Samsung, LG, HTC, похоже, используют стек Broadcom, но есть и другие стеки bluetooth, если продавец решит использовать другое оборудование bluetooth. Из того, что я прочитал, телефоны Google Nexus НЕ фильтруют 0x00. (Кстати, отметьте это как ответ, если ваш вопрос решен - спасибо.) - person Mr. Bungle; 28.06.2011
comment
Есть ли галочка, на которую можно нажать рядом с рейтингом ответа (слева от ответа)? - person Mr. Bungle; 01.07.2011
comment
Ссылка не работает. У кого-нибудь есть решение? - person kike; 30.10.2017