开发者

How to implement a BroadcastReceiver in Android

开发者 https://www.devze.com 2023-04-12 19:26 出处:网络
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.

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.


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.


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);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号