从广播接收器传递数据到活动页面

3
我有一个短信阅读器应用程序,将发件人号码和消息正文显示在自定义列表视图中。对于传入的消息,我已经注册了广播接收器并填充了列表视图。
每当新消息进来时,广播接收器就能获取到它,但我想将这些数据传递到活动中。
代码片段如下:
MainActivity.java
public class MainSmsActivity extends Activity{
    private ListView smsList;
    SmsAdapter smsAdapter;
    private SmsDao smsDao;
    private List<SmsDao> smsDataList;

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sms_demo);
        smsDataList = new ArrayList<SmsDao>();
        Intent intent = new Intent();
        intent.setAction("com.mobile.sms.IncomingSms");
        sendBroadcast(intent);
        populateSms();
   }

public void populateSms(){
        Uri inboxURI = Uri.parse("content://sms/inbox");
        String[] reqCols = new String[] { "_id", "address", "body", "date" };
        ContentResolver cr = getContentResolver();
        Cursor cursor = cr.query(inboxURI, reqCols, null, null, null);
        smsDataList.clear();

        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            smsDao = new SmsDao();
            smsDao.setMessageBody(cursor.getString(1));
            smsDao.setSenderNo(cursor.getString(2));
            smsDao.setMessageTime(cursor.getLong(3));
            smsDataList.add(smsDao);
          }
        smsAdapter = new SmsAdapter(this,smsDataList);
        smsList.setAdapter(smsAdapter);
        smsAdapter.notifyDataSetChanged();
        cursor.close();
}
}

IncomingSms.Java

public class IncomingSms extends BroadcastReceiver {
    final SmsManager sms = SmsManager.getDefault();
    public void onReceive(Context context, Intent intent) {
        final Bundle bundle = intent.getExtras();
        try {
            if (bundle != null) {
                final Object[] pdusObj = (Object[]) bundle.get("pdus");
                for (int i = 0; i < pdusObj.length; i++) {
                    SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                    String senderNum = phoneNumber;
                    String message = currentMessage.getDisplayMessageBody();
                    int duration = Toast.LENGTH_LONG;  // HERE I WANT TO SEND MESSAGE BODY TO THE MAIN ACTIVITY CLASS
                    Toast toast = Toast.makeText(context,
                            "senderNum: " + senderNum + ", message: " + message, duration);
                    toast.show();
                } // end for loop
            } // bundle is null
        } catch (Exception e) {
            Log.e("SmsReceiver", "Exception smsReceiver" + e);
        }
    }

我能够在最初将所有信息接收到列表视图中,但我希望ListView在新消息到达时能自动更新。
3个回答

2
在你的广播接收器中,可以像这样做:(使用该意图)
public class SMSReceiver extends BroadcastReceiver {

public static final String NOTIFICATION = "receiver_sms";
@Override
public void onReceive(Context context, Intent intent) {

    Log.i("onReceive methode", "new SMS Comming");

    Bundle myBundle = intent.getExtras();

    SmsMessage[] messages = null;
    String strMessage = "", address = "";
    abortBroadcast();
    if (myBundle != null) {
        // get message in pdus format(protocol description unit)
        Object[] pdus = (Object[]) myBundle.get("pdus");
        // create an array of messages
        messages = new SmsMessage[pdus.length];
        Log.i("onReceive methode", "new SMS Comming");
        for (int i = 0; i < messages.length; i++) {
            // Create an SmsMessage from a raw PDU.
            messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
            // get the originating address (sender) of this SMS message in
            // String form or null if unavailable
            address = messages[i].getOriginatingAddress();

            // get the message body as a String, if it exists and is text
            // based.
            strMessage += messages[i].getMessageBody();
            strMessage += "\n";
        }

        // show message in a Toast
    }
        // this is what you need
        Intent broadcast = new Intent(NOTIFICATION);
        broadcast.putExtra("data", strMessage);
        LocalBroadcastManager.getInstance(context).sendBroadcast(broadcast);

}

然后在您的活动中注册接收器。
public BroadcastReceiver receiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(tag, "SMS Received.");
        // Intent i = getIntent();
        Bundle b = intent.getBundleExtra("SMS");
        // String bun = b.getString("MyData");
        Log.i(tag, "Bundle:  " + b);
        String str = intent.getStringExtra("data");

        parseSMSData(str);
    }
};

然后在onResume()方法中:

@Override
protected void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
            new IntentFilter(SMSReceiver.NOTIFICATION));
}

在onDestroy()方法中,你必须像这样注销该接收器:

@Override
protected void onDestroy() {
    // Unregister since the activity is about to be closed.
    LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    super.onDestroy();
}

同时,不要忘记在应用程序标签中的清单文件中添加以下内容:
 <receiver android:name=".SMSBroadcastReceiver">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
        </intent-filter>
    </receiver>

1
OnResume()中注册您的服务,然后您可以在类内轻松访问。
@Override
public void onResume()
{
    super.onResume();
    this.registerReceiver(this.yourservice, new IntentFilter("your service type"));
}

在您的代码中取消注册服务,可以在onPause()中实现。
@Override
public void onPause() {
    super.onPause();
    try
    {
        this.unregisterReceiver(this.your service);
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

在您的活动中添加广播接收器,
private WakefulBroadcastReceiver IncomingSms = new WakefulBroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        //use your receiver content
     }

这里的"service type"是什么意思? - anand
1
使用以下方式:com.mobile.sms.IncomingSms 这种类型过滤 GCM 消息或其他类型的消息。 - prakash
在registerReceiver中,你提到了this.yourservice,我不太明白这部分的意思... - anand
在您的活动中添加IncomingSms类,this.IncomingSms - prakash
你的IncomingSms类之前是否正常工作?如果之前正常工作,那么只需将整个IncomingSms类复制并粘贴到你的MainActivity类中即可。 - prakash

0
把以下类放在你的MainSmsActivity中,这样你就可以处理你的列表了。
private class IncomingSms extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
       if (intent.getAction().equals("incomingSms")) {
       //your impl here
       }
    }
 }

在您的MainSmsActivity活动的onCreate()中,放置以下代码。
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
...
    IncomingSms broadcastReceiver = new IncomingSms(); // declare it outside so that it should be accessible in onDestroy()
    IntentFilter intentFilter = new IntentFilter("incomingSms");
    registerReceiver(broadcastReceiver , intentFilter);
}

而在 onDestroy() 中放置以下代碼

@Override
protected void onDestroy() {
   if (broadcastReceiver != null) {
      unregisterReceiver(broadcastReceiver);
    }
   super.onDestroy();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接