Android 遇坑【5】 - bindService 未触发onServiceConnected回调

问题

在绑定蓝牙获取服务时,发现以下问题:

bindService()绑定蓝牙服务,onServiceConnected()未被触发。

在我的 Demo

说明:Service服务 中 未开启多线程


//...

/**
 * 成功连接到服务则会触发onServiceConnected回调
 */
private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceDisconnected(ComponentName name) {
        mService = null;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mService = ((BluetoothLeService.LocalBinder) service).getBLEService();// 程序走到这里之后,就得到了 Service 对象
        mBluetoothGattService = mService.getBluetoothGattService();
        mBluetoothGattCharacteristic = mService.getBluetoothGattCharacteristic();
    }
};


//...

@Override
public void onStart() {
    super.onStart();

    final int BIND_AUTO_CREATE = 0x0001;

    //获取 BLE 服务实例
    Intent bindIntent = new Intent(getActivity(), BluetoothLeService.class);

    boolean bind = getActivity().bindService(bindIntent, connection, BIND_AUTO_CREATE);

    Log.i("Display BindService",""+bind);

}



@Override
public void onResume() {
    super.onResume();

    //读取设备信息
    Read_Information_Data();

    //读取实时信息
    Read_Realtime_Data();

}


/**
 * 蓝牙解绑
 */
@Override
public void onStop() {
    super.onStop();

    getActivity().unbindService(connection);
}



onResume()中发送读指令操作失败。

通过 Debug 发现我们并未获取蓝牙服务实例,即onServiceConnected()未执行。

解决方法

查阅 官方文档,发现了这么一段描述:

注意,根据文档所述,我们bindService()的返回值只是表明服务是否存在;真正能代表是否成功绑定服务的是触发onServiceConnected()回调。

为此 我先想到的解决方法是

while(true){

    //等待取得mService
    if(null != mService){

        //获得服务后的一些处理
    }

}

然而这样如果是在 UI线程 中绑定服务,绑定后就进入死循环等待。这时就会出现 “未响应”的错误。

因为 UI线程 被阻塞了,我们一直等不到重写的onServiceConnected()方法被调用。

文档中还有这样一段描述:

所谓异步操作,即我们执行完bindService(),并 不会马上回调onServiceConnected()当然也不会等待它;而是按照程序的顺序继续执行。这时由于服务还未成功获取到,我们调用服务中的方法就会出错。

目前我的 解决方法

绑定后开启一个线程去判断是否已获取服务,如果以获取进行相应的处理。如果未获取,则延时后再判断。

 new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    Utils.delay(20);
                    //等待取得mService
                    if(null != mService){
                        //...
                    }
                    //...

                }
            }

        }).start();

当然还有一种方法,即官方例程提供的做法:

在按键监听事件中使用

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
        mBound = false;
    }

    /** Called when a button is clicked (the button in the layout file attaches to
      * this method with the android:onClick attribute) */
    public void onButtonClick(View v) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call were something that might hang, then this request should
            // occur in a separate thread to avoid slowing down the activity performance.
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

结语

如果有不一样的解决方法,欢迎留言交流~

如果有说得不对得地方,还望指正~

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值