Methods are not getting executed in the written order inside onPressed

160 Views Asked by At

Im trying to create a flutter app with a simple raised button that does the following:

  1. 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)),
                ],
              ),
            ],
          ),
        );
      }
    }

2

There are 2 best solutions below

1
On

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

1
On

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'),
              ),