اذهب إلى المحتوى

السؤال

Recommended Posts

  • 0
نشر

توجد شركة agara يمكنك قراءة التوثيق الخاص بها من هنا , تقريباً هي أفضل شركة تقدم خدمات live Streaming.

بعد الاشتراك في هذه الخدمة يمكنك تضمين مكتبة agora_rtc_engine  داخل مشروعك يمكنك إيجاد المكتبة من هنا.

في ملف pubspec.yaml تضع التالي 

agora_rtc_engine: ^3.3.3

ثم تقوم بتنفيذ الأمر التالي 

flutter pub get

بعد الاشتراك ستجد APPI_ID, TOKEN  حيث في ملف main.dart ستقوم بوضع كليهما بهذا الشكل 

const APP_ID = '';
const Token = '';

ثم تقوم بتعريف ملف main.dart بهذا الشكل 

import 'dart:async';

import 'package:agora_rtc_engine/rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Live Stream',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: homePage(),
    );
  }
}

ثم تقوم بتعريف homePage بهذا الشكل 

class homePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => IndexState();
}

class IndexState extends State<homePage> {
  final _channelController = TextEditingController();
  bool _validateError = false;
  ClientRole _role = ClientRole.Broadcaster;

  @override
	void dispose() {
		// dispose input controller
		_channelController.dispose();
		super.dispose();
	}
	
	@override
	Widget build(BuildContext context) {
	  return Scaffold(
		appBar: AppBar(
		  title: Text('Agora Flutter QuickStart'),
		),
		body: Center(
		  child: Container(
			padding: const EdgeInsets.symmetric(horizontal: 20),
			height: 400,
			child: Column(
			  children: <Widget>[
				Row(
				  children: <Widget>[
					Expanded(
						child: TextField(
					  controller: _channelController,
					  decoration: InputDecoration(
						errorText:
							_validateError ? 'Channel name is mandatory' : null,
						border: UnderlineInputBorder(
						  borderSide: BorderSide(width: 1),
						),
						hintText: 'Channel name',
					  ),
					))
				  ],
				),
				Column(
				  children: [
					ListTile(
					  title: Text(ClientRole.Broadcaster.toString()),
					  leading: Radio(
						value: ClientRole.Broadcaster,
						groupValue: _role,
						onChanged: (ClientRole value) {
						  setState(() {
							_role = value;
						  });
						},
					  ),
					),
					ListTile(
					  title: Text(ClientRole.Audience.toString()),
					  leading: Radio(
						value: ClientRole.Audience,
						groupValue: _role,
						onChanged: (ClientRole value) {
						  setState(() {
							_role = value;
						  });
						},
					  ),
					)
				  ],
				),
				Padding(
				  padding: const EdgeInsets.symmetric(vertical: 20),
				  child: Row(
					children: <Widget>[
					  Expanded(
						child: RaisedButton(
						  onPressed: joinStream,
						  child: Text('Join'),
						  color: Colors.green,
						  textColor: Colors.black,
						),
					  )
					],
				  ),
				)
			  ],
			),
		  ),
		),
	  );
	}
	  /// زر الانضمام إلى البث
	  Future<void> joinStream() async {
		setState(() {
		  _channelController.text.isEmpty
			  ? _validateError = true
			  : _validateError = false;
		});
		if (_channelController.text.isNotEmpty) {
		  // انتظر إذن الكاميرا والميكروفون
		  await _handleCameraAndMic();
		  // أدخل صفحة البث المباشر وانضم إلى القناة باستخدام اسم القناة والدور المحدد في صفحة تسجيل الدخول
		  await Navigator.push(
			context,
			MaterialPageRoute(
			  builder: (context) => CallPage(
				channelName: _channelController.text,
				role: _role,
			  ),
			),
		  );
		}
	  }

	  // لتفعيل الكاميرا و المايكرفون
	  Future<void> _handleCameraAndMic() async {
		await PermissionHandler().requestPermissions(
		  [PermissionGroup.camera, PermissionGroup.microphone],
		);
	  }
}

كود صفحة البث , يوجد شرح مضمن بداخله للدوال  

class livePage extends StatefulWidget {
  final String channelName;
  final ClientRole role;
  const livePage({Key key, this.channelName, this.role}) : super(key: key);

  @override
  _livePageState createState() => _livePageState();
}

class _livePageState extends State<CallPage> {
  final _users = <int>[];
  final _infoStrings = <String>[];
  bool muted = false;
  RtcEngine _engine;



  @override
  void dispose() {
    _users.clear();
    _engine.leaveChannel();
    _engine.destroy();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    initialize();
  }

  Future<void> initialize() async {
    if (APP_ID.isEmpty) {
      setState(() {
        _infoStrings.add(
          'مفقود ، يرجى تقديم APP_ID الخاص بك في',
        );
        _infoStrings.add('Agora Engine is not starting');
      });
      return;
    }

    await _initAgoraRtcEngine();
    _addAgoraEventHandlers();
        /// Join channel
    await _engine.joinChannel(Token, widget.channelName, null, 0);
  }
  
  
    // تخطيط شريط الأدوات
  Widget _toolbar() {
    if (widget.role == ClientRole.Audience) return Container();
    return Container(
      alignment: Alignment.bottomCenter,
      padding: const EdgeInsets.symmetric(vertical: 48),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RawMaterialButton(
            onPressed: _onToggleMute,
            child: Icon(
              muted ? Icons.mic_off : Icons.mic,
              color: muted ? Colors.white : Colors.blueAccent,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: muted ? Colors.blueAccent : Colors.white,
            padding: const EdgeInsets.all(12.0),
          ),
          RawMaterialButton(
            onPressed: () => _onCallEnd(context),
            child: Icon(
              Icons.call_end,
              color: Colors.white,
              size: 35.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: Colors.redAccent,
            padding: const EdgeInsets.all(15.0),
          ),
          RawMaterialButton(
            onPressed: _onSwitchCamera,
            child: Icon(
              Icons.switch_camera,
              color: Colors.blueAccent,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: Colors.white,
            padding: const EdgeInsets.all(12.0),
          )
        ],
      ),
    );
  }
  
  
  Future<void> _initAgoraRtcEngine() async {
	  RtcEngineConfig config = RtcEngineConfig(APP_ID);
	  _engine = await RtcEngine.createWithConfig(config);
	  await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting);
	  await _engine.setClientRole(widget.role);
	}

void _addAgoraEventHandlers() {
  _engine.setEventHandler(RtcEngineEventHandler(error: (code) {
    setState(() {
      final info = 'onError: $code';
      _infoStrings.add(info);
    });
  }, joinChannelSuccess: (channel, uid, elapsed) {
    setState(() {
      final info = 'onJoinChannel: $channel, uid: $uid';
      _infoStrings.add(info);
    });
  }, leaveChannel: (stats) {
    setState(() {
      _infoStrings.add('onLeaveChannel');
      _users.clear();
    });
  }, userJoined: (uid, elapsed) {
    setState(() {
      final info = 'userJoined: $uid';
      _infoStrings.add(info);
      _users.add(uid);
    });
  }, userOffline: (uid, elapsed) {
    setState(() {
      final info = 'userOffline: $uid';
      _infoStrings.add(info);
      _users.remove(uid);
    });
  }));
}

	  /// تخطيط شريط الأدوات
  Widget _toolbar() {
    if (widget.role == ClientRole.Audience) return Container();
    return Container(
      alignment: Alignment.bottomCenter,
      padding: const EdgeInsets.symmetric(vertical: 48),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RawMaterialButton(
            onPressed: _onToggleMute,
            child: Icon(
              muted ? Icons.mic_off : Icons.mic,
              color: muted ? Colors.white : Colors.blueAccent,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: muted ? Colors.blueAccent : Colors.white,
            padding: const EdgeInsets.all(12.0),
          ),
          RawMaterialButton(
            onPressed: () => _onCallEnd(context),
            child: Icon(
              Icons.call_end,
              color: Colors.white,
              size: 35.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: Colors.redAccent,
            padding: const EdgeInsets.all(15.0),
          ),
          RawMaterialButton(
            onPressed: _onSwitchCamera,
            child: Icon(
              Icons.switch_camera,
              color: Colors.blueAccent,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: Colors.white,
            padding: const EdgeInsets.all(12.0),
          )
        ],
      ),
    );
  }


 // لوحة معلومات لعرض السجلات
  Widget _panel() {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 48),
      alignment: Alignment.bottomCenter,
      child: FractionallySizedBox(
        heightFactor: 0.5,
        child: Container(
          padding: const EdgeInsets.symmetric(vertical: 48),
          child: ListView.builder(
            reverse: true,
            itemCount: _infoStrings.length,
            itemBuilder: (BuildContext context, int index) {
              if (_infoStrings.isEmpty) {
                return null;
              }
              return Padding(
                padding: const EdgeInsets.symmetric(
                  vertical: 3,
                  horizontal: 10,
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Flexible(
                      child: Container(
                        padding: const EdgeInsets.symmetric(
                          vertical: 2,
                          horizontal: 5,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.yellowAccent,
                          borderRadius: BorderRadius.circular(5),
                        ),
                        child: Text(
                          _infoStrings[index],
                          style: TextStyle(color: Colors.blueGrey),
                        ),
                      ),
                    )
                  ],
                ),
              );
            },
          ),
        ),
      ),
    );
  }

	// وقف البث المباشر
	void _onCallEnd(BuildContext context) {
		Navigator.pop(context);
	  }

	  /// صامت
	  void _onToggleMute() {
		setState(() {
		  muted = !muted;
		});
		_engine.muteLocalAudioStream(muted);
	  }

	  @override
	  Widget build(BuildContext context) {
		return Scaffold(
		  appBar: AppBar(
			title: Text('Agora Flutter QuickStart'),
		  ),
		  backgroundColor: Colors.black,
		  body: Center(
			child: Stack(
			  children: <Widget>[
				_panel(),
				_toolbar(),
			  ],
			),
		  ),
		);
	  }
}

هذه الأكواد مجرد أمثلة يمكنك مراجعة توثيق agora من هنا فكل شيء مشروح بشكلٍ مفصل لكيفية تضمين المكتبة و الاشتراك في الخدمة.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...