从广播接收器android调用活动方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从广播接收器android调用活动方法?相关的知识,希望对你有一定的参考价值。

在我的应用程序中,我正在向移动设备发送端口短信。收到消息后,我需要在我的活动中执行一些任务并更新UI。

显示接收者的宣言

 <receiver android:name="com.vfi.BinarySMSReceiver" >
        <intent-filter android:priority="10" >
            <action android:name="android.intent.action.DATA_SMS_RECEIVED" />

            <data
                android:host="*"
                android:port="9512"
                android:scheme="sms" />
        </intent-filter>
    </receiver>

接收器类

public class BinarySMSReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    SmsMessage[] msgs = null;

    if (null != bundle) {
        String info = "SMS from ";
        String sender = "";
        String msg = "";

        Object[] pdus = (Object[]) bundle.get("pdus");

        msgs = new SmsMessage[pdus.length];
        byte[] data = null;

        for (int i = 0; i < msgs.length; i++) {
            msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
            sender += msgs[i].getOriginatingAddress();
            info += msgs[i].getOriginatingAddress() + "
";

            data = msgs[i].getUserData();

            for (int index = 0; index < data.length; ++index) {
                info += Character.toString((char) data[index]);
                msg += Character.toString((char) data[index]);
            }
        }
        Log.e("SakjsdMS", "akjsdhkas" + msg);
        Log.e("sender", "asdasdasdasdasdasd" + info);

        ((VerifyActivity)context).msgReceived(msg);
    }
}
}

活动方法

public  void msgReceived(String msgContent)
{
    if(msgContent.equalsIgnoreCase(etMobile.getText().toString().trim())){
        showToast("Number Verified");
    }else{
        showToast("Sorry wrong number. Input your number again.");
    }

}

我得到的例外

java.lang.RuntimeException: Unable to start receiver com.vfi.BinarySMSReceiver: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to com.vfi.VerifyActivity
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:2467)
        at android.app.ActivityThread.access$1700(ActivityThread.java:145)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5127)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to com.vfi.VerifyActivity
        at com.vfi.BinarySMSReceiver.onReceive(BinarySMSReceiver.java:46)
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:2460)

在android.app.ActivityThread.access $ 1700(ActivityThread.java:145)

如何在接收器中获取活动上下文来调用我的方法?

答案

我能够通过编程方式声明接收器来解决它:

在发送消息之前的活动中

private void sendSMS() {
    BinarySMSReceiver smsReceiver = null;
    smsReceiver = new BinarySMSReceiver();
    smsReceiver.setActivityHandler(this);
    IntentFilter portIntentFilter = new IntentFilter("android.intent.action.DATA_SMS_RECEIVED");
    portIntentFilter.addDataAuthority("*", "9512");
    portIntentFilter.addDataScheme("sms");
    registerReceiver(smsReceiver, portIntentFilter);



        String messageText = etMobile.getText().toString().trim();
        short SMS_PORT = 9512;
        SmsManager smsManager = SmsManager.getDefault();
        smsManager.sendDataMessage(etMobile.getText().toString().trim(), null, SMS_PORT, messageText.getBytes(), null, null);
}

在接收器类

public class BinarySMSReceiver extends BroadcastReceiver {
VerifyActivity vAct = null;

void setActivityHandler(VerifyActivity main) {
    vAct = main;
}

@Override
public void onReceive(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    SmsMessage[] msgs = null;

    if (null != bundle) {
        String info = "SMS from ";
        String sender = "";
        String msg = "";

        Object[] pdus = (Object[]) bundle.get("pdus");

        msgs = new SmsMessage[pdus.length];
        byte[] data = null;

        for (int i = 0; i < msgs.length; i++) {
            msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
            sender += msgs[i].getOriginatingAddress();
            info += msgs[i].getOriginatingAddress() + "
";

            data = msgs[i].getUserData();

            for (int index = 0; index < data.length; ++index) {
                info += Character.toString((char) data[index]);
                msg += Character.toString((char) data[index]);
            }
        }

        Log.e("message", "receiver " + msg);
        Log.e("sender", "from " + info);
        vAct.msgReceived(msg);  //activity method
    }
}

}

取消注册接收器

 @Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(smsReceiver);
}
另一答案

你得到的错误是你错误地将android.app.ReceiverRestrictedContext投射到com.vfi.VerifyActivity

如果您想实现您想要做的事情,只需通过提供一些额外信息开始您的活动。

public class BinarySMSReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    SmsMessage[] msgs = null;

    if (null != bundle) {
        String info = "SMS from ";
        String sender = "";
        String msg = "";

        Object[] pdus = (Object[]) bundle.get("pdus");

        msgs = new SmsMessage[pdus.length];
        byte[] data = null;

        for (int i = 0; i < msgs.length; i++) {
            msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
            sender += msgs[i].getOriginatingAddress();
            info += msgs[i].getOriginatingAddress() + "
";

            data = msgs[i].getUserData();

            for (int index = 0; index < data.length; ++index) {
                info += Character.toString((char) data[index]);
                msg += Character.toString((char) data[index]);
            }
        }
        Log.e("SakjsdMS", "akjsdhkas" + msg);
        Log.e("sender", "asdasdasdasdasdasd" + info);

        // HERE COMES THE CHANGE
        Intent intent = new Intent(context, YourActivityToLaunch.class);
        intent.putExtra("message_received", msg);
        context.startActivity(intent);
    }
}
}

在您的其他课程中,只需以这种方式检索您的信息:

Intent intent = getIntent();
String message = intent.getStringExtra("message_received");

而已。

希望这有帮助!

另一答案

你的ContextBinarySMSReceiver传递的onReceive不是活动 - 它是Context in which the receiver is running。要启动Activity,您需要使用context.startActivity(Intent)并使用Intent将任何其他数据传递给Activity。

另一答案

((VerifyActivity)context).msgReceived(msg);那是你的错。你为什么假设这个背景是你的活动?

最好的方法(没有第三方库)来发送本地广播。

在另一个答案,我给出了如何使用LocalBroadcast Best practice to launch AsyncTask from custom view的一般概念

如果您使用第三方库,我建议您查看OttoSquare

另一答案

默认情况下,您的BroadcastReceiver对任何活动都不了解。您必须为其提供上下文,例如在创建broadcastReceiver时在构造函数中。

private Activity activity;
public BroadcastReceiver(Activity activity) {
    super();
    this.activity = activity;
}

在on onceceive方法中,您现在可以以任何您喜欢的方式使用您的活动。

以上是关于从广播接收器android调用活动方法?的主要内容,如果未能解决你的问题,请参考以下文章

Android - 在动态注册的广播接收器上出现“无法传递广播”错误

[android] 代码注册广播接收者&利用广播调用服务的方法

Android广播接收器与服务[重复]

在广播接收器中调用活动字符串方法[重复]

Android广播接收器从短信关键字开始

如何从活动中调用片段方法?