Android上见鬼的蓝牙

以前发的各种蓝牙开发的文章中使用的程序,都是在我自己的手机上完美运行过的.

我信心满满的就把app发布了.

之后就收到了很多邮件…各种投诉,说蓝牙完全搜索不到啦!蓝牙连不上啦!用不了啦!

和公司之前所有Android版本的蓝牙功能相比,我做的这个版本在扫描附近蓝牙的时候,可以实时的更新蓝牙信号的强度.
完美解决了之前用户拿着app不知道哪一个蓝牙是前轮,哪一个蓝牙是后轮.

这一套在我自己的手机(Nexus 6P)上完美流畅的运行了,在一些用户的手机上竟然出现了,完全扫描不到蓝牙外设的情况!

其实在发布之前,我们公司内部所有的android手机都参与了测试,虽然手机不同,性能不同,但是都没有出现完全搜索不到的现象.

于是我掏出我的坚果手机(不是坚果pro),打开了搜索界面,也出现了搜索的结果,只不过…过了一会儿,它们就消失了!

Debug

于是我就接上电脑看看控制台都说了一些什么…

在搜索到了某一个设备的蓝牙广播之后,系统好像就不想再收这个蓝牙外设的广播信号了!

我的搜索界面是定时刷新可用的蓝牙外设列表的,在判断某一个蓝牙外设是不是还存在的时候,我用了时间戳.每次底层搜索到蓝牙外设的时候,我会在model层更新这个蓝牙外设的时间戳.每次View层获取最新列表数据的时候,把每个设备的更新时间戳减去当前的时间戳,如果超过一个阈值,说明这个蓝牙外设已经不存在了.

public class ScanItem {

    private BluetoothDevice device;
    private int rssi;
    private int model;
    private long updateTime;
    private boolean connecting;
    private boolean connected;

    /**
    ...
    **/

    public boolean isAvailable(){
        return ((System.currentTimeMillis()-updateTime)<2000);
    }
}

在判断这里我的阈值是2秒,看来在某些垃圾手机上面,是不能酱紫的.于是我就改成了20秒.

运行起来,发现还是不行……

因为,不管过多少秒,这个垃圾系统都不在把收到的广播信息返回给我了!

See see dalao’s work

然后我想到,有那么多做蓝牙的app,我看看它们怎么运行的,怎么实时更新信号强度的.

我下载了我最喜欢的BLE Scanner,运行了起来,发现很完美啊.

然后我就在控制台里面看,发现这个app在一个劲的停止搜索,开始搜索,停止搜索,开始搜索……

或许这是一个好方法!既然这种破系统一次扫描对一个设备只会给一次广播信号,那我只能多次停止扫描开启扫描咯.

if (VKBluetoothManager.getInstance().isScanning()){
    VKBluetoothManager.getInstance().stopScan();
    handler.postDelayed(scanControlRunnable,50);
}else {
    VKBluetoothManager.getInstance().scanDevices();
    handler.postDelayed(scanControlRunnable,950);
}

心满意足的运行了起来,发现完美,这个破坚果终于达成了实时刷新的效果!

But……在Nexus 6P上面竟然出现了系统错误

E/BtGatt.GattService: App 'XuanWheel' is scanning too frequently

Are you f**king kidding me?

这样不行,那样也不行~

扫描的太频繁,意思应该是刚结束扫描后,再次开始的时间间隔太短了吧.

于是我就改了两个时间postdelay的延迟时间

if (VKBluetoothManager.getInstance().isScanning()){
    VKBluetoothManager.getInstance().stopScan();
    handler.postDelayed(scanControlRunnable,2000);
}else {
    VKBluetoothManager.getInstance().scanDevices();
    handler.postDelayed(scanControlRunnable,4000);
}

这样子就可以了!

嗯,虽然说这样子实现了实时刷新信号强度的功能,但是毕竟刷新率还是很低的……而且本来Nexus 6p可以拥有更高的刷新率,为了兼容这些臭系统,只能一起降低效果了……这么看起来,还是iOS比较好~

Why

那么,为啥某些Android系统要这么搞呢!

我猜,他们为了提高电池寿命,节省CPU资源,让UI更加流畅,所以牺牲了一些使用频率不那么高的外设的性能,于是我们可怜的蓝牙,就这么被阉割了.不过你们在系统里面搞幺蛾子,用户不会说什么,但是用户的手机在使用需要蓝牙的app的时候,这些开发者就很悲催了呀~他们(我们)明明遵守着设计准则,却发现自己的程序跑在了假系统上,还被用户吐槽,被打一星,真是有苦说不清啊…