Search code examples
fluttervideo-streamingagora.iovideochat

How to make video call in flutter with agora?


I am using official flutter agora example for making video call , but the local camera only opens , and the remote user is never called.

packages : "agora_rtc_engine: ^4.2.0" "permission_handler: ^8.3.0"

This is the official example https://pub.dev/packages/agora_rtc_engine/example

and this I am following this tutorial also https://www.youtube.com/watch?v=zVqs1EIpVxs

and this is my code

    import 'dart:async';
    
    import 'package:agora_rtc_engine/rtc_engine.dart';
    import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView;
    import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView;
    import 'package:flutter/material.dart';
    import 'package:permission_handler/permission_handler.dart';
    
    const appId = "843b5a8f8c3a4e0fbe2c804654f4ce36";
    const token = "006843b5a8f8c3a4e0fbe2c804654f4ce36IAA4Le0bHwiNWScQ3+1c4sM+UXErd0xfOdjuoZRe1Dz8B9vEKrAAAAAAEADVz7HmNwPgYQEAAQAWA+Bh";
    
    void main() => runApp(MaterialApp(home: MyApp()));
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      int? _remoteUid;
      bool _localUserJoined = false;
      late RtcEngine _engine;
    
      @override
      void initState() {
        super.initState();
        initAgora();
      }
    
      Future<void> initAgora() async {
        // retrieve permissions
        await [Permission.microphone, Permission.camera].request();
    
        //create the engine
        _engine = await RtcEngine.create(appId);
        await _engine.enableVideo();
        _engine.setEventHandler(
          RtcEngineEventHandler(
            joinChannelSuccess: (String channel, int uid, int elapsed) {
              print("local user $uid joined");
              setState(() {
                _localUserJoined = true;
              });
            },
            userJoined: (int uid, int elapsed) {
              print("remote user $uid joined");
              setState(() {
                _remoteUid = uid;
              });
            },
            userOffline: (int uid, UserOfflineReason reason) {
              print("remote user $uid left channel");
              setState(() {
                _remoteUid = null;
              });
            },
            
          ),
        );
    
        await _engine.joinChannel(token, "test_video_call", null, 0);
      }
    
      // Create UI with local view and remote view
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Agora Video Call'),
          ),
          body: Stack(
            children: [
              Center(
                child: _remoteVideo(),
              ),
              Align(
                alignment: Alignment.topLeft,
                child: Container(
                  width: 100,
                  height: 150,
                  child: Center(
                    child: _localUserJoined
                        ? RtcLocalView.SurfaceView()
                        : CircularProgressIndicator(),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    
      // Display remote user's video
      Widget _remoteVideo() {
        if (_remoteUid != null) {
          return RtcRemoteView.SurfaceView(uid: _remoteUid!);
        } else {
          return Text(
            'Please wait for remote user to join',
            textAlign: TextAlign.center,
          );
        }
      }
    }

Screenshot


Solution

  • I have also gone through the sample code available in the plugin example but there are few thing that you need to ensure.

    1. UID should be different for each user (put 0 if testing)
    2. token should be from same AppId used in create method. (if token is enabled)
    3. Token expires in 24 hours so make sure that token is working.
    4. Channel name should be unique