【问题标题】:How to wait for Broadcast Receiver to finish如何等待广播接收器完成
【发布时间】:2026-02-11 14:40:01
【问题描述】:

我有一种方法,我使用意图过滤器注册广播接收器以发现蓝牙设备。

// global variable
 String xpto = "empty";

这里是void方法:

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

            BroadcastReceiver mReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {

                     App appState = ((App)getApplicationContext());
                     appState.setTeste("OLAAAAA");

                    String action = intent.getAction();

                    elementos = new Vector<String>();

                    String delimiter = "_";
                    String[] temp = null;

                    xpto = "OLA";

                    // When discovery finds a device
                    if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                        // Get the BluetoothDevice object from the Intent
                        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);


                        // SO VAI VERIFICAR DO QUE ESTAO PRESENTES (DISCOVERABLE) OS QUE ESTAO PAIRED
                        if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
                            Log.v("TAG","PAIRED AND PRESENT="+device.getName());
                            temp = device.getName().split(delimiter);
                        }

                        int aux = 0;

                        if(temp != null)
                        {
                            for(int i =0; i < temp.length ; i++)
                            {
                                if(temp[aux].equals("SapoFit"))
                                {
                                    elementos.add(temp[aux]+"_"+temp[aux+1]);
                                    Log.v("TAG","Seleccionado="+temp[aux]+"_"+temp[aux+1]);
                                }
                                aux++;
                            }

                            elSelecionado = temp[0]+"_"+temp[0+1];

                        }

                    } 

                }
            };

            this.registerReceiver(mReceiver, filter);

            Log.v("TAG","HERE COMES empty="+xpto.toString());

我的问题是:因为该方法中的代码是按顺序执行的,所以当我尝试使用(在该方法中的序列中)我在广播接收器中分配的一些全局变量时,它们仍然是 null强>或空。

我已经在一些“解决方案”中,比如将我的“主代码”从一个地方移动到广播接收器,或者在 B.R 完成时将一些其他全局变量分配为 1(以及一段时间 x =!主代码中的 1 到等等)但这不是好的编程,我相信有一个正确的方法来做到这一点。

我找到了 PendingResult,但它是 API 级别 11,对我来说太高了。有什么建议吗?

【问题讨论】:

    标签: java android broadcastreceiver intentfilter


    【解决方案1】:

    如果它被多个组件使用并且对您的应用程序真正“全局”,您可以扩展Application 对象并在那里使用它。这意味着它将在您的任何一个组件启动之前分配并且您的所有组件都可以访问它。它也是“安全的”并且被许多人推荐,因为“全局”变量在生命周期之外,就像 Application 对象一样。只要两个组件不是同时读取和写入,就可以了。如果您预见到那里存在问题,您也可以通过同步来使代码线程安全。

    关于扩展应用程序的警告。这不应该用于需要多个对象来访问它的所有内容。这应该只用于那些出于必要而需要保留在生命周期之外的数据。

    如果您需要说明如何扩展 Application 并访问新数据,请告诉我。

    希望这会有所帮助, 模糊逻辑

    【讨论】:

    • 我将此代码 pastebin.com/mXG6iyW6 类 App 放在另一个文件中,并将其添加到清单中,但我仍然得到空值。我不明白什么?
    • 我去看看。 Null 只是我们必须处理的事情之一。 :)
    • 查看您的代码后,1) 在您的 Activity 中,不要使用 getApplicationContext()。使用 getApplication()。活动可以访问两者。两者相似,但可以访问不同的信息。 2)您可能会遇到处理效率太高且应用程序可能会死掉的情况。将状态(及其 getter 和 setter)设为静态可能会解决此问题,这是一个安全的地方(甚至当您需要在对象的 Android 生命周期之外持续存在时,Google 也建议您这样做)。
    • 此外,如果您将 Application 对象设为 Singleton(无论如何它本质上都是),它还将保留其数据。只是不要在其中存储对生命周期管理对象的任何引用,你会没事的。
    【解决方案2】:

    也许你可以使用 wait() 和 notify().. 注意同步:

    NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    
    synchronized (nm) {
                try {
                    // Esperar a que finalice la descarga
                    nm.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    

    参考Threading in Java: How to lock an object? 还有how to fire notification from BroadcastReceiver?

    【讨论】: