【问题标题】:Return values from BroadcastReceiver (Bluetooth)BroadcastReceiver(蓝牙)的返回值
【发布时间】:2017-10-26 12:31:52
【问题描述】:

我正在尝试通过实现我自己的 android 蓝牙库来进行蓝牙聊天。我想在图形部分和逻辑部分(为了模块化)之间有一个明确的分离。

为了获取蓝牙设备列表,我以编程方式在我的 BluetoothManager 类(库)中注册了一个新的 BroadcastReceiver。

我想将这些值返回或存储在此类中的一个数组中,以便我可以从我的(外部)活动/片段中访问它们。

我应该怎么做?

这是来自 BluetoothManager(库)的代码:

public class BluetoothManager {

    private BluetoothAdapter bluetoothAdapter;
    private Context context;

    public BluetoothManager(Context context) {
        this.context = context;
        this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Log.d("[BluetoothManager]", "Error device does not support Bluetooth");
        }
    }

    // Create a BroadcastReceiver for ACTION_FOUND.
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object and its info from the Intent.
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // Add value into an array or return --> TODO 
            }
        }
    };

    public void discovery(){
        // Check if the device is already "discovering". If it is, then cancel discovery.
        if (bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
        // Start Discovery
        bluetoothAdapter.startDiscovery();
        // Register for broadcasts when a device is discovered.
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        context.getApplicationContext().registerReceiver(mReceiver, filter);
    }

    ...

}

这是片段中的代码:

public class TabFragment extends ListFragment implements AdapterView.OnItemClickListener {

private BluetoothManager bluetoothManager;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View fragmentView = inflater.inflate(R.layout.fragment_tab_fragment2, container, false);

    Button button = fragmentView.findViewById(R.id.button2);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            bluetoothManager = new BluetoothManager(getContext());
            if(bluetoothManager.activeBluetooth()){
                bluetoothManager.discovery();
                // Get Values here --> TODO
            }
        }
    });

    // Add return values into a list
    //final String[] items = ...;
    final ArrayAdapter<String> aa = new ArrayAdapter<String>(getActivity(),
            android.R.layout.simple_list_item_1, items);
    setListAdapter(aa);

    return fragmentView;
    }
}

【问题讨论】:

    标签: java android asynchronous bluetooth


    【解决方案1】:

    发现可用蓝牙设备的列表是异步的。在接收到广播时,BluetoothManager 类可以将更新的设备列表保存在列表成员变量中,并公开一个公共 getter 方法以从 Activity 或片段中检索它。此外,请考虑将侦听器暴露给您的活动以提供更新的列表,因为设备可以不断地动态添加或删除。在任何时间点,UI 都应在收到更新的设备列表时自行刷新。

    public void onClick(View v) { bluetoothManager = new BluetoothManager(getContext()); ...}

    是个坏主意。理想情况下,您必须在活动或片段的 onCreate 中实例化您的 BluetoothManager 类,以便在用户单击按钮之前有时间发现设备列表。

    我的建议是:

    1. 在Activity的onCreate中实例化BluetoothManager,改变构造函数接受一个回调对象,当设备列表发生变化时进行通知。
    2. 在BluetoothManager 中收听广播以识别设备的添加或删除。更新您的本地列表,每当发生更新时,通知 UI 的回调
    3. 在活动/片段中实现回调,并在收到来自 BluetoothManager 类的更新时更新 UI
    4. 当用户单击按钮时,调用 BluetoothManager 以获取更新的设备列表并更新您的 UI。
    5. 从您的活动的 onDestroy 中取消注册在 BluetoothManager 中注册的广播(非常重要。否则会导致内存泄漏

    或者,如果您想与多个活动共享蓝牙管理器实例,请将蓝牙管理器设置为单例并使用应用程序上下文注册 BroadcastReceiver。当您的所有活动都被销毁并且您不再需要接收器时,请确保取消注册广播接收器。

    更新: 回调可能只是您的活动或片段实现的接口。示例代码如下:

            public interface BluetoothDevicesAvailable {
        void onBluetoothDeviceListChanged(List<BluetoothDevice> deviceList);
        }
    
        public class SomeActivity implements BluetoothDevicesAvailable {
        //... Some code
    
        @Override
        public void onBluetoothDeviceListChanged(List<BluetoothDevice> deviceList) {
        //Add your logic here to update UI
        }
    }
    

    【讨论】:

    • 谢谢。你有回调对象的例子吗?
    【解决方案2】:

    您不能从广播接收器返回值作为其事件驱动。您可以做的是在 onReceive() 中您可以将这些值全局保存到 Collection 中(在同一个类中或在 Singleton 包装器类中),然后在整个应用程序中使用它。

    要发送值更新的回调,另一个本地广播接收器将很有帮助。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多