1. ভূমিকা
শেষ আপডেট: ২০২২-০৩-১৪
ক্রস ডিভাইস যোগাযোগের জন্য FlutterFire
যেহেতু আমরা বিপুল সংখ্যক হোম অটোমেশন, পরিধেয় এবং ব্যক্তিগত স্বাস্থ্য প্রযুক্তি ডিভাইস অনলাইনে আসতে দেখছি, তাই মোবাইল অ্যাপ্লিকেশন তৈরির ক্ষেত্রে ক্রস-ডিভাইস যোগাযোগ ক্রমশ গুরুত্বপূর্ণ হয়ে উঠছে। ফোন অ্যাপ থেকে ব্রাউজার নিয়ন্ত্রণ করা, অথবা আপনার ফোন থেকে আপনার টিভিতে কী চলছে তা নিয়ন্ত্রণ করার মতো ক্রস-ডিভাইস যোগাযোগ সেট আপ করা, ঐতিহ্যগতভাবে একটি সাধারণ মোবাইল অ্যাপ তৈরির চেয়ে বেশি জটিল।
ফায়ারবেসের রিয়েলটাইম ডাটাবেস প্রেজেন্স এপিআই প্রদান করে যা ব্যবহারকারীদের তাদের ডিভাইসের অনলাইন/অফলাইন অবস্থা দেখতে দেয়; আপনি এটি ফায়ারবেস ইনস্টলেশন পরিষেবার সাথে ব্যবহার করতে পারবেন যেখানে একই ব্যবহারকারী সাইন ইন করেছেন এমন সমস্ত ডিভাইস ট্র্যাক এবং সংযোগ করতে। আপনি দ্রুত একাধিক প্ল্যাটফর্মের জন্য অ্যাপ্লিকেশন তৈরি করতে ফ্লটার ব্যবহার করবেন এবং তারপরে আপনি একটি ক্রস ডিভাইস প্রোটোটাইপ তৈরি করবেন যা একটি ডিভাইসে সঙ্গীত বাজায় এবং অন্যটিতে সঙ্গীত নিয়ন্ত্রণ করে!
তুমি কী তৈরি করবে
এই কোডল্যাবে, আপনি একটি সাধারণ মিউজিক প্লেয়ার রিমোট কন্ট্রোলার তৈরি করবেন। আপনার অ্যাপটি করবে:
- অ্যান্ড্রয়েড, আইওএস এবং ওয়েবে ফ্লটার দিয়ে তৈরি একটি সাধারণ মিউজিক প্লেয়ার রাখুন।
- ব্যবহারকারীদের সাইন ইন করার অনুমতি দিন।
- একই ব্যবহারকারী একাধিক ডিভাইসে সাইন ইন করলে ডিভাইসগুলি সংযুক্ত করুন।
- ব্যবহারকারীদের এক ডিভাইস থেকে অন্য ডিভাইসে সঙ্গীত প্লেব্যাক নিয়ন্ত্রণ করার অনুমতি দিন।

তুমি কি শিখবে
- কিভাবে একটি ফ্লাটার মিউজিক প্লেয়ার অ্যাপ তৈরি এবং চালানো যায়।
- ব্যবহারকারীদের Firebase Auth দিয়ে সাইন ইন করার অনুমতি কীভাবে দেওয়া যায়।
- ডিভাইস সংযোগ করার জন্য Firebase RTDB Presence API এবং Firebase Installation Service কীভাবে ব্যবহার করবেন।
তোমার যা লাগবে
- একটি ফ্লাটার ডেভেলপমেন্ট এনভায়রনমেন্ট। এটি সেট আপ করার জন্য ফ্লাটার ইনস্টলেশন গাইডের নির্দেশাবলী অনুসরণ করুন।
- ন্যূনতম ফ্লটার ভার্সন ২.১০ বা তার বেশি হতে হবে। যদি আপনার কম ভার্সন থাকে, তাহলে
flutter upgrade. - একটি ফায়ারবেস অ্যাকাউন্ট।
2. সেট আপ করা
স্টার্টার কোডটি পান
আমরা Flutter-এ একটি মিউজিক প্লেয়ার অ্যাপ তৈরি করেছি। স্টার্টার কোডটি একটি Git রেপোতে অবস্থিত। শুরু করতে, কমান্ড লাইনে, রেপোটি ক্লোন করুন, শুরুর অবস্থা সহ ফোল্ডারে যান এবং নির্ভরতা ইনস্টল করুন:
git clone https://github.com/FirebaseExtended/cross-device-controller.git
cd cross-device-controller/starter_code
flutter pub get
অ্যাপটি তৈরি করুন
অ্যাপটি তৈরি করতে আপনি আপনার পছন্দের IDE দিয়ে কাজ করতে পারেন, অথবা কমান্ড লাইন ব্যবহার করতে পারেন।
আপনার অ্যাপ ডিরেক্টরিতে, flutter run -d web-server. আপনি নিম্নলিখিত প্রম্পটটি দেখতে সক্ষম হবেন।
lib/main.dart is being served at http://localhost:<port>
মিউজিক প্লেয়ারটি দেখতে http://localhost:<port> দেখুন।
যদি আপনি অ্যান্ড্রয়েড এমুলেটর বা iOS সিমুলেটরের সাথে পরিচিত হন, তাহলে আপনি সেই প্ল্যাটফর্মগুলির জন্য অ্যাপটি তৈরি করতে পারেন এবং flutter run -d <device_name> কমান্ড দিয়ে এটি ইনস্টল করতে পারেন।
ওয়েব অ্যাপটিতে একটি বেসিক স্ট্যান্ডঅ্যালোন মিউজিক প্লেয়ার দেখানো উচিত। নিশ্চিত করুন যে প্লেয়ারের বৈশিষ্ট্যগুলি ইচ্ছাকৃতভাবে কাজ করছে। এটি একটি সাধারণ মিউজিক প্লেয়ার অ্যাপ যা এই কোডল্যাবের জন্য ডিজাইন করা হয়েছে। এটি শুধুমাত্র একটি Firebase গান, Better Together , বাজাতে পারে।
একটি অ্যান্ড্রয়েড এমুলেটর বা একটি iOS সিমুলেটর সেট আপ করুন
যদি আপনার ইতিমধ্যেই ডেভেলপমেন্টের জন্য একটি Android ডিভাইস বা iOS ডিভাইস থাকে, তাহলে আপনি এই ধাপটি এড়িয়ে যেতে পারেন।
একটি অ্যান্ড্রয়েড এমুলেটর তৈরি করতে, অ্যান্ড্রয়েড স্টুডিও ডাউনলোড করুন যা ফ্লটার ডেভেলপমেন্ট সমর্থন করে এবং ভার্চুয়াল ডিভাইস তৈরি এবং পরিচালনা করুন -এর নির্দেশাবলী অনুসরণ করুন।
একটি iOS সিমুলেটর তৈরি করতে, আপনার একটি Mac পরিবেশের প্রয়োজন হবে। XCode ডাউনলোড করুন এবং Simulator Overview > Use Simulator > Open and Close a simulator এর নির্দেশাবলী অনুসরণ করুন।
৩. ফায়ারবেস সেট আপ করুন
একটি ফায়ারবেস প্রকল্প তৈরি করুন
- আপনার গুগল অ্যাকাউন্ট ব্যবহার করে ফায়ারবেস কনসোলে সাইন ইন করুন।
- একটি নতুন প্রকল্প তৈরি করতে বোতামটি ক্লিক করুন, এবং তারপর একটি প্রকল্পের নাম লিখুন (উদাহরণস্বরূপ,
Firebase-Cross-Device-Codelab)। - চালিয়ে যান ক্লিক করুন।
- যদি অনুরোধ করা হয়, তাহলে Firebase শর্তাবলী পর্যালোচনা করুন এবং গ্রহণ করুন, এবং তারপর Continue এ ক্লিক করুন।
- (ঐচ্ছিক) Firebase কনসোলে ("Gemini in Firebase" নামে পরিচিত) AI সহায়তা সক্ষম করুন।
- এই কোডল্যাবের জন্য, আপনার গুগল অ্যানালিটিক্সের প্রয়োজন নেই , তাই গুগল অ্যানালিটিক্স বিকল্পটি টগল করে বন্ধ করে দিন ।
- Create project এ ক্লিক করুন, আপনার province করার জন্য অপেক্ষা করুন, এবং তারপর Continue এ ক্লিক করুন।
ফায়ারবেস এসডিকে ইনস্টল করুন
কমান্ড লাইনে ফিরে, প্রজেক্ট ডিরেক্টরিতে, Firebase ইনস্টল করতে নিম্নলিখিত কমান্ডটি চালান:
flutter pub add firebase_core
pubspec.yaml ফাইলে, firebase_core এর সংস্করণটি কমপক্ষে 1.13.1 করুন, অথবা flutter upgrade চালান।
ফ্লাটারফায়ার শুরু করুন
- যদি আপনার Firebase CLI ইনস্টল না থাকে, তাহলে আপনি
curl -sL https://firebase.tools | bashচালিয়ে এটি ইনস্টল করতে পারেন। -
firebase loginচালিয়ে এবং প্রম্পটগুলি অনুসরণ করে লগ ইন করুন। -
dart pub global activate flutterfire_cliচালিয়ে FlutterFire CLI ইনস্টল করুন। -
flutterfire configureচালিয়ে FlutterFire CLI কনফিগার করুন। - প্রম্পটে, এই কোডল্যাবের জন্য আপনি যে প্রকল্পটি তৈরি করেছেন তা নির্বাচন করুন, যেমন Firebase-Cross-Device-Codelab ।
- কনফিগারেশন সাপোর্ট বেছে নিতে বলা হলে iOS , Android এবং Web নির্বাচন করুন।
- অ্যাপল বান্ডেল আইডির জন্য অনুরোধ করা হলে, একটি অনন্য ডোমেন টাইপ করুন, অথবা
com.example.appnameলিখুন, যা এই কোডল্যাবের উদ্দেশ্যে ঠিক আছে।
একবার কনফিগার হয়ে গেলে, আপনার জন্য একটি firebase_options.dart ফাইল তৈরি করা হবে যাতে আরম্ভের জন্য প্রয়োজনীয় সমস্ত বিকল্প থাকবে।
আপনার এডিটরে, Flutter এবং Firebase শুরু করতে আপনার main.dart ফাইলে নিম্নলিখিত কোডটি যোগ করুন:
lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyMusicBoxApp());
}
কমান্ডটি ব্যবহার করে অ্যাপটি কম্পাইল করুন:
flutter run
আপনি এখনও কোনও UI উপাদান পরিবর্তন করেননি, তাই অ্যাপটির চেহারা এবং আচরণ পরিবর্তন হয়নি। কিন্তু এখন আপনার একটি Firebase অ্যাপ আছে, এবং আপনি Firebase পণ্য ব্যবহার শুরু করতে পারেন, যার মধ্যে রয়েছে:
- Firebase Authentication , যা আপনার ব্যবহারকারীদের আপনার অ্যাপে সাইন ইন করতে দেয়।
- ফায়ারবেস রিয়েলটাইম ডাটাবেস (RTDB) ; আপনি ডিভাইসের অনলাইন/অফলাইন অবস্থা ট্র্যাক করতে উপস্থিতি API ব্যবহার করবেন।
- ফায়ারবেস সিকিউরিটি রুলস আপনাকে ডাটাবেস সুরক্ষিত করতে দেবে।
- একজন ব্যবহারকারী যে ডিভাইসগুলিতে সাইন ইন করেছেন তা সনাক্ত করার জন্য ফায়ারবেস ইনস্টলেশন পরিষেবা ।
৪. ফায়ারবেস প্রমাণীকরণ যোগ করুন
Firebase প্রমাণীকরণের জন্য ইমেল সাইন-ইন সক্ষম করুন
ব্যবহারকারীদের ওয়েব অ্যাপে সাইন ইন করার অনুমতি দিতে, আপনি ইমেল/পাসওয়ার্ড সাইন-ইন পদ্ধতি ব্যবহার করবেন:
- ফায়ারবেস কনসোলে, বাম প্যানেলে বিল্ড মেনুটি প্রসারিত করুন।
- Authentication এ ক্লিক করুন, এবং তারপর Get Started বাটনে ক্লিক করুন, তারপর Sign-in method ট্যাবে ক্লিক করুন।
- সাইন-ইন প্রোভাইডার তালিকায় ইমেল/পাসওয়ার্ড ক্লিক করুন, Enable সুইচটিকে on পজিশনে সেট করুন এবং তারপর Save এ ক্লিক করুন।

Flutter-এ Firebase প্রমাণীকরণ কনফিগার করুন
কমান্ড লাইনে, প্রয়োজনীয় ফ্লাটার প্যাকেজ ইনস্টল করতে নিম্নলিখিত কমান্ডগুলি চালান:
flutter pub add firebase_auth
flutter pub add provider
এই কনফিগারেশনের মাধ্যমে, আপনি এখন সাইন-ইন এবং সাইন-আউট ফ্লো তৈরি করতে পারবেন। যেহেতু auth অবস্থা স্ক্রিন থেকে স্ক্রিনে পরিবর্তিত হওয়া উচিত নয়, তাই আপনি অ্যাপ স্তরের অবস্থার পরিবর্তনগুলি, যেমন লগ ইন এবং লগ আউট, ট্র্যাক রাখতে একটি application_state.dart ক্লাস তৈরি করবেন। Flutter অবস্থা ব্যবস্থাপনা ডকুমেন্টেশনে এই সম্পর্কে আরও জানুন।
নতুন application_state.dart ফাইলে নিম্নলিখিতটি পেস্ট করুন:
lib/src/application_state.dart
import 'package:firebase_auth/firebase_auth.dart'; // new
import 'package:firebase_core/firebase_core.dart'; // new
import 'package:flutter/material.dart';
import '../firebase_options.dart';
import 'authentication.dart';
class ApplicationState extends ChangeNotifier {
ApplicationState() {
init();
}
Future<void> init() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
_loginState = ApplicationLoginState.loggedIn;
} else {
_loginState = ApplicationLoginState.loggedOut;
}
notifyListeners();
});
}
ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
ApplicationLoginState get loginState => _loginState;
String? _email;
String? get email => _email;
void startLoginFlow() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
Future<void> verifyEmail(
String email,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
var methods =
await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
if (methods.contains('password')) {
_loginState = ApplicationLoginState.password;
} else {
_loginState = ApplicationLoginState.register;
}
_email = email;
notifyListeners();
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
Future<void> signInWithEmailAndPassword(
String email,
String password,
void Function(FirebaseAuthException e) errorCallback,
) async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void cancelRegistration() {
_loginState = ApplicationLoginState.emailAddress;
notifyListeners();
}
Future<void> registerAccount(
String email,
String displayName,
String password,
void Function(FirebaseAuthException e) errorCallback) async {
try {
var credential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
await credential.user!.updateDisplayName(displayName);
} on FirebaseAuthException catch (e) {
errorCallback(e);
}
}
void signOut() {
FirebaseAuth.instance.signOut();
}
}
অ্যাপটি শুরু হওয়ার সাথে সাথে ApplicationState চালু হবে কিনা তা নিশ্চিত করতে, আপনাকে main.dart এ একটি প্রাথমিককরণ ধাপ যোগ করতে হবে:
lib/main.dart
import 'src/application_state.dart';
import 'package:provider/provider.dart';
void main() async {
...
runApp(ChangeNotifierProvider(
create: (context) => ApplicationState(),
builder: (context, _) => const MyMusicBoxApp(),
));
}
আবার, অ্যাপ্লিকেশন UI একই থাকা উচিত ছিল, কিন্তু এখন আপনি ব্যবহারকারীদের সাইন ইন করতে এবং অ্যাপের অবস্থা সংরক্ষণ করতে দিতে পারেন।
একটি সাইন ইন ফ্লো তৈরি করুন
এই ধাপে, আপনি সাইন ইন এবং সাইন আউট ফ্লোতে কাজ করবেন। ফ্লোটি কেমন হবে তা এখানে দেওয়া হল:
- লগ আউট হওয়া ব্যবহারকারী প্রসঙ্গ মেনুতে ক্লিক করে সাইন-ইন প্রবাহ শুরু করবেন।
অ্যাপ বারের ডানদিকে। - সাইন-ইন প্রবাহ একটি ডায়ালগে প্রদর্শিত হবে।
- যদি ব্যবহারকারী আগে কখনও সাইন ইন না করে থাকেন, তাহলে তাদের একটি বৈধ ইমেল ঠিকানা এবং পাসওয়ার্ড ব্যবহার করে একটি অ্যাকাউন্ট তৈরি করতে বলা হবে।
- যদি ব্যবহারকারী আগে সাইন ইন করে থাকেন, তাহলে তাদের পাসওয়ার্ড লিখতে বলা হবে।
- ব্যবহারকারী সাইন ইন হয়ে গেলে, প্রসঙ্গ মেনুতে ক্লিক করলে একটি সাইন আউট বিকল্প দেখাবে।

সাইন-ইন ফ্লো যোগ করার জন্য তিনটি ধাপ প্রয়োজন।
প্রথমে একটি AppBarMenuButton উইজেট তৈরি করুন। এই উইজেটটি ব্যবহারকারীর loginState এর উপর নির্ভর করে কনটেক্সট মেনু পপআপ নিয়ন্ত্রণ করবে। আমদানি যোগ করুন।
lib/src/widgets.dart
import 'application_state.dart';
import 'package:provider/provider.dart';
import 'authentication.dart';
widgets.dart.
lib/src/widgets.dart
class AppBarMenuButton extends StatelessWidget {
const AppBarMenuButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<ApplicationState>(
builder: (context, appState, child) {
if (appState.loginState == ApplicationLoginState.loggedIn) {
return SignedInMenuButton(buildContext: context);
}
return SignInMenuButton(buildContext: context);
},
);
}
}
class SignedInMenuButton extends StatelessWidget {
const SignedInMenuButton({Key? key, required this.buildContext})
: super(key: key);
final BuildContext buildContext;
@override
Widget build(BuildContext context) {
return PopupMenuButton<String>(
onSelected: _handleSignedInMenu,
color: Colors.deepPurple.shade300,
itemBuilder: (context) => _getMenuItemBuilder(),
);
}
List<PopupMenuEntry<String>> _getMenuItemBuilder() {
return [
const PopupMenuItem<String>(
value: 'Sign out',
child: Text(
'Sign out',
style: TextStyle(color: Colors.white),
),
)
];
}
Future<void> _handleSignedInMenu(String value) async {
switch (value) {
case 'Sign out':
Provider.of<ApplicationState>(buildContext, listen: false).signOut();
break;
}
}
}
class SignInMenuButton extends StatelessWidget {
const SignInMenuButton({Key? key, required this.buildContext})
: super(key: key);
final BuildContext buildContext;
@override
Widget build(BuildContext context) {
return PopupMenuButton<String>(
onSelected: _signIn,
color: Colors.deepPurple.shade300,
itemBuilder: (context) => _getMenuItemBuilder(context),
);
}
Future<void> _signIn(String value) async {
return showDialog<void>(
context: buildContext,
builder: (context) => const SignInDialog(),
);
}
List<PopupMenuEntry<String>> _getMenuItemBuilder(BuildContext context) {
return [
const PopupMenuItem<String>(
value: 'Sign in',
child: Text(
'Sign in',
style: TextStyle(color: Colors.white),
),
),
];
}
}
দ্বিতীয়ত, একই widgets.dart ক্লাসে, SignInDialog উইজেট তৈরি করুন।
lib/src/widgets.dart
class SignInDialog extends AlertDialog {
const SignInDialog({Key? key}) : super(key: key);
@override
AlertDialog build(BuildContext context) {
return AlertDialog(
content: Column(mainAxisSize: MainAxisSize.min, children: [
Consumer<ApplicationState>(
builder: (context, appState, _) => Authentication(
email: appState.email,
loginState: appState.loginState,
startLoginFlow: appState.startLoginFlow,
verifyEmail: appState.verifyEmail,
signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
cancelRegistration: appState.cancelRegistration,
registerAccount: appState.registerAccount,
signOut: appState.signOut,
),
),
]),
);
}
}
তৃতীয়ত, main.dart. সাইন ইন বা সাইন আউট বিকল্পটি প্রদর্শন করতে AppBarMenuButton যুক্ত করুন।
lib/main.dart
import 'src/widgets.dart';
appBar: AppBar(
title: const Text('Music Box'),
backgroundColor: Colors.deepPurple.shade400,
actions: const <Widget>[
AppBarMenuButton(),
],
),
এই পরিবর্তনগুলি সহ অ্যাপটি পুনরায় চালু করতে flutter run কমান্ডটি চালান। আপনি প্রসঙ্গ মেনু দেখতে সক্ষম হবেন।
অ্যাপ বারের ডানদিকে। এটিতে ক্লিক করলে আপনাকে একটি সাইন-ইন ডায়ালগে নিয়ে যাবে।
একবার আপনি একটি বৈধ ইমেল ঠিকানা এবং পাসওয়ার্ড দিয়ে সাইন ইন করলে, আপনি প্রসঙ্গ মেনুতে একটি সাইন আউট বিকল্প দেখতে পাবেন।
Firebase কনসোলে, Authentication এর অধীনে, আপনি একজন নতুন ব্যবহারকারী হিসাবে তালিকাভুক্ত ইমেল ঠিকানাটি দেখতে সক্ষম হবেন।

অভিনন্দন! ব্যবহারকারীরা এখন অ্যাপটিতে সাইন ইন করতে পারবেন!
৫. ডাটাবেস সংযোগ যোগ করুন
এখন আপনি Firebase Presence API ব্যবহার করে ডিভাইস নিবন্ধনের জন্য প্রস্তুত।
কমান্ড লাইনে, প্রয়োজনীয় নির্ভরতা যোগ করতে নিম্নলিখিত কমান্ডগুলি চালান:
flutter pub add firebase_app_installations
flutter pub add firebase_database
একটি ডাটাবেস তৈরি করুন
ফায়ারবেস কনসোলে,
- Firebase কনসোলের রিয়েলটাইম ডেটাবেস বিভাগে যান। Create Database এ ক্লিক করুন।
- যদি আপনার নিরাপত্তা নিয়মের জন্য একটি শুরুর মোড নির্বাচন করতে বলা হয়, তাহলে আপাতত টেস্ট মোড নির্বাচন করুন**.** (টেস্ট মোড নিরাপত্তা নিয়ম তৈরি করে যা সমস্ত অনুরোধের মাধ্যমে অনুমতি দেয়। আপনি পরে নিরাপত্তা নিয়ম যোগ করবেন। আপনার নিরাপত্তা নিয়মগুলি এখনও টেস্ট মোডে থাকা অবস্থায় কখনও উৎপাদনে না যাওয়া গুরুত্বপূর্ণ।)
ডাটাবেসটি আপাতত খালি। জেনারেল ট্যাবের অধীনে, প্রজেক্ট সেটিংসে আপনার databaseURL খুঁজুন। ওয়েব অ্যাপস বিভাগে স্ক্রোল করুন।

firebase_options.dart ফাইলে আপনার databaseURL যোগ করুন :
lib/firebase_options.dart
static const FirebaseOptions web = FirebaseOptions(
apiKey: yourApiKey,
...
databaseURL: 'https://<YOUR_DATABASE_URL>,
...
);
RTDB Presence API ব্যবহার করে ডিভাইসগুলি নিবন্ধন করুন
আপনি যখন কোনও ব্যবহারকারীর ডিভাইস অনলাইনে উপস্থিত হয় তখন তাদের নিবন্ধন করতে চান। এটি করার জন্য, আপনাকে একজন ব্যবহারকারীর অনলাইন ডিভাইসের তালিকা ট্র্যাক করার জন্য Firebase Installations এবং Firebase RTDB Presence API-এর সুবিধা নিতে হবে। নিম্নলিখিত কোডটি এই লক্ষ্য অর্জনে সহায়তা করবে:
lib/src/application_state.dart
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_app_installations/firebase_app_installations.dart';
class ApplicationState extends ChangeNotifier {
String? _deviceId;
String? _uid;
Future<void> init() async {
...
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
_loginState = ApplicationLoginState.loggedIn;
_uid = user.uid;
_addUserDevice();
}
...
});
}
Future<void> _addUserDevice() async {
_uid = FirebaseAuth.instance.currentUser?.uid;
String deviceType = _getDevicePlatform();
// Create two objects which we will write to the
// Realtime database when this device is offline or online
var isOfflineForDatabase = {
'type': deviceType,
'state': 'offline',
'last_changed': ServerValue.timestamp,
};
var isOnlineForDatabase = {
'type': deviceType,
'state': 'online',
'last_changed': ServerValue.timestamp,
};
var devicesRef =
FirebaseDatabase.instance.ref().child('/users/$_uid/devices');
FirebaseInstallations.instance
.getId()
.then((id) => _deviceId = id)
.then((_) {
// Use the semi-persistent Firebase Installation Id to key devices
var deviceStatusRef = devicesRef.child('$_deviceId');
// RTDB Presence API
FirebaseDatabase.instance
.ref()
.child('.info/connected')
.onValue
.listen((data) {
if (data.snapshot.value == false) {
return;
}
deviceStatusRef.onDisconnect().set(isOfflineForDatabase).then((_) {
deviceStatusRef.set(isOnlineForDatabase);
});
});
});
}
String _getDevicePlatform() {
if (kIsWeb) {
return 'Web';
} else if (Platform.isIOS) {
return 'iOS';
} else if (Platform.isAndroid) {
return 'Android';
}
return 'Unknown';
}
কমান্ড লাইনে ফিরে যান, আপনার ডিভাইসে অথবা flutter run.
আপনার অ্যাপে, একজন ব্যবহারকারী হিসেবে সাইন ইন করুন। বিভিন্ন প্ল্যাটফর্মে একই ব্যবহারকারী হিসেবে সাইন ইন করতে ভুলবেন না।
Firebase কনসোলে , আপনার ডাটাবেসে আপনার ডিভাইসগুলিকে একটি ব্যবহারকারী আইডির অধীনে দেখা যাবে।

6. ডিভাইসের অবস্থা সিঙ্ক করুন
একটি লিড ডিভাইস নির্বাচন করুন
ডিভাইসগুলির মধ্যে অবস্থা সিঙ্ক করার জন্য, একটি ডিভাইসকে লিডার বা কন্ট্রোলার হিসেবে মনোনীত করুন। লিড ডিভাইসটি ফলোয়ার ডিভাইসগুলিতে অবস্থা নির্দেশ করবে।
application_state.dart এ একটি setLeadDevice পদ্ধতি তৈরি করুন এবং RTDB এ active_device কী দিয়ে এই ডিভাইসটি ট্র্যাক করুন:
lib/src/application_state.dart
bool _isLeadDevice = false;
String? leadDeviceType;
Future<void> setLeadDevice() async {
if (_uid != null && _deviceId != null) {
var playerRef =
FirebaseDatabase.instance.ref().child('/users/$_uid/active_device');
await playerRef
.update({'id': _deviceId, 'type': _getDevicePlatform()}).then((_) {
_isLeadDevice = true;
});
}
}
অ্যাপ বারের কনটেক্সট মেনুতে এই কার্যকারিতা যোগ করতে, SignedInMenuButton উইজেট পরিবর্তন করে Controller নামে একটি PopupMenuItem তৈরি করুন। এই মেনু ব্যবহারকারীদের লিড ডিভাইস সেট করার অনুমতি দেবে।
lib/src/widgets.dart
class SignedInMenuButton extends StatelessWidget {
const SignedInMenuButton({Key? key, required this.buildContext})
: super(key: key);
final BuildContext buildContext;
List<PopupMenuEntry<String>> _getMenuItemBuilder() {
return [
const PopupMenuItem<String>(
value: 'Sign out',
child: Text(
'Sign out',
style: TextStyle(color: Colors.white),
),
),
const PopupMenuItem<String>(
value: 'Controller',
child: Text(
'Set as controller',
style: TextStyle(color: Colors.white),
),
)
];
}
void _handleSignedInMenu(String value) async {
switch (value) {
...
case 'Controller':
Provider.of<ApplicationState>(buildContext, listen: false)
.setLeadDevice();
}
}
}
ডাটাবেসে লিড ডিভাইসের অবস্থা লিখুন
একবার আপনি একটি লিড ডিভাইস সেট করে ফেললে, আপনি নিম্নলিখিত কোডটি ব্যবহার করে লিড ডিভাইসের অবস্থা RTDB-তে সিঙ্ক করতে পারেন। application_state.dart. এটি দুটি বৈশিষ্ট্য সংরক্ষণ শুরু করবে: প্লেয়ার স্টেট (প্লে বা পজ) এবং স্লাইডার অবস্থান।
lib/src/application_state.dart
Future<void> setLeadDeviceState(
int playerState, double sliderPosition) async {
if (_isLeadDevice && _uid != null && _deviceId != null) {
var leadDeviceStateRef =
FirebaseDatabase.instance.ref().child('/users/$_uid/active_device');
try {
var playerSnapshot = {
'id': _deviceId,
'state': playerState,
'type': _getDevicePlatform(),
'slider_position': sliderPosition
};
await leadDeviceStateRef.set(playerSnapshot);
} catch (e) {
throw Exception('updated playerState with error');
}
}
}
এবং পরিশেষে, কন্ট্রোলারের প্লেয়ার স্টেট আপডেট হওয়ার সাথে সাথে আপনাকে setActiveDeviceState কল করতে হবে। বিদ্যমান player_widget.dart ফাইলে নিম্নলিখিত পরিবর্তনগুলি করুন:
lib/player_widget.dart
import 'package:provider/provider.dart';
import 'application_state.dart';
void _onSliderChangeHandler(v) {
...
// update player state in RTDB if device is active
Provider.of<ApplicationState>(context, listen: false)
.setLeadDeviceState(_playerState.index, _sliderPosition);
}
Future<int> _pause() async {
...
// update DB if device is active
Provider.of<ApplicationState>(context, listen: false)
.setLeadDeviceState(_playerState.index, _sliderPosition);
return result;
}
Future<int> _play() async {
var result = 0;
// update DB if device is active
Provider.of<ApplicationState>(context, listen: false)
.setLeadDeviceState(PlayerState.PLAYING.index, _sliderPosition);
if (_playerState == PlayerState.PAUSED) {
result = await _audioPlayer.resume();
return result;
}
...
}
Future<int> _updatePositionAndSlider(Duration tempPosition) async {
...
// update DB if device is active
Provider.of<ApplicationState>(context, listen: false)
.setLeadDeviceState(_playerState.index, _sliderPosition);
return result;
}
ডাটাবেস থেকে লিড ডিভাইসের অবস্থা পড়ুন
লিড ডিভাইসের অবস্থা পড়ার এবং ব্যবহার করার জন্য দুটি অংশ আছে। প্রথমত, আপনি application_state এ লিড প্লেয়ার স্টেটের একটি ডাটাবেস লিসেনার সেট আপ করতে চান। এই লিসেনার একটি কলব্যাকের মাধ্যমে ফলোয়ার ডিভাইসগুলিকে স্ক্রিনটি কখন আপডেট করতে হবে তা বলবে। লক্ষ্য করুন আপনি এই ধাপে OnLeadDeviceChangeCallback ইন্টারফেসটি সংজ্ঞায়িত করেছেন। এটি এখনও বাস্তবায়িত হয়নি; আপনি পরবর্তী ধাপে player_widget.dart এ এই ইন্টারফেসটি বাস্তবায়ন করবেন।
lib/src/application_state.dart
// Interface to be implemented by PlayerWidget
typedef OnLeadDeviceChangeCallback = void Function(
Map<dynamic, dynamic> snapshot);
class ApplicationState extends ChangeNotifier {
...
OnLeadDeviceChangeCallback? onLeadDeviceChangeCallback;
Future<void> init() async {
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
_loginState = ApplicationLoginState.loggedIn;
_uid = user.uid;
_addUserDevice().then((_) => listenToLeadDeviceChange());
}
...
});
}
Future<void> listenToLeadDeviceChange() async {
if (_uid != null) {
var activeDeviceRef =
FirebaseDatabase.instance.ref().child('/users/$_uid/active_device');
activeDeviceRef.onValue.listen((event) {
final activeDeviceState = event.snapshot.value as Map<dynamic, dynamic>;
String activeDeviceKey = activeDeviceState['id'] as String;
_isLeadDevice = _deviceId == activeDeviceKey;
leadDeviceType = activeDeviceState['type'] as String;
if (!_isLeadDevice) {
onLeadDeviceChangeCallback?.call(activeDeviceState);
}
notifyListeners();
});
}
}
দ্বিতীয়ত, player_widget.dart এ প্লেয়ার ইনিশিয়ালাইজেশনের সময় ডাটাবেস লিসেনার চালু করুন। _updatePlayer ফাংশনটি পাস করুন যাতে ডাটাবেসের মান পরিবর্তন হলে ফলোয়ার প্লেয়ারের অবস্থা আপডেট করা যায়।
lib/player_widget.dart
class _PlayerWidgetState extends State<PlayerWidget> {
@override
void initState() {
...
Provider.of<ApplicationState>(context, listen: false)
.onLeadDeviceChangeCallback = updatePlayer;
}
void updatePlayer(Map<dynamic, dynamic> snapshot) {
_updatePlayer(snapshot['state'], snapshot['slider_position']);
}
void _updatePlayer(dynamic state, dynamic sliderPosition) {
if (state is int && sliderPosition is double) {
try {
_updateSlider(sliderPosition);
final PlayerState newState = PlayerState.values[state];
if (newState != _playerState) {
switch (newState) {
case PlayerState.PLAYING:
_play();
break;
case PlayerState.PAUSED:
_pause();
break;
case PlayerState.STOPPED:
case PlayerState.COMPLETED:
_stop();
break;
}
_playerState = newState;
}
} catch (e) {
if (kDebugMode) {
print('sync player failed');
}
}
}
}
এখন আপনি অ্যাপটি পরীক্ষা করার জন্য প্রস্তুত:
- কমান্ড লাইনে, এমুলেটর এবং/অথবা ব্রাউজারে অ্যাপটি চালান:
flutter run -d <device-name> - অ্যাপগুলো ব্রাউজারে, iOS সিমুলেটরে, অথবা Android এমুলেটরে খুলুন। কনটেক্সট মেনুতে যান, লিডার ডিভাইস হিসেবে একটি অ্যাপ বেছে নিন। লিডার ডিভাইস আপডেট হওয়ার সাথে সাথে আপনি ফলোয়ার ডিভাইসের প্লেয়ারের পরিবর্তন দেখতে পাবেন।
- এখন লিডার ডিভাইসটি পরিবর্তন করুন, সঙ্গীত চালান বা বিরতি দিন, এবং অনুসরণকারী ডিভাইসগুলি সেই অনুযায়ী আপডেট হচ্ছে তা পর্যবেক্ষণ করুন।
যদি ফলোয়ার ডিভাইসগুলি সঠিকভাবে আপডেট হয়, তাহলে আপনি একটি ক্রস ডিভাইস কন্ট্রোলার তৈরি করতে সফল হয়েছেন। আর মাত্র একটি গুরুত্বপূর্ণ ধাপ বাকি আছে।
৭. নিরাপত্তা বিধি আপডেট করুন
যদি আমরা আরও ভালো নিরাপত্তা নিয়ম না লিখি, তাহলে কেউ এমন একটি ডিভাইসে একটি অবস্থা লিখতে পারে যা তার নিজের নয়! তাই শেষ করার আগে, রিয়েলটাইম ডেটাবেস সুরক্ষা নিয়ম আপডেট করুন যাতে নিশ্চিত করা যায় যে কেবলমাত্র সেই ব্যবহারকারীই ডিভাইসটি পড়তে বা লিখতে পারেন যিনি সেই ডিভাইসে সাইন ইন করেছেন। Firebase কনসোলে, রিয়েলটাইম ডেটাবেসে নেভিগেট করুন এবং তারপরে নিয়ম ট্যাবে যান। নিম্নলিখিত নিয়মগুলি পেস্ট করুন যা শুধুমাত্র সাইন ইন করা ব্যবহারকারীদের তাদের নিজস্ব ডিভাইসের অবস্থা পড়তে এবং লিখতে দেয়:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
},
}
}
৮. অভিনন্দন!

অভিনন্দন, আপনি Flutter ব্যবহার করে সফলভাবে একটি ক্রস ডিভাইস রিমোট কন্ট্রোলার তৈরি করেছেন!
ক্রেডিট
বেটার টুগেদার, একটি ফায়ারবেস গান
- রায়ান ভার্ননের সঙ্গীত
- মারিসা ক্রিস্টির লেখা গানের কথা এবং অ্যালবামের কভার
- কণ্ঠ দিয়েছেন জেপি গোমেজ
৯. বোনাস
একটি অতিরিক্ত চ্যালেঞ্জ হিসেবে, ফ্লাটার FutureBuilder ব্যবহার করে বর্তমান লিড ডিভাইস টাইপটি অ্যাসিঙ্ক্রোনাসভাবে UI তে যোগ করার কথা বিবেচনা করুন। যদি আপনার কোনও সহায়তার প্রয়োজন হয়, তবে এটি কোডল্যাবের সমাপ্ত অবস্থা ধারণকারী ফোল্ডারে প্রয়োগ করা হয়।