I have been trying to write a simple flutter code and trying to send SMS using telephony. Sending Sms via the default SMS app works (telephony.sendSmsByDefaultApp()) but not sending directly from the app.
My code is as follows:
import 'package:flutter/material.dart';
import 'package:telephony/telephony.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
sendSMS();
},
child: Text("Send SMS"),
),
),
),
);
}
void sendSMS() async {
final Telephony telephony = Telephony.instance;
bool? permissionsGranted = await telephony.requestPhoneAndSmsPermissions;
print(permissionsGranted);
await telephony.sendSms(to: "+92xxxxxxxxxx", message: "Hello, this is a test message.");
print("SMS Sent");
}
}
I have added the following required permissions
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
can you try the code
https://d7networks.com/docs/Messages/Send_Message/
we need to have an account on https://d7networks.com/ platform.
Have you tried changing that onPressed() function in the ElevatedButton(), to an async function:
ElevatedButton(
onPressed: () async {
await sendSMS();
},
child: Text("Send SMS"),
)
And then change your sendSMS() function to return a Future<void>, instead of void:
Future<void> sendSMS() async {
final Telephony telephony = Telephony.instance;
bool? permissionsGranted = await telephony.requestPhoneAndSmsPermissions;
print(permissionsGranted);
await telephony.sendSms(to: "+92xxxxxxxxxx", message: "Hello, this is a test message.");
print("SMS Sent");
}
}
Related
I made an application like this:
To renew the SMS, it is necessary to click the button at the bottom right. If there is no SMS permission, it asks for permission. This is happening on my emulator but not asking for permission on my physical phone. As it cannot ask for permission, I cannot see the SMS. Why could this be? How can I solve it?
Thanks in advance for your help.
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_sms_inbox/flutter_sms_inbox.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(Main());
SmsQuery query = SmsQuery();
}
class Main extends StatefulWidget {
const Main({Key? key}) : super(key: key);
#override
State<Main> createState() => _MainState();
}
class _MainState extends State<Main> {
final SmsQuery _query = SmsQuery();
List<SmsMessage> _messages = [];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
shrinkWrap: true,
itemCount: _messages.length,
itemBuilder: (BuildContext context, int i) {
var message = _messages[i];
return ListTile(
title: Text('${message.sender} [${message.date}]'),
subtitle: Text('${message.body}'),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
var permission = await Permission.sms.status;
if (permission.isGranted) {
final messages = await _query.querySms(
kinds: [SmsQueryKind.inbox, SmsQueryKind.sent],
// address: '+254712345789',
count: 10,
);
debugPrint('sms inbox messages: ${messages.length}');
setState(() => _messages = messages);
} else {
await Permission.sms.request();
}
},
child: const Icon(Icons.refresh),
),
),
);
}
}
android/app/src/profile/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.teen_message">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
</manifest>
I am currently working on Notification Feature so when a new Update is availible the User gets a Dialog where he can choose to Update or not. I'm doing it with Firebase Remote Config where i have a Parameter called "force_update_current_version" where i then add the Value for the Version for checking. But I do get following errors.
Thanks for your help and i wish you a healty start into the new Year.
Main.dart Code
import 'checkUpdate.dart';
#override
void initState() {
try {
versionCheck(**context**);
} catch (e) {
print(e);
}
**super**.initState();
}
context error: Undefined name 'context'.
Try correcting the name to one that is defined, or defining the name.
super error: Invalid context for 'super' invocation.
checkUpdate.dart Code
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:package_info/package_info.dart';
import 'package:flutter/cupertino.dart';
const APP_STORE_URL = 'https://apps.apple.com/us/app/appname/idAPP-ID';
const PLAY_STORE_URL =
'https://play.google.com/store/apps/details?id=APP-ID';
versionCheck(context) async {
//Get Current installed version of app
final PackageInfo info = await PackageInfo.fromPlatform();
double currentVersion = double.parse(info.version.trim().replaceAll(".", ""));
//Get Latest version info from firebase config
final RemoteConfig remoteConfig = await RemoteConfig.instance;
try {
// Using default duration to force fetching from remote server.
await remoteConfig.fetch(expiration: const Duration(seconds: 0));
await remoteConfig.activateFetched();
remoteConfig.getString('force_update_current_version');
double newVersion = double.parse(remoteConfig
.getString('force_update_current_version')
.trim()
.replaceAll(".", ""));
if (newVersion > currentVersion) {
_showVersionDialog(context);
}
} on FetchThrottledException catch (exception) {
// Fetch throttled.
print(exception);
} catch (exception) {
print('Unable to fetch remote config. Cached or default values will be '
'used');
}
}
//Show Dialog to force user to update
_showVersionDialog(context) async {
await showDialog<String>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
String title = "New Update Available";
String message =
"There is a newer version of app available please update it now.";
String btnLabel = "Update Now";
String btnLabelCancel = "Later";
return Platform.isIOS
? new CupertinoAlertDialog(
title: Text(title),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text(btnLabel),
onPressed: () => _launchURL(**Config**.APP_STORE_URL),
),
FlatButton(
child: Text(btnLabelCancel),
onPressed: () => Navigator.pop(context),
),
],
)
: new AlertDialog(
title: Text(title),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text(btnLabel),
onPressed: () => _launchURL(**Config**.PLAY_STORE_URL),
),
FlatButton(
child: Text(btnLabelCancel),
onPressed: () => Navigator.pop(context),
),
],
);
},
);
}
_launchURL(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
Config Error for App and Play Store: Undefined name 'Config'.
Try correcting the name to one that is defined, or defining the name.
In checkUpdate.dart we need to import the firebase_remote_config package that exposes the RemoteConfig class:
import 'package:firebase_remote_config/firebase_remote_config.dart';
Make sure to install it before.
The versionCheck() function shall be invoked from a StatefulWidget, hence, a good place to call it would be inside the first screen Widget, for example:
class FirstScreen extends StatefulWidget {
const FirstScreen({ Key key }) : super(key: key);
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => versionCheck(context));
}
#override
Widget build(BuildContext context) {
return Container(color: const Color(0xFFFFE306));
}
}
Im trying to create a flutter app with a simple raised button that does the following:
sends an sms in the background using the sms package opens a webpage
2. in the app(only for 5 seconds) using url_launcher opens the phones
3. native app for making a voice call with the onPressed property.
And I wanted it to be in this order so that I can make the phone call at the end. However, the inside the onPressed opens the native phone call app first, which doesnt let my web page open unless I exit out of the phone call app.
Im having a hard time understanding why the phone call native app is opened first, even though I make the call the _makePhoneCall() method only after I make the _launchInApp(toLaunch) call. sendSMS() is being called correctly
How can I set this in a way that the phone call native app is called only after the webpage is opened in the app and follows the order? Any help would be great
Below is the piece of code:
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:sms/sms.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Packages testing',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Packages testing'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _phone = '';
_launchInApp(String url) async {
if (await canLaunch(url)) {
await launch(
url,
forceSafariVC: true,
forceWebView: true,
headers: <String, String>{'my_header_key': 'my_header_value'},
);
} else {
throw 'Could not launch $url';
}
}
_makePhoneCall(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
void sendSMS() {
SmsSender sender = new SmsSender();
sender.sendSms(new SmsMessage(_phone, 'Testing Handset'));
}
#override
Widget build(BuildContext context) {
const String toLaunch = 'https://flutter.dev/';
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
onChanged: (String text) => _phone = text,
decoration:
const InputDecoration(hintText: 'Phone Number')),
),
FlatButton(
onPressed: () => setState(() {
sendSMS();
_launchInApp(toLaunch);
_makePhoneCall('tel:$_phone');
}),
child: const Text('Run All'),
),
const Padding(padding: EdgeInsets.all(16.0)),
],
),
],
),
);
}
}
You will have to use the await keyword before the _launchInApp function to make it work properly. Try the following code.
FlatButton(
onPressed: () aync {
sendSMS();
await _launchInApp(toLaunch);
_makePhoneCall('tel:$_phone');
}),
child: const Text('Run All'),
),
You created async functions but when you called them you did not specify that you want to wait for them to complete. Add the await keyword in OnPressed
So I have followed the tutorial https://github.com/ryanheise/audio_service/wiki/Tutorial
However I have not had any success getting it to work.
My first issues was
final _completer = Completer();
Their is no Completer class so that throw an error.
And it seems that the code they provide just does not fire the following class.
/*AUDIO PLAYER*/
class AudioPlayerTask extends BackgroundAudioTask {
final _audioPlayer = AudioPlayer();
// final _completer = Completer();
#override
Future<void> onStart(Map<String, dynamic> params) async {
// Connect to the URL
print("test");
await _audioPlayer.setUrl("https://perth.adstichr.com.au/station/DRN1?uuid=0000-0000-0000-0000");
// Now we're ready to play
_audioPlayer.play();
}
#override
Future<void> onStop() async {
// Stop playing audio
await _audioPlayer.stop();
// Shut down this background task
await super.onStop();
}
}
The full code is
import 'package:flutter/material.dart';
import 'package:audio_service/audio_service.dart';
import 'package:just_audio/just_audio.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: AudioServiceWidget(child: MainScreen()),
);
}
}
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(child: Text("Start"), onPressed: start),
RaisedButton(child: Text("Stop"), onPressed: stop),
],
),
),
);
}
start() =>
AudioService.start(backgroundTaskEntrypoint: _backgroundTaskEntrypoint);
stop() => AudioService.stop();
_backgroundTaskEntrypoint() {
AudioServiceBackground.run(() => AudioPlayerTask());
}
}
/*AUDIO PLAYER*/
class AudioPlayerTask extends BackgroundAudioTask {
final _audioPlayer = AudioPlayer();
// final _completer = Completer();
#override
Future<void> onStart(Map<String, dynamic> params) async {
// Connect to the URL
print("test");
await _audioPlayer.setUrl("https://perth.adstichr.com.au/station/DRN1?uuid=0000-0000-0000-0000");
// Now we're ready to play
_audioPlayer.play();
}
#override
Future<void> onStop() async {
// Stop playing audio
await _audioPlayer.stop();
// Shut down this background task
await super.onStop();
}
}
I followed the document we must add the method _backgroundTaskEntrypoint() on the top level function, so you should move the function outside the class.
// Must be a top-level function
void _backgroundTaskEntrypoint() {
AudioServiceBackground.run(() => AudioPlayerTask());
}
/*AUDIO PLAYER*/
class AudioPlayerTask extends BackgroundAudioTask {
final _audioPlayer = AudioPlayer();
...
}
It's not working for me either. Note that to use audio_service on Android you must put the following lines into AndroidManifest.xml. However, when I do so, com.ryanheise.audioservice.MediaButtonReceiver gives an error "Class referenced in the manifest, com.ryanheise.audioservice.AudioService, was not found in the project or the libraries", and I'm not sure what to do about that.
This needs to go into the Manifest. See the documentation.
<manifest ...>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application ...>
...
<service android:name="com.ryanheise.audioservice.AudioService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
</application>
</manifest>
I building an app that interacts with some android camera features using dart and flutter on Android Studio.
I'm not very experienced with Dart & Flutter, I'm still in learning process.
class SwitchWidget extends StatefulWidget {
#override
SwitchWidgetClass createState() => new SwitchWidgetClass();
}
Whenever I call Torch.turnOn() nothing is happening and I don't know why. I have tried many approaches and I'm still getting nothing.
The function I'm trying to call is from this package called torch. This package is for turning on and off the android camera flashlight.
The main file of this package I'm using has the following code:
import 'dart:async';
import 'package:flutter/services.dart';
class Torch {
static const MethodChannel _channel = const MethodChannel('io.siteplan.flutterplugins/torch');
static Future turnOn() => _channel.invokeMethod('turnOn');
static Future turnOff() => _channel.invokeMethod('turnOff');
static Future<bool> get hasTorch async => await _channel.invokeMethod('hasTorch');
static Future flash(Duration duration) => turnOn().whenComplete(() => Future.delayed(duration, () => turnOff()));
}
I wrote the code that is below this statement in my custom dart file called homepage.dart.
import 'package:flutter/material.dart';
import 'package:torch/torch.dart';
/**
* HomePage StatefulWidget is here!
*/
class SwitchWidgetClass extends State {
bool switchControl = false;
var textHolder = 'Switch is OFF';
void toggleSwitch(bool value) {
if (switchControl == false) {
setState(() {
switchControl = true;
textHolder = 'Switch is ON';
});
print('Switch is ON');
Torch.turnOn();
} else {
setState(() {
switchControl = false;
textHolder = 'Switch is OFF';
});
print('Switch is OFF');
Torch.turnOff();
}
}
#override
Widget build(BuildContext context) {
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Transform.scale(
scale: 1.5,
child: Switch(
onChanged: toggleSwitch,
value: switchControl,
activeColor: Colors.blue,
activeTrackColor: Colors.green,
inactiveThumbColor: Colors.white,
inactiveTrackColor: Colors.grey,
)),
Text(
'$textHolder',
style: TextStyle(fontSize: 24),
)
]);
}
}
What I want is When I call the Torch.turnOn() method, it should work and turn on the camera flashlight.
To use Torch you must import "torch.dart" package;A Flutter plugin to access the device's torch on Android and iOS.
import 'package:torch/torch.dart';
Read more here
try to add this Permission to Manifest file in Android
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera.flash" />