问题
I am trying to listen for any incoming SMS messages on an Android device and then showing a toast in my Flutter app whenever an SMS is received. I am connecting to Flutter through EventChannel and detecting SMS using a BroadcastReceiver. How do I send an events.success(message) whenever my broadcast receiver detects an SMS?
I tried adding the BroadcastReceiver directly inside the EventChannel but that did not work. The flutter SMS package also doesn't seem to work.
This is what my MainActivity looks like:
public class MainActivity extends FlutterActivity{
public static final String STREAM = "com.myapp.thisapp/stream";
public static final String TAG = "THIS IS A MESSAGE: ";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new EventChannel(getFlutterView(), STREAM).setStreamHandler(
new EventChannel.StreamHandler() {
@Override
public void onListen(Object args, final
EventChannel.EventSink events) {
//Send events.success() when SMS received
Log.w(TAG, "adding listener");
}
@Override
public void onCancel(Object args) {
Log.w(TAG, "cancelling listener");
}
}
);
}
}
And this is the code for my BroadcastReceiver:
public class IncomingSmsBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent != null && SMS_RECEIVED.equals(intent.getAction())) {
final SmsMessage smsMessage = extractSmsMessage(intent);
processMessage(context, smsMessage);
}
}
private SmsMessage extractSmsMessage(final Intent intent) {
final Bundle pudsBundle = intent.getExtras();
final Object[] pdus = (Object[]) pudsBundle.get("pdus");
final SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[0]);
return smsMessage;
}
private void processMessage(final Context context, final SmsMessage smsMessage) {
//TODO: Send message to event channel
}
}
Whenever the BroadCastReceiver encounters an SMS, I want the content of the message to be sent to the EventChannel which will send the message text to the Flutter front-end. How do I do this?
回答1:
This is what you should be using in MainActivity, store the Result
public class MainActivity extends FlutterActivity{
public static final String STREAM = "com.myapp.thisapp/stream";
public static final String TAG = "THIS IS A MESSAGE: ";
public Result resultLater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
//store the reference for later access
resultLater = result;
}
});
}
public class IncomingSmsBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent != null && SMS_RECEIVED.equals(intent.getAction())) {
final SmsMessage smsMessage = extractSmsMessage(intent);
processMessage(context, smsMessage);
}
}
private SmsMessage extractSmsMessage(final Intent intent) {
final Bundle pudsBundle = intent.getExtras();
final Object[] pdus = (Object[]) pudsBundle.get("pdus");
final SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[0]);
return smsMessage;
}
}
private void processMessage(final Context context, final SmsMessage smsMessage) {
//here send back result, like this
if(smsMessage.getMessageBody()!=null){
result.success(smsMessage.getMessageBody());
}else{
result.error("Error", "Sms not found", null);
}
}
}
now make the sms broadcast sub class in your main activity and declare below. and access the result when you get the sms. And from your flutter side just make channel call as usual.
Follow the reference for docs sample.
回答2:
Based on your first comment Laksh22 YES it can be possible.
Create a constructor for your 'Activity' like this :
_yourclassnameState() {
platform.setMethodCallHandler(JavaMethodHandler);
}
and then implement a handler for response
Future<dynamic> JavaMethodHandler(MethodCall methodcall) async
{
switch(methodcall.method)
{
case 'SMSRecived':
print('DataRecived is' + methodcall.arguments);
break;
default:
break;
}
}
then in your 'BroadcastReceiver' use this code to call a flutter method :
MethodChannel channel =new MethodChannel(view,CHANNEL);
channel.invokeMethod("SMSRecived",args, new MethodChannel.Result() {
@Override
public void success(Object o) {
System.out.println(o);
}
@Override
public void error(String s, String s1, Object o) {
}
@Override
public void notImplemented() {
}
});
Don't forget about CHANNEL. It should be the same both side.
Don't forget about manifest file.
For receiving SMS while your app is closed use 'ForegroundService'.Unfortunately Flutter dosen't support ForegroundService yet. you should implement it in Java.
来源:https://stackoverflow.com/questions/54088421/sending-android-sms-broadcastreceiver-data-to-flutter-through-eventchannel