moving to flutter comm

This commit is contained in:
Rody Davis 2019-05-24 14:20:18 -04:00
parent 193d21a352
commit 276f97427d
42 changed files with 292 additions and 260 deletions

View File

@ -1,3 +1,36 @@
## 1.0.1
* Android result added
## 1.0.0 * 04.29.2019
* Reduce minSdkVersion to 16
* Fix crash on android when `recipients` is empty (substring on empty string)
* Add `canSendSMS` API
- Checks if device is SMS capable (iOS and Android)
- Checks if `smsto:` Intent is resolved and resulting activity exported (Android)
* sendSMS: Return error when device is not SMS capable (Android)
* Remove unused AndroidX dependency
* Use Intent.ACTION_SENDTO and Intent.EXTRA_TEXT to increase message app support coverage
## 0.2.0 * 04.06.2019
* Updating example to be desktop aware
## 0.1.0
* Fix for Android Multiple People
* Fixes Issues #8 and #4
## 0.0.5
* Removed SMS Permissions on Android
## 0.0.4
* Bug Fix Send Result
* Added Can Send Text
## 0.0.3
* Bug Fix for iOS Simulator Error

View File

@ -1,3 +1,59 @@
[![Buy Me A Coffee](https://img.shields.io/badge/Donate-Buy%20Me%20A%20Coffee-yellow.svg)](https://www.buymeacoffee.com/rodydavis)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WSH3GVC49GNNJ)
# flutter_sms
<h3 align="center">The <i>flutter_sms<i> plugin was moved to <a href='https://github.com/AppleEducate/plugins'>plugins/packages/flutter_sms</a></h3>
![alt-text-1](https://github.com/AppleEducate/flutter_sms/blob/master/screenshots/ios_blank.PNG)
## Description
Flutter Plugin for sending SMS and MMS on Android and iOS. If you send to more than one person it will send as MMS. On the iOS if the number is an iPhone and iMessage is enabled it will send as an iMessage.
## How To Use
You can send multiple ways:
1. Message and No People
2. People and No Message
3. Message and People
This will populate the correct fields.
## Example
Make sure to Install and Import the Package.
``` dart
import 'package:flutter_sms/flutter_sms.dart';
```
Create a function for sending messages.
``` dart
void _sendSMS(String message, List<String> recipents) async {
String _result = await FlutterSms
.sendSMS(message: message, recipients: recipents)
.catchError((onError) {
print(onError);
});
print(_result);
}
```
You can quickly send the message with this function.
``` dart
String message = "This is a test message!";
List<String> recipents = ["1234567890", "5556787676"];
_sendSMS(message, recipents);
```
## Screenshots
iOS SMS | Android MMS
:-------------------------:|:-------------------------:
![alt-text-1](https://github.com/AppleEducate/flutter_sms/blob/master/screenshots/ios_sms.PNG) | ![alt-text-2](https://github.com/AppleEducate/flutter_sms/blob/master/screenshots/android_mms.png)
You can find other [screenshots here](https://github.com/AppleEducate/flutter_sms/tree/master/screenshots).

0
android/.classpath Normal file → Executable file
View File

0
android/.gitignore vendored Normal file → Executable file
View File

0
android/.idea/.name Normal file → Executable file
View File

BIN
android/.idea/caches/build_file_checksums.ser Normal file → Executable file

Binary file not shown.

0
android/.idea/codeStyles/Project.xml Normal file → Executable file
View File

3
android/.idea/gradle.xml Normal file → Executable file
View File

@ -3,6 +3,9 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT" />
</compositeConfiguration>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">

14
android/.idea/misc.xml Normal file → Executable file
View File

@ -5,22 +5,32 @@
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="5">
<list size="10">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
</list>
</value>
</option>

1
android/.idea/modules.xml Normal file → Executable file
View File

@ -3,6 +3,7 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/flutter_sms.iml" filepath="$PROJECT_DIR$/flutter_sms.iml" />
<module fileurl="file://$PROJECT_DIR$/flutter_sms.iml" filepath="$PROJECT_DIR$/flutter_sms.iml" />
</modules>
</component>
</project>

0
android/.idea/runConfigurations.xml Normal file → Executable file
View File

0
android/.project Normal file → Executable file
View File

2
android/.settings/org.eclipse.buildship.core.prefs Normal file → Executable file
View File

@ -1,2 +1,2 @@
connection.project.dir=
connection.project.dir=../example/android
eclipse.preferences.version=1

View File

@ -1,62 +0,0 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.appleeducate.fluttersms"
minSdkVersion 16
targetSdkVersion 27
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:support-v4:27.1.0'
}

View File

@ -1,39 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.appleeducate.fluttersms">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
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
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_sms"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,13 +0,0 @@
package com.appleeducate.fluttersms;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>

13
android/build.gradle Normal file → Executable file
View File

@ -5,10 +5,11 @@ buildscript {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.2.1'
}
}
@ -16,23 +17,21 @@ rootProject.allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
api 'com.android.support:appcompat-v7:27.1.0'
}

0
android/gradle.properties Normal file → Executable file
View File

0
android/gradle/wrapper/gradle-wrapper.jar vendored Normal file → Executable file
View File

4
android/gradle/wrapper/gradle-wrapper.properties vendored Normal file → Executable file
View File

@ -1,6 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
#Thu Mar 28 08:00:16 EDT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip

0
android/gradlew.bat vendored Normal file → Executable file
View File

0
android/settings.gradle Normal file → Executable file
View File

0
android/src/main/AndroidManifest.xml Normal file → Executable file
View File

View File

@ -1,116 +1,89 @@
package com.appleeducate.fluttersms;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
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.content.Intent;
import android.telephony.SmsManager;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
//import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.VisibleForTesting;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.ArrayList;
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener;
/** FlutterSmsPlugin */
public class FlutterSmsPlugin implements MethodCallHandler {
public class FlutterSmsPlugin implements MethodCallHandler, ActivityResultListener {
private static final int REQUEST_CODE_SEND_SMS = 0315;
Activity activity;
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_sms");
channel.setMethodCallHandler(new FlutterSmsPlugin(registrar.activity()));
channel.setMethodCallHandler(new FlutterSmsPlugin(registrar));
}
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("sendSMS")) {
String message = call.argument("message");
ArrayList<String> recipients = call.argument("recipients");
String smsPermission = "SEND_SMS";
if (!checkPermission(smsPermission)) {
requestPermission(smsPermission);
if (!checkPermission(smsPermission)) {
openSettings();
} else {
sendSMS(recipients, message);
}
} else {
sendSMS(recipients, message);
if (!canSendSMS()) {
result.error(
"device_not_capable",
"The current device is not capable of sending text messages.",
"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;
}
result.success("Sent!");
String message = call.argument("message");
String recipients = call.argument("recipients");
sendSMS(result, recipients, message);
//result.success("SMS Sent!");
} else if (call.method.equals("canSendSMS")) {
result.success(canSendSMS());
} else {
result.notImplemented();
}
}
private FlutterSmsPlugin(Activity activity) {
this.activity = activity;
private FlutterSmsPlugin(Registrar registrar) {
this.activity = registrar.activity();
registrar.addActivityResultListener(this);
}
private void sendSMS(ArrayList<String> phones, String message) {
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("sms_body", message);
sendIntent.setData(Uri.parse("sms:" + phones));
activity.startActivity(sendIntent);
private boolean canSendSMS() {
if (!activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY))
return false;
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:"));
ActivityInfo activityInfo =
intent.resolveActivityInfo(activity.getPackageManager(), intent.getFlags());
if (activityInfo == null || !activityInfo.exported) return false;
return true;
}
private boolean checkPermission(String permission) {
permission = getManifestPermission(permission);
Log.i("SimplePermission", "Checking permission : " + permission);
return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(activity, permission);
private Result result;
private void sendSMS(Result result, String phones, String message) {
this.result = result;
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:" + phones));
intent.putExtra("sms_body", message);
intent.putExtra(Intent.EXTRA_TEXT, message);
// intent.putExtra(Intent.EXTRA_STREAM, attachment);
activity.startActivityForResult(intent, REQUEST_CODE_SEND_SMS);
}
private void requestPermission(String permission) {
permission = getManifestPermission(permission);
Log.i("SimplePermission", "Requesting permission : " + permission);
String[] perm = { permission };
ActivityCompat.requestPermissions(activity, perm, 0);
}
private String getManifestPermission(String permission) {
String res;
switch (permission) {
case "SEND_SMS":
res = Manifest.permission.SEND_SMS;
break;
default:
res = "ERROR";
break;
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_CODE_SEND_SMS && result!=null){
result.success("finished");
result = null;
return true;
}
return res;
}
private void openSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse("package:" + activity.getPackageName()));
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
return false;
}
}

View File

@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
@ -34,11 +34,11 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.appleeducate.fluttersmsexample"
minSdkVersion 16
targetSdkVersion 27
minSdkVersion 18
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -56,6 +56,6 @@ flutter {
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}

View File

@ -6,7 +6,6 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.

View File

@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.3.1'
}
}

View File

@ -1 +1,3 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

View File

@ -19,4 +19,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 7765ea4305eaab0b3dfd384c7de11902aa3195fd
COCOAPODS: 1.5.0
COCOAPODS: 1.5.3

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>

View File

@ -3,7 +3,34 @@ import 'dart:async';
import 'package:flutter_sms/flutter_sms.dart';
void main() => runApp(new MyApp());
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
// The existing imports
// !! Keep your existing impots here !!
/// main is entry point of Flutter application
void main() {
// Desktop platforms aren't a valid platform.
_setTargetPlatformForDesktop();
return runApp(MyApp());
}
/// If the current platform is desktop, override the default platform to
/// a supported platform (iOS for macOS, Android for Linux and Windows).
/// Otherwise, do nothing.
void _setTargetPlatformForDesktop() {
TargetPlatform targetPlatform;
if (Platform.isMacOS) {
targetPlatform = TargetPlatform.iOS;
} else if (Platform.isLinux || Platform.isWindows) {
targetPlatform = TargetPlatform.android;
}
if (targetPlatform != null) {
debugDefaultTargetPlatformOverride = targetPlatform;
}
}
class MyApp extends StatefulWidget {
@override
@ -13,6 +40,7 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
TextEditingController _controllerPeople, _controllerMessage;
String _message, body;
String _canSendSMSMessage = "Check is not run.";
List<String> people = [];
@override
@ -27,9 +55,19 @@ class _MyAppState extends State<MyApp> {
}
void _sendSMS(String message, List<String> recipents) async {
String _result =
await FlutterSms.sendSMS(message: message, recipients: recipents);
setState(() => _message = _result);
try {
String _result =
await FlutterSms.sendSMS(message: message, recipients: recipents);
setState(() => _message = _result);
} catch (error) {
setState(() => _message = error.toString());
}
}
void _canSendSMS() async {
bool _result = await FlutterSms.canSendSMS();
setState(() => _canSendSMSMessage =
_result ? 'This unit can send SMS' : 'This unit cannot send SMS');
}
Widget _phoneTile(String name) {
@ -99,6 +137,7 @@ class _MyAppState extends State<MyApp> {
title: TextField(
controller: _controllerPeople,
decoration: InputDecoration(labelText: "Add Phone Number"),
keyboardType: TextInputType.number,
onChanged: (String value) => setState(() {}),
),
trailing: IconButton(
@ -139,7 +178,7 @@ class _MyAppState extends State<MyApp> {
trailing: IconButton(
icon: Icon(Icons.send),
onPressed: () {
if ((people == null || people.isEmpty) ||
if ((people == null || people.isEmpty) &&
(body == null || body.isEmpty)) {
setState(() =>
_message = "At Least 1 Person or Message Required");
@ -163,6 +202,31 @@ class _MyAppState extends State<MyApp> {
),
],
),
Divider(),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
"Can send SMS",
style: Theme.of(context).textTheme.title,
),
),
Padding(
padding: const EdgeInsets.all(8),
child: Text(_canSendSMSMessage,
style: Theme.of(context).textTheme.body1)),
Padding(
padding:
const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24),
child: RaisedButton(
color: Theme.of(context).accentColor,
padding: EdgeInsets.symmetric(vertical: 16),
child: Text("RUN CHECK",
style: Theme.of(context).accentTextTheme.button),
onPressed: () {
_canSendSMS();
},
),
)
],
),
),

View File

@ -25,12 +25,12 @@ public class SwiftFlutterSmsPlugin: NSObject, FlutterPlugin, UINavigationControl
)
#else
if (MFMessageComposeViewController.canSendText()) {
self.result = result
let controller = MFMessageComposeViewController()
controller.body = _arguments["message"] as? String
controller.recipients = _arguments["recipients"] as? [String]
controller.messageComposeDelegate = self
UIApplication.shared.keyWindow?.rootViewController?.present(controller, animated: true, completion: nil)
// result(message)
} else {
result(FlutterError(
code: "device_not_capable",
@ -40,6 +40,18 @@ public class SwiftFlutterSmsPlugin: NSObject, FlutterPlugin, UINavigationControl
)
}
#endif
case "canSendSMS":
#if targetEnvironment(simulator)
result(false)
#else
if (MFMessageComposeViewController.canSendText()) {
result(true)
} else {
result(false)
}
#endif
default:
result(FlutterMethodNotImplemented)
break

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
@ -6,22 +7,26 @@ import 'package:flutter/services.dart';
class FlutterSms {
static const MethodChannel _channel = const MethodChannel('flutter_sms');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
static Future<String> sendSMS({
@required String message,
@required List<String> recipients,
}) async {
var mapData = Map();
var mapData = Map<dynamic, dynamic>();
mapData["message"] = message;
mapData["recipients"] = recipients;
final String result = await _channel.invokeMethod('sendSMS', mapData);
// String _log = "SMS Message: $message";
// for (var person in recipients) _log += "\nSent: $person";
// final String result = _log;
if (Platform.isIOS) {
mapData["recipients"] = recipients;
final String result = await _channel.invokeMethod('sendSMS', mapData);
return result;
} else {
String _phones = recipients.join(",");
mapData["recipients"] = _phones;
final String result = await _channel.invokeMethod('sendSMS', mapData);
return result;
}
}
static Future<bool> canSendSMS() async {
final bool result = await _channel.invokeMethod('canSendSMS');
return result;
}
}

View File

@ -1,11 +1,12 @@
name: flutter_sms
description: A Flutter plugin to Send SMS and MMS on iOS and Android. If iMessage is enabled it will send as iMessage on iOS. This plugin must be tested on a real device on iOS.
version: 0.0.3
version: 1.0.1
author: Rody Davis <rody.davis.jr@gmail.com>
homepage: https://github.com/AppleEducate/flutter_sms
homepage: https://github.com/AppleEducate/plugins
environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
flutter: ">=0.1.4 <2.0.0"
sdk: ">=2.0.0 <3.0.0"
dependencies:
flutter: