How to send sms with URL_launcher package with flutter? - flutter

Hello I search a simple example (Android and iOS) to send SMS with this package
https://pub.dartlang.org/packages/url_launcher
In the plugin page I only see how to open sms native app with phone number, but no extra message
sms:<phone number>, e.g. sms:5550101234 Send an SMS message to <phone
number> using the default messaging app

On Android the full sms: URI is supported and you can send a message with a body like that (RFC5724):
_textMe() async {
// Android
const uri = 'sms:+39 348 060 888?body=hello%20there';
if (await canLaunch(uri)) {
await launch(uri);
} else {
// iOS
const uri = 'sms:0039-222-060-888?body=hello%20there';
if (await canLaunch(uri)) {
await launch(uri);
} else {
throw 'Could not launch $uri';
}
}
}
On iOS the official doc says you can only use the number field of The URI.
Instead as Konstantine pointed out, if you use a non standard URI and instead and instead of starting the query string with ? you use & it still works as well. It seems like an undocumented feature.
The sms scheme is used to launch the Messages app. The format for URLs
of this type is “sms:”, where is an optional parameter
that specifies the target phone number of the SMS message. This
parameter can contain the digits 0 through 9 and the plus (+), hyphen
(-), and period (.) characters. The URL string must not include any
message text or other information.
PS. to check the plaform you could use the dart.io library Platform class:
_textMe() async {
if (Platform.isAndroid) {
const uri = 'sms:+39 348 060 888?body=hello%20there';
await launch(uri);
} else if (Platform.isIOS) {
// iOS
const uri = 'sms:0039-222-060-888&body=hello%20there';
await launch(uri);
}
}

you can trying this for android and IOS:
sendMessage() async {
if(Platform.isAndroid){
//FOR Android
url ='sms:+6000000000?body=message';
await launch(url);
}
else if(Platform.isIOS){
//FOR IOS
url ='sms:+6000000000&body=message';
}
}

This answer is for the new people coming in here for answers.
The previous answers are right however they won't work on iOS.
The App might crash on iOS but work on Android.
so to solve that we need to implement sending SMS in the way given below
String? encodeQueryParameters(Map<String, String> params) {
return params.entries
.map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.join('&');
}
Uri smsUri = Uri(
scheme: 'sms',
path: '$phoneNumber',
query: encodeQueryParameters(<String, String>{
'body':
'Hey this is message body'
}),
);
try {
if (await canLaunch(smsUri.toString())) {
await launch(smsUri.toString());
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Some error occured'),
),
);
}

Final updated answer post flutter 3 and latest url launcher package
smsUri = Uri(scheme: 'sms', path: phoneNumber);
try {
print(smsUri.toString());
if (await canLaunchUrl(
smsUri,
)) {
await launchUrl(smsUri);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: const Text('Some error occured'),
),
);
}

Here is the updated answer for sending SMS based on the OS of the device. I have tried the previous answers but I was facing body text issues on IOS devices.
_launchSms() async {
try {
if (Platform.isAndroid) {
String uri = 'sms:$phoneNumber?body=${Uri.encodeComponent("Hello there")}';
await launchUrl(Uri.parse(uri));
} else if (Platform.isIOS) {
String uri = 'sms:$phoneNumber&body=${Uri.encodeComponent("Hello there")}';
await launchUrl(Uri.parse(uri));
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Some error occurred. Please try again!'),
),
);
}
}

Related

Flutter web firebase auth signInWithPhoneNumber showing error "captcha-check-failed" in release mode

I'm facing a problem with Flutter Web Firebase Phone Auth Verification. In debug it is working well and showing me the reCaptcha. But when I host it through GitHub pages in release mode, it shows an error "captcha-check-failed". Even the capcha isn't showing in release mode.
The signInWithPhoneNumber function:
Future<void> loginWithPhoneRequestOTPWeb(
WidgetRef ref,
GlobalKey<FormState> formKey,
String phoneNumber,
) async {
try {
EasyLoading.show();
await FirebaseAuth.instance
.signInWithPhoneNumber(
phoneNumber,
RecaptchaVerifier(
container: 'recaptcha',
size: RecaptchaVerifierSize.compact,
theme: RecaptchaVerifierTheme.dark,
onError: (e) {
print(e);
EasyLoading.showError(e.message!);
return;
},
onExpired: () {
print('Expired');
EasyLoading.showError('Session Expired');
return;
},
onSuccess: () {
EasyLoading.dismiss();
print('Captcha Success');
},
),
)
.then((ConfirmationResult result) {
// update the verificationphone provider
ref.read(sendOtpProvider(formKey).state).update((_) => true);
ref.read(confirmationResultProvider(formKey).state).update((_) => result);
EasyLoading.showSuccess(t!.otpSentSuccessfully);
});
} on FirebaseAuthException catch (e) {
if (e.code == 'invalid-phone-number') {
print('The provided phone number is not valid.');
EasyLoading.showError('The provided phone number is not valid.');
} else if (e.code == 'too-many-requests') {
print(
'You have exceeded the number of attempts allowed for this operation.');
EasyLoading.showError(
'You have exceeded the number of attempts allowed for this operation.');
} else {
print(e.code.toString());
EasyLoading.showError(e.code.toString());
}
} catch (e) {
print(e.toString());
EasyLoading.showError(e.toString());
}
}
I've tried without the RecaptchaVerifier as it is optional parameter.
Error Screenshot:
If I've missed anything please let me know. Thank You :)
Okay, I've figure out my problem. In the firebase authentication section, there is an "Authorized domains" section. Here I've to add my domains. But firebase only takes .com domains. As a result, I used firebase hosting and it is working fine

why do not getting notification in ios with firebase_messaging plugin in flutter?

I'm trying to send notification to the android and Ios device as well.
It's working on android devcice but something fishy with ios token , not getting notification on ios devices , I have enabled background notification for ios. In fact it was working before few days ago but suddenly stopped working on ios device. I have updated firebase_messaging plugin but still not getting notification, also visited firebase_messaging issue ,this as well .
I think there is something wrong with my ios token , because I have tested from pushtry website and throw error saying Please check device token , but testing with android token , not getting any errors. so I could say that ios token is not generating properly.
I did everything what I could do but every time got disappointed.
Here's my test Code:
class PUSHTest extends StatefulWidget {
const PUSHTest({Key key}) : super(key: key);
#override
_PUSHTestState createState() => _PUSHTestState();
}
class _PUSHTestState extends State<PUSHTest> {
String token = '';
var serverKey =
'AAAAL4uGYoY:.............................';
#override
void initState() {
super.initState();
getToken();
showAlertNotification();
}
getToken() async {
String t = await FirebaseMessaging.instance.getToken();
print(
"FCM TOKEN: $t");
setState(() {
token = t;
});
}
showAlertNotification() {
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE11${message.data}");
}
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
AppleNotification ios = message.notification?.apple;
print("ios ios ios:$ios");
if (notification != null && android != null && !kIsWeb) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE22${message.data}");
}
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE33${message.data}");
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => sendNotification(),
child: Text("SEND NOTIFICATION"),
),
),
);
}
// My FCM Payload To send notification to the device:
sendNotification() async {
print("send notification button pressed");
try {
http.Response response = await http.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverKey',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
'body': 'this is a body',
'title': 'this is a title',
"content_available": true
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
},
'to': token,
},
),
);
if (response.statusCode == 200) {
print("SENT NOTIFICATION TO THE DEVICE :$token");
Fluttertoast.showToast(msg: "SENT NOTIFICATION TO THE DEVICE :$token");
} else {
print("error push notification");
Fluttertoast.showToast(msg: "error push notification");
}
} catch (e) {
print("error push notification");
}
}
}
Okay, finally I found my stupidity, what I exactly did. actually It was 2 major mistakes.
firstly, I used permission_hander and haven't ask for permission for the notification because I was thinking it will be auto ask , when I added remote notification to the plistfile.
secondly, My huge stupidity, I have created 2 firebase project , added configuration file for android (google-service.json) from the another and ios(google-service.plist) from the other projects. and added server-key to the backend from one of them. Nothing wrong with FCM token.
that's why it were working for android only.
Now I have recognised my silliness and deleted duplicate firebase project one, and added configuration file from the original one and updated my server-key to my backend. and also asking permission for notification using permission_handler. That's all.

Send sms directly from flutter app on click in adnroid and ios,

I m trying to send SMS directly from my flutter app but I m not finding good package, I try flutter SMS but its open SMS default app or I also try telephony its send SMS only to android
Try "**url_launcher**" flutter plugin, using this you can directly call and send sms from the app you built.
//you can use it using this method as reference
// this is for calling to a required number
Future _callContact(BuildContext context, String number) async {
final url = 'tel:$number';
if (await canLaunch(url)) {
await launch(url);
}
else {
const snackbar = SnackBar(content: Text('Can\'t make a call'));
Scaffold.of(context).showSnackBar(snackbar);
}
}
// this is for sms
Future _smsContact(BuildContext context, String number) async {
final url = 'sms:$number';
if (await canLaunch(url)) {
await launch(url);
} else {
const snackbar = SnackBar(content: Text('Can\'t make a call'));
Scaffold.of(context).showSnackBar(snackbar);
}
}

flutter dio or http doesn't work on some emulators

I cloned my code on different PCs. It works on some of them and doesn't work on the others.
I have a login screen with a mobile number. when I send a request nothing happens and it doesn't give any responses. but that exact same code works fine on other pc and send verification code. I don't know what is the difference that makes it not work on my pc.
Future<Response> init(String mobile) async {
Response response;
try {
response = await Dio()
.post(URLs.BASE_URL + URLs.INIT, data: InitModel(mobile: mobile));
} on DioError catch (e) {}
return response;
}
and here I call it:
void onPressed() {
var text = tEC?.text?.trim();
init("0$text").then((response) {
setState(() {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => ConfirmCode(
mobileNum: tEC.text,
message: response.data['message'],
),
),
);
});
});
}
It was because of the emulator's proxy setting. I change it from "android studio proxy setting" to "no proxy".

How to launch other android apps using the flutter app

I have used the following method as specified in the documentation.
Future<void> launchUniversalLink(String url) async {
if (await canLaunch(url)) {
final bool nativeAppLaunchSuccess = await launch(url, forceSafariVC: false, universalLinksOnly: true);
print(nativeAppLaunchSuccess);
}else {
print('launch not successfull');
}
}
if I give URL = 'https://www.WhatsApp.com'
print(nativeAppLaunchSuccess); output ==> true
but still the app launches in the browser.
can anyone help me with this problem
Oh I'm sorry. This is my mistake.
Please use 'device_apps' flutter package and usage is below.
And here is a how to know app package name.
https://www.techmesto.com/find-android-app-package-name/
In ios, you know other app's custom Url schema that officially opened.
But usually we can not know that url.
So below ios code is executed, it will open appstore page and need to push 'open' button.
if (Platform.isAndroid) {
if (await DeviceApps.isAppInstalled('com.nbt.moves') ==
true) {
DeviceApps.openApp('com.nbt.moves');
}
} else {
const url =
'https://apps.apple.com/kr/app/%EC%BA%90%EC%8B%9C%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%85%9D%EC%97%85/id1400703652?uo=4';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}