问题
In my application I am sending a port SMS to the mobile. And when the message is recieved I need to perform some task in my activity and update the UI.
Manifest Declaration of receiver
<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>
Receiver class
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() + "\n";
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);
}
}
}
Method in activity
public void msgReceived(String msgContent)
{
if(msgContent.equalsIgnoreCase(etMobile.getText().toString().trim())){
showToast("Number Verified");
}else{
showToast("Sorry wrong number. Input your number again.");
}
}
The exception I get
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)
at android.app.ActivityThread.access$1700(ActivityThread.java:145)
How can I get activity context in reciever to call my method??
回答1:
I was able to solve it by declaring receiver programmatically:
In the activity befor sending the message
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);
}
In receiver class
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() + "\n";
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
}
}
}
Unregister the receiver
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(smsReceiver);
}
回答2:
The error you get is that you are wrongly casting a android.app.ReceiverRestrictedContext
to a com.vfi.VerifyActivity
.
If you want to achieve what you want to do simply start your activity by giving it some extra information.
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() + "\n";
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);
}
}
}
And in your other class simply retrieve your message this way :
Intent intent = getIntent();
String message = intent.getStringExtra("message_received");
That's it.
Hope this help !
回答3:
The Context
that your BinarySMSReceiver
is passed in onReceive
is not an Activity - it is the Context in which the receiver is running. To start an Activity, you need to use context.startActivity(Intent)
and pass any additional data to the Activity using the Intent.
回答4:
that ((VerifyActivity)context).msgReceived(msg);
that's your mistake.
Why are you assuming that this context is your activity?
The best way (without 3rd party libraries) to do this is to send a local broadcast.
On this other answer I gave a general idea on how to use LocalBroadcast
Best practice to launch AsyncTask from custom view
if you're Ok using 3rd party libraries I suggest you check Otto
from Square
回答5:
Your BroadcastReceiver doesn't know anything about any activity by default. You will have to give the context to it, for example in your constructor when you create the broadcastReceiver.
private Activity activity;
public BroadcastReceiver(Activity activity) {
super();
this.activity = activity;
}
In you onReceive method you will now be able to use your activity in whatever way you like.
来源:https://stackoverflow.com/questions/30639756/call-activity-method-from-broadcast-receiver-android