I wanna make an app that its main functionality depends on sending SMS. Im using Flutter to make it for both IOS and Android.
In Android, it's possible to send sms in the background if you get user permission. but after searching through the net I couldn't find a way to do it in a flutter. I'm wondering if there is any way to send SMS in the background for Android using flutter.
after all, is there anyway( library, ...) that can sends sms in background. I am attaching the snapshot of the main.dart and MainActivity.kt files.
class SendSms extends StatefulWidget {
const SendSms({super.key});
@override
_SendSmsState createState() => _SendSmsState();
}
class _SendSmsState extends State<SendSms> {
static const platform = MethodChannel('sendSms');
List<String> phoneNumbers = [
"+923000000000",
];
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(const Duration(seconds: 2), (timer) {
sendSms();
});
}
Future<void> sendSms() async {
for (String number in phoneNumbers) {
try {
final String result = await platform.invokeMethod(
'send',
<String, dynamic>{
"phone": number,
"msg": "Automatic message",
},
);
if (kDebugMode) {
print("Message sent to $number: $result");
}
} on PlatformException catch (e) {
if (kDebugMode) {
print("Failed to send SMS to $number: ${e.toString()}");
}
}
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("SMS App")),
body: const Center(
child: Text("Sending SMS every 2 seconds..."),
),
);
}
}
MainActivity.kt
class MainActivity : FlutterActivity() {
private val CHANNEL = "sendSms"
private val SMS_PERMISSION_CODE = 1
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
print("Method call: ${call.method}");
if (call.method == "send") {
val phone: String? = call.argument("phone")
val msg: String? = call.argument("msg")
if (!phone.isNullOrEmpty() && !msg.isNullOrEmpty()) {
if (checkSmsPermission()) {
sendSMS(phone, msg, result)
} else {
requestSmsPermission(result)
}
} else {
result.error("INVALID_ARGUMENTS","Phone number or message is null", null)
}
} else {
result.notImplemented()
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == SMS_PERMISSION_CODE) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Log.d("SMS_PERMISSION", "Permission granted")
} else {
Log.e("SMS_PERMISSION", "Permission denied")
}
}
}
private fun checkSmsPermission(): Boolean {
return ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
}
private fun requestSmsPermission(result: MethodChannel.Result) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.SEND_SMS), SMS_PERMISSION_CODE)
result.error("PERMISSION_DENIED", "SMS permission is required", null)
}
private fun sendSMS(phoneNo: String, msg: String, result: MethodChannel.Result) {
try {
val smsManager: SmsManager = SmsManager.getDefault()
smsManager.sendTextMessage(phoneNo, null, msg, null, null)
result.success("SMS Sent")
} catch (e: Exception) {
Log.e("SMS_ERROR", "Failed to send SMS", e)
result.error("ERR", "Sms Not Sent", e.localizedMessage)
}
}
}
I wanna make an app that its main functionality depends on sending SMS. Im using Flutter to make it for both IOS and Android.
In Android, it's possible to send sms in the background if you get user permission. but after searching through the net I couldn't find a way to do it in a flutter. I'm wondering if there is any way to send SMS in the background for Android using flutter.
after all, is there anyway( library, ...) that can sends sms in background. I am attaching the snapshot of the main.dart and MainActivity.kt files.
class SendSms extends StatefulWidget {
const SendSms({super.key});
@override
_SendSmsState createState() => _SendSmsState();
}
class _SendSmsState extends State<SendSms> {
static const platform = MethodChannel('sendSms');
List<String> phoneNumbers = [
"+923000000000",
];
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(const Duration(seconds: 2), (timer) {
sendSms();
});
}
Future<void> sendSms() async {
for (String number in phoneNumbers) {
try {
final String result = await platform.invokeMethod(
'send',
<String, dynamic>{
"phone": number,
"msg": "Automatic message",
},
);
if (kDebugMode) {
print("Message sent to $number: $result");
}
} on PlatformException catch (e) {
if (kDebugMode) {
print("Failed to send SMS to $number: ${e.toString()}");
}
}
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("SMS App")),
body: const Center(
child: Text("Sending SMS every 2 seconds..."),
),
);
}
}
MainActivity.kt
class MainActivity : FlutterActivity() {
private val CHANNEL = "sendSms"
private val SMS_PERMISSION_CODE = 1
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
print("Method call: ${call.method}");
if (call.method == "send") {
val phone: String? = call.argument("phone")
val msg: String? = call.argument("msg")
if (!phone.isNullOrEmpty() && !msg.isNullOrEmpty()) {
if (checkSmsPermission()) {
sendSMS(phone, msg, result)
} else {
requestSmsPermission(result)
}
} else {
result.error("INVALID_ARGUMENTS","Phone number or message is null", null)
}
} else {
result.notImplemented()
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == SMS_PERMISSION_CODE) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Log.d("SMS_PERMISSION", "Permission granted")
} else {
Log.e("SMS_PERMISSION", "Permission denied")
}
}
}
private fun checkSmsPermission(): Boolean {
return ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
}
private fun requestSmsPermission(result: MethodChannel.Result) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.SEND_SMS), SMS_PERMISSION_CODE)
result.error("PERMISSION_DENIED", "SMS permission is required", null)
}
private fun sendSMS(phoneNo: String, msg: String, result: MethodChannel.Result) {
try {
val smsManager: SmsManager = SmsManager.getDefault()
smsManager.sendTextMessage(phoneNo, null, msg, null, null)
result.success("SMS Sent")
} catch (e: Exception) {
Log.e("SMS_ERROR", "Failed to send SMS", e)
result.error("ERR", "Sms Not Sent", e.localizedMessage)
}
}
}
Share
Improve this question
edited Mar 14 at 15:24
Frank van Puffelen
601k85 gold badges890 silver badges860 bronze badges
Recognized by Mobile Development Collective
asked Mar 14 at 5:50
Muhammad OsamaMuhammad Osama
435 bronze badges
1 Answer
Reset to default -1I also developed an application that listens to SMS. I did a lot of research but I couldn't solve this with Flutter. And I did it with Kotlin.
If the application is going to be open all the time, you need to get permission from the user to ignore battery optimization.
Don't fet to get permission for SMS too. (These may be sensitive permissions --> https://support.google/googleplay/android-developer/answer/9888170?hl=en) If you want to review it, you can look here ->> https://github/dcicek/read_sms