parent
f68c750b4b
commit
d4b2579f90
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Flutter",
|
"name": "Example App",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"program": "example/lib/main.dart"
|
"program": "example/lib/main.dart"
|
||||||
|
13
README.md
13
README.md
@ -56,6 +56,19 @@ List<String> recipents = ["1234567890", "5556787676"];
|
|||||||
_sendSMS(message, recipents);
|
_sendSMS(message, recipents);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
On Android, you can skip the additional dialog with the sendDirect parameter.
|
||||||
|
|
||||||
|
``` dart
|
||||||
|
String message = "This is a test message!";
|
||||||
|
List<String> recipents = ["1234567890", "5556787676"];
|
||||||
|
|
||||||
|
String _result = await sendSMS(message: message, recipients: recipents, sendDirect: true)
|
||||||
|
.catchError((onError) {
|
||||||
|
print(onError);
|
||||||
|
});
|
||||||
|
print(_result);
|
||||||
|
```
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
iOS SMS | Android MMS
|
iOS SMS | Android MMS
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
package com.example.flutter_sms
|
package com.example.flutter_sms
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import io.flutter.plugin.common.MethodCall
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
|
||||||
import io.flutter.plugin.common.MethodChannel.Result
|
|
||||||
import io.flutter.plugin.common.PluginRegistry.Registrar
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.net.Uri
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.telephony.SmsManager
|
||||||
|
import android.util.Log
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||||
import io.flutter.plugin.common.BinaryMessenger
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
|
import io.flutter.plugin.common.MethodCall
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||||
|
import io.flutter.plugin.common.MethodChannel.Result
|
||||||
|
import io.flutter.plugin.common.PluginRegistry.Registrar
|
||||||
|
|
||||||
|
|
||||||
class FlutterSmsPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
|
class FlutterSmsPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
|
||||||
private lateinit var mChannel: MethodChannel
|
private lateinit var mChannel: MethodChannel
|
||||||
@ -76,9 +80,10 @@ class FlutterSmsPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
|
|||||||
"A device may be unable to send messages if it does not support messaging or if it is not currently configured to send messages. This only applies to the ability to send text messages via iMessage, SMS, and MMS.")
|
"A device may be unable to send messages if it does not support messaging or if it is not currently configured to send messages. This only applies to the ability to send text messages via iMessage, SMS, and MMS.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val message = call.argument<String?>("message")
|
val message = call.argument<String?>("message") ?: ""
|
||||||
val recipients = call.argument<String?>("recipients")
|
val recipients = call.argument<String?>("recipients") ?: ""
|
||||||
sendSMS(result, recipients, message!!)
|
val sendDirect = call.argument<Boolean?>("sendDirect") ?: false
|
||||||
|
sendSMS(result, recipients, message!!, sendDirect)
|
||||||
}
|
}
|
||||||
"canSendSMS" -> result.success(canSendSMS())
|
"canSendSMS" -> result.success(canSendSMS())
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
@ -95,7 +100,35 @@ class FlutterSmsPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
|
|||||||
return !(activityInfo == null || !activityInfo.exported)
|
return !(activityInfo == null || !activityInfo.exported)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendSMS(result: Result, phones: String?, message: String?) {
|
private fun sendSMS(result: Result, phones: String, message: String, sendDirect: Boolean) {
|
||||||
|
if (sendDirect) {
|
||||||
|
sendSMSDirect(result, phones, message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendSMSDialog(result, phones, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendSMSDirect(result: Result, phones: String, message: String) {
|
||||||
|
// SmsManager is android.telephony
|
||||||
|
val sentIntent = PendingIntent.getBroadcast(activity, 0, Intent("SMS_SENT_ACTION"), PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
val mSmsManager = SmsManager.getDefault()
|
||||||
|
val numbers = phones.split(";")
|
||||||
|
|
||||||
|
for (num in numbers) {
|
||||||
|
Log.d("Flutter SMS", "msg.length() : " + message.toByteArray().size)
|
||||||
|
if (message.toByteArray().size > 80) {
|
||||||
|
val partMessage = mSmsManager.divideMessage(message)
|
||||||
|
mSmsManager.sendMultipartTextMessage(num, null, partMessage, null, null)
|
||||||
|
} else {
|
||||||
|
mSmsManager.sendTextMessage(num, null, message, sentIntent, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.success("SMS Sent!")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendSMSDialog(result: Result, phones: String, message: String) {
|
||||||
val intent = Intent(Intent.ACTION_SENDTO)
|
val intent = Intent(Intent.ACTION_SENDTO)
|
||||||
intent.data = Uri.parse("smsto:$phones")
|
intent.data = Uri.parse("smsto:$phones")
|
||||||
intent.putExtra("sms_body", message)
|
intent.putExtra("sms_body", message)
|
||||||
|
@ -1 +1 @@
|
|||||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_sms","path":"/Users/rodydavis/Developer/GitHub/plugins/packages/flutter_sms/","dependencies":["url_launcher"]},{"name":"url_launcher","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.12/","dependencies":[]}],"android":[{"name":"flutter_sms","path":"/Users/rodydavis/Developer/GitHub/plugins/packages/flutter_sms/","dependencies":["url_launcher"]},{"name":"url_launcher","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.12/","dependencies":[]}],"macos":[{"name":"url_launcher_macos","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-2.0.2/","dependencies":[]}],"linux":[{"name":"url_launcher_linux","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-2.0.2/","dependencies":[]}],"windows":[{"name":"url_launcher_windows","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-2.0.2/","dependencies":[]}],"web":[{"name":"flutter_sms","path":"/Users/rodydavis/Developer/GitHub/plugins/packages/flutter_sms/","dependencies":[]},{"name":"url_launcher_web","path":"/usr/local/Caskroom/flutter/1.2.1/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-2.0.4/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_sms","dependencies":["url_launcher"]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-09-27 10:56:42.626795","version":"2.5.1"}
|
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_sms","path":"/Users/dsilk/Development/flutter/packages/flutter_sms/","dependencies":[]},{"name":"url_launcher_ios","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_ios-6.0.15/","dependencies":[]}],"android":[{"name":"flutter_sms","path":"/Users/dsilk/Development/flutter/packages/flutter_sms/","dependencies":[]},{"name":"url_launcher_android","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_android-6.0.15/","dependencies":[]}],"macos":[{"name":"url_launcher_macos","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-3.0.0/","dependencies":[]}],"linux":[{"name":"url_launcher_linux","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-3.0.0/","dependencies":[]}],"windows":[{"name":"url_launcher_windows","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-3.0.0/","dependencies":[]}],"web":[{"name":"flutter_sms","path":"/Users/dsilk/Development/flutter/packages/flutter_sms/","dependencies":[]},{"name":"url_launcher_web","path":"/Users/dsilk/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-2.0.8/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_sms","dependencies":["url_launcher"]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2022-02-14 16:50:47.982162","version":"2.10.1"}
|
@ -5,8 +5,11 @@
|
|||||||
In most cases you can leave this as-is, but you if you want to provide
|
In most cases you can leave this as-is, but you if you want to provide
|
||||||
additional functionality it is fine to subclass or reimplement
|
additional functionality it is fine to subclass or reimplement
|
||||||
FlutterApplication and put your custom class here. -->
|
FlutterApplication and put your custom class here. -->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.SEND_SMS"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="io.flutter.app.FlutterApplication"
|
android:name="${applicationName}"
|
||||||
android:label="example"
|
android:label="example"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
@ -15,6 +18,7 @@
|
|||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
|
android:exported="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.6.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
@ -15,6 +15,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
String? _message, body;
|
String? _message, body;
|
||||||
String _canSendSMSMessage = 'Check is not run.';
|
String _canSendSMSMessage = 'Check is not run.';
|
||||||
List<String> people = [];
|
List<String> people = [];
|
||||||
|
bool sendDirect = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -30,7 +31,10 @@ class _MyAppState extends State<MyApp> {
|
|||||||
Future<void> _sendSMS(List<String> recipients) async {
|
Future<void> _sendSMS(List<String> recipients) async {
|
||||||
try {
|
try {
|
||||||
String _result = await sendSMS(
|
String _result = await sendSMS(
|
||||||
message: _controllerMessage.text, recipients: recipients);
|
message: _controllerMessage.text,
|
||||||
|
recipients: recipients,
|
||||||
|
sendDirect: sendDirect,
|
||||||
|
);
|
||||||
setState(() => _message = _result);
|
setState(() => _message = _result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setState(() => _message = error.toString());
|
setState(() => _message = error.toString());
|
||||||
@ -89,7 +93,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (people == null || people.isEmpty)
|
if (people.isEmpty)
|
||||||
const SizedBox(height: 0)
|
const SizedBox(height: 0)
|
||||||
else
|
else
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -144,12 +148,21 @@ class _MyAppState extends State<MyApp> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Send Direct'),
|
||||||
|
subtitle: const Text('Should we skip the additional dialog?'),
|
||||||
|
value: sendDirect,
|
||||||
|
onChanged: (bool newValue) {
|
||||||
|
setState(() {
|
||||||
|
sendDirect = newValue;
|
||||||
|
});
|
||||||
|
}),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: MaterialStateProperty.resolveWith(
|
backgroundColor: MaterialStateProperty.resolveWith(
|
||||||
(states) => Theme.of(context).accentColor),
|
(states) => Theme.of(context).colorScheme.secondary),
|
||||||
padding: MaterialStateProperty.resolveWith(
|
padding: MaterialStateProperty.resolveWith(
|
||||||
(states) => const EdgeInsets.symmetric(vertical: 16)),
|
(states) => const EdgeInsets.symmetric(vertical: 16)),
|
||||||
),
|
),
|
||||||
@ -158,7 +171,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'SEND',
|
'SEND',
|
||||||
style: Theme.of(context).accentTextTheme.button,
|
style: Theme.of(context).textTheme.displayMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
import 'src/flutter_sms_platform.dart';
|
import 'src/flutter_sms_platform.dart';
|
||||||
|
|
||||||
/// Open SMS Dialog on iOS/Android/Web
|
/// Open SMS Dialog on iOS/Android/Web
|
||||||
Future<String> sendSMS({
|
Future<String> sendSMS({
|
||||||
required String message,
|
required String message,
|
||||||
required List<String> recipients,
|
required List<String> recipients,
|
||||||
|
required bool sendDirect,
|
||||||
}) =>
|
}) =>
|
||||||
FlutterSmsPlatform.instance
|
FlutterSmsPlatform.instance.sendSMS(
|
||||||
.sendSMS(message: message, recipients: recipients);
|
message: message,
|
||||||
|
recipients: recipients,
|
||||||
|
sendDirect: sendDirect,
|
||||||
|
);
|
||||||
|
|
||||||
/// Launch SMS Url Scheme on all platforms
|
/// Launch SMS Url Scheme on all platforms
|
||||||
Future<bool> launchSms({
|
Future<bool> launchSms({
|
||||||
|
@ -15,6 +15,7 @@ class FlutterSmsPlugin extends FlutterSmsPlatform {
|
|||||||
Future<String> sendSMS({
|
Future<String> sendSMS({
|
||||||
required String message,
|
required String message,
|
||||||
required List<String> recipients,
|
required List<String> recipients,
|
||||||
|
bool sendDirect = false,
|
||||||
}) async {
|
}) async {
|
||||||
bool _messageSent =
|
bool _messageSent =
|
||||||
await FlutterSmsPlatform.instance.launchSmsMulti(recipients, message);
|
await FlutterSmsPlatform.instance.launchSmsMulti(recipients, message);
|
||||||
|
@ -32,9 +32,12 @@ class FlutterSmsPlatform extends PlatformInterface {
|
|||||||
_instance = instance;
|
_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
Future<String> sendSMS({
|
Future<String> sendSMS({
|
||||||
required String message,
|
required String message,
|
||||||
required List<String> recipients,
|
required List<String> recipients,
|
||||||
|
required bool sendDirect,
|
||||||
}) {
|
}) {
|
||||||
final mapData = <dynamic, dynamic>{};
|
final mapData = <dynamic, dynamic>{};
|
||||||
mapData['message'] = message;
|
mapData['message'] = message;
|
||||||
@ -46,6 +49,7 @@ class FlutterSmsPlatform extends PlatformInterface {
|
|||||||
} else {
|
} else {
|
||||||
String _phones = recipients.join(';');
|
String _phones = recipients.join(';');
|
||||||
mapData['recipients'] = _phones;
|
mapData['recipients'] = _phones;
|
||||||
|
mapData['sendDirect'] = sendDirect;
|
||||||
return _channel
|
return _channel
|
||||||
.invokeMethod<String>('sendSMS', mapData)
|
.invokeMethod<String>('sendSMS', mapData)
|
||||||
.then((value) => value ?? 'Error sending sms');
|
.then((value) => value ?? 'Error sending sms');
|
||||||
|
Loading…
Reference in New Issue
Block a user