如何在Android中实现BroadcastReceiver

发布于 2024-12-09 09:57:24 字数 3124 浏览 0 评论 0原文

我正在尝试实现 BroadcastReceiver 但它不起作用。 我想用它从实现网络 io 的类返回进度,该类是从我的 Activity 内的 AsyncTask 调用的。

这是我的活动的代码:

package com.ClinicalInterface;

public class TestActivity extends ListActivity {

    static AsyncDataLoader mAsyncDataLoader;
    static ProgressDialog dialog;
    static ArrayList<String> list;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dialog = new ProgressDialog(this);
        dialog.setMessage("Loading...");
        dialog.show();
        mAsyncDataLoader = new AsyncDataLoader();
        mAsyncDataLoader.execute();  
     }

    public class AsyncDataLoader extends AsyncTask<Void, Integer, String> {        

        public class mTestReceiver extends BroadcastReceiver {
            @Override 
            public void onReceive(Context context, Intent intent){
                System.out.println( "I've received something!" );
                publishProgress(2);
            }
        }

        @Override
        protected String doInBackground( Void ... params ) {            
            TestLoader tl = new TestLoader();
            tl.setContext(getApplicationContext());
            tl.setServeraddress("192.168.2.109");
            list = tl.doLST(null);
            return "COMPLETE!";
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (values[0] == 2) {
                dialog.setMessage("Loading data ...");
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            dialog.dismiss();
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(TestActivity.this, R.layout.list_item, list);
            TestActivity.this.setListAdapter(adapter);                     
        }
    }         
}

这应该显示一个列表,然后用一个进度对话框覆盖它,同时从服务器返回列表的数据。这工作正常。 我想在网络 io 完成时更新进度对话框中的文本。 这是实现网络 io 的代码:

package com.ClinicalInterface;

public class TestLoader {
    private Context mContext;

    public void setContext(Context context) {
        mContext = context;
    }

     public ArrayList<String> doLST(String arg) {

         // Send intent to AsyncTask         
         Intent intent = new Intent(mContext, mTestReceiver.class);
         intent.setAction("PROGRESS");
         mContext.sendBroadcast(intent);
         System.out.println( "message sent" );

         // Code that actually does network io removed for brevity
    }
}

在 Android 清单文件中,我添加了以下内容:

<activity android:name="TestActivity" android:label="TestActivity">
    <receiver android:name=".AsyncDataLoader.mTestReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PROGRESS" />
        </intent-filter>
    </receiver>
</activity>

我得到日志打印“消息已发送” 但不是日志打印“我收到了一些东西”

我是一个Android新手,所以我认为我没有正确实现一些东西。 有什么想法吗?

原始帖子在创建意图时更新了意图过滤器和一组操作。仍然没有工作。

I am trying to implement a BroadcastReceiver but it is not working.
I want to use it to return progress from a class that implements network io, which is called from an AsyncTask inside my Activity.

Here is the code for my activity:

package com.ClinicalInterface;

public class TestActivity extends ListActivity {

    static AsyncDataLoader mAsyncDataLoader;
    static ProgressDialog dialog;
    static ArrayList<String> list;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dialog = new ProgressDialog(this);
        dialog.setMessage("Loading...");
        dialog.show();
        mAsyncDataLoader = new AsyncDataLoader();
        mAsyncDataLoader.execute();  
     }

    public class AsyncDataLoader extends AsyncTask<Void, Integer, String> {        

        public class mTestReceiver extends BroadcastReceiver {
            @Override 
            public void onReceive(Context context, Intent intent){
                System.out.println( "I've received something!" );
                publishProgress(2);
            }
        }

        @Override
        protected String doInBackground( Void ... params ) {            
            TestLoader tl = new TestLoader();
            tl.setContext(getApplicationContext());
            tl.setServeraddress("192.168.2.109");
            list = tl.doLST(null);
            return "COMPLETE!";
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (values[0] == 2) {
                dialog.setMessage("Loading data ...");
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            dialog.dismiss();
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(TestActivity.this, R.layout.list_item, list);
            TestActivity.this.setListAdapter(adapter);                     
        }
    }         
}

This is supposed to display a list, then overlay this with a progress dialog while the data for the list is returned from a server. And this works OK.
I would like to update the text in the progress dialog as the network io is done.
This is the code that implements the network io:

package com.ClinicalInterface;

public class TestLoader {
    private Context mContext;

    public void setContext(Context context) {
        mContext = context;
    }

     public ArrayList<String> doLST(String arg) {

         // Send intent to AsyncTask         
         Intent intent = new Intent(mContext, mTestReceiver.class);
         intent.setAction("PROGRESS");
         mContext.sendBroadcast(intent);
         System.out.println( "message sent" );

         // Code that actually does network io removed for brevity
    }
}

In the Android manifest file I've added the following:

<activity android:name="TestActivity" android:label="TestActivity">
    <receiver android:name=".AsyncDataLoader.mTestReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PROGRESS" />
        </intent-filter>
    </receiver>
</activity>

I get the log print "message sent"
But not the log print "I've received something"

I am an Android newbie so I assume I've not implemented something correctly.
Any ideas?

Original post updated with intent-filter and set of action when creating the intent. Still not working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安静 2024-12-16 09:57:24

您的 标记需要包含 告诉 Android 您实际想要接收哪些广播意图。

编辑:

Intent只不过是消息的容器;您调用该函数来发送Intent,该函数确定您需要设置哪些字段。

来自 Intent 的文档:

[Intent] 可以与 startActivity 一起使用来启动 ActivitybroadcastIntent 将其发送到 <任何感兴趣的 BroadcastReceiver 组件,以及 startService(Intent)bindService(Intent, ServiceConnection, int) 与背景服务

这些函数是您发送 Intent 的选项。 startActivitystartService/bindService 函数使用显式 IntentsendBroadcast 没有。

请注意,如果 startActivity 找不到您的 Intent 的目标类,则会引发异常,并且 startService 将返回 null code> 如果找不到你的目标类。 sendBroadcast 不会执行类似的操作,因为它甚至不查看该字段。 sendBroadcast “向所有感兴趣的广播接收器广播给定的意图。”

由于您使用 Context.sendBroadcast() 来发送您的意图,因此您应该在您的 Intent 上设置一个操作,并且您的 BroadcastReceiver 应该有一个包含该操作条目的意图过滤器。

Your <receiver> tag needs to contain an <intent-filter> to tell Android which broadcast intents you actually want to receive.

EDIT:

An Intent is not much more than a container for a message; it's the function that you call to send the Intent that determines which fields you need to set.

From the docs for Intent:

[Intent] can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.

Those functions are your options for sending Intents. startActivity and the startService/bindService functions use explicit Intents; sendBroadcast does not.

Notice that startActivity throws an exception if it can't find your Intent's target class, and startService will return null if it can't find your target class. sendBroadcast doesn't do anything like that because it doesn't even look at that field. sendBroadcast "Broadcasts the given intent to all interested BroadcastReceivers."

Since you are using Context.sendBroadcast() to send your intent, you should be setting an action on your Intent and your BroadcastReceiver should have an intent filter containing an entry for that action.

月下凄凉 2024-12-16 09:57:24

好的
答案似乎是不可能使用清单来注册接收者。
如果我更改代码以使其使用 registerReceiver 那么它就可以正常工作。
代码更新如下:

@Override
protected String doInBackground( Void ... params ) {            
    TestLoader tl = new TestLoader();
    IntentFilter intentFilter = new IntentFilter("PROGRESS");
    mReceiver mmReceiver = new mReceiver();
    registerReceiver(mmReceiver, intentFilter);            
    tl.setContext(getApplicationContext());
    tl.setServeraddress("192.168.2.109");
    list = tl.doLST(null);
    unregisterReceiver(mmReceiver);
    return "COMPLETE!";
}

并从清单中删除与接收者有关的任何内容。

注意:发送Broadcast的代码是这样的:

 Intent intent = new Intent();
 intent.setAction("PROGRESS");
 mContext.sendBroadcast(intent);

Ok
It seems like the answer is that its not possible to use the manifest to register the receiver.
If I change the code so that it uses registerReceiver then it works ok.
Code updated like this:

@Override
protected String doInBackground( Void ... params ) {            
    TestLoader tl = new TestLoader();
    IntentFilter intentFilter = new IntentFilter("PROGRESS");
    mReceiver mmReceiver = new mReceiver();
    registerReceiver(mmReceiver, intentFilter);            
    tl.setContext(getApplicationContext());
    tl.setServeraddress("192.168.2.109");
    list = tl.doLST(null);
    unregisterReceiver(mmReceiver);
    return "COMPLETE!";
}

And remove anything to do with the receiver from the manifest.

Note: the code that sends the Broadcast is like this:

 Intent intent = new Intent();
 intent.setAction("PROGRESS");
 mContext.sendBroadcast(intent);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文