إنشاء تطبيقات جوال متعددة الأنظمة الأساسية في الوقت الفعلي: أمثلة باستخدام Ionic Framework و Firebase
نشرت: 2022-03-11إحدى المشكلات الرئيسية التي تواجهها الشركات عند إنشاء تطبيق للهواتف الذكية هي التكلفة المضاعفة لإنشاء تطبيق محلي عبر منصات مختلفة. بينما قام مطورو الواجهة الأمامية الأذكياء بضبط العديد من الأنظمة الأساسية الهجينة التي تعد بالمساعدة في معالجة هذه المشكلة ، فإن Ionic Framework و Firebase هما ثنائي ديناميكي يمنحنا بشكل مشترك مرونة مذهلة في إنشاء تطبيقات الهواتف الذكية في الوقت الفعلي باستخدام JavaScript و HTML5 .
يقدم هذا البرنامج التعليمي إمكانات أدوات تطوير الأجهزة المحمولة متعددة الأنظمة الأساسية ويقدم أيضًا بعض الأمثلة Ionic و Firebase.
(ملاحظة: تفترض هذه المقالات بعض الإلمام بأساسيات إطار عمل AngularJS. إليك مقالة تمهيدية رائعة على AngularJS لمن ليس لديهم تلك الخلفية.)
تقديم الإطار الأيوني
يتكون الإطار الأيوني من ثلاثة مكونات رئيسية:
- تم تصميم إطار واجهة المستخدم المستند إلى SASS وتحسينه لواجهات مستخدم الهاتف المحمول.
- يستخدم إطار عمل JavaScript للواجهة الأمامية لـ AngularJS لبناء تطبيقات سريعة وقابلة للتطوير بسرعة.
- مترجم (كوردوفا أو PhoneGap) لتطبيقات الهاتف المحمول الأصلية مع CSS و HTML و JavaScript.
الإطار الأيوني مليء أيضًا بالعديد من مكونات CSS المفيدة خارج الصندوق.
مجد لشركة Ionic لتوفير وثائق وأمثلة ومقاطع فيديو بداية شاملة للمساعدة في تبسيط منحنى التعلم وتشغيل المطورين بسرعة.
نقدم لكم Firebase
Firebase هو نظام بيانات خلفي كخدمة بدون مخطط يوفر مزامنة البيانات في الوقت الفعلي دون الحاجة إلى كتابة أي رمز مخصص. يجعل Firebase الكثير من التطوير الخلفي قديمًا ، مما يقلل بشكل كبير من وقت تطوير الأنظمة الأساسية المتعددة.
تشمل الميزات والفوائد الرئيسية ما يلي:
- تتغير البيانات دون تغيير التعليمات البرمجية. يتم نشر جميع تغييرات البيانات للعملاء على الفور ، دون الحاجة إلى أي تعديل في كود الواجهة الخلفية.
- الكثير من المحولات. هناك محولات ، مع دعم وتوثيق جيد ، لجميع أطر عمل JavaScript الشائعة ، ومجموعات SDK للنظام الأساسي للجوّال. (استخدمنا AngularFire ، وهو رابط AngularJS لـ Firebase ، في هذه المقالة.)
- سهولة المصادقة. المصادقة في Firebase بسيطة مثل استدعاء طريقة واحدة ، بغض النظر عن طريقة المصادقة. يدعم البريد الإلكتروني البسيط وكلمة المرور وعمليات تسجيل الدخول المستندة إلى Google أو Facebook أو Twitter أو Github.
- تمكين وضع عدم الاتصال. جميع بيانات Firebase ممكَّنة في وضع عدم الاتصال ، لذلك يمكن أن يعمل التطبيق بشكل كامل (أو قريب من التشغيل الكامل) في وضع غير متصل. تتم مزامنة التطبيقات تلقائيًا عند استعادة الاتصال.
- لوحة معلومات التكوين. يمكن تهيئة الكثير من Firebase (قواعد الأمان ، على سبيل المثال) بسهولة من خلال واجهة لوحة معلومات Firebase البديهية.
- مركزية JSON. في Firebase ، يتم تخزين جميع البيانات واستردادها في شكل كائنات JSON.
يقدم Firebase أيضًا خدمات سحابية لاستضافة كود الواجهة الأمامية والتي يمكن أن تقضي وقتًا طويلاً في النشر والصيانة.
ومن الجدير بالذكر أيضًا أن Google قد استحوذت على Firebase في أكتوبر الماضي ، الأمر الذي منحها مزيدًا من الاهتمام والوضوح.
مثال على حالة استخدام بسيطة: تتبع النفقات
غالبًا ما يتقاسم رفقاء الغرفة النفقات ويعتمدون على بعضهم البعض في أوقات الحاجة. لذا ، دعونا نساعد زملاء السكن في تتبع نفقاتهم ، ومساعدتهم على التوفيق في نهاية الشهر.
لجعل الأمور أكثر إثارة للاهتمام ، دعونا نبني تطبيقًا للجوال متعدد المنصات يوفر تحديثات في الوقت الفعلي ، حتى يتمكن كل منهم من مراقبة النفقات عند حدوثها.
الآن بعد أن قررنا ما نريد بناءه وتعرّفنا على الأدوات ، فلنبدأ!
الشروع في العمل مع Ionic و Firebase
أول شيء يتعين علينا القيام به هو تثبيت Ionic. اتبع تعليمات التثبيت المتوفرة في صفحة Ionic Getting Started. (لاحظ أن Ionic تعتمد على NodeJS ، لذا ستتطلب منك التعليمات تثبيت ذلك أيضًا إذا لم يكن لديك بالفعل على جهازك).
يعد البرنامج التعليمي لمدة 5 دقائق على AngularFire مكانًا رائعًا لبدء التعرف على Firebase. وإذا كنت "مبتكرًا" أو متعلمًا ملموسًا مثلي ، فقد ترغب في سحب تطبيقي من GitHub والبدء في اللعب بالكود.
ترميز تطبيقنا متعدد المنصات
في هذا البرنامج التعليمي ، سنستخدم نموذج tabs
المقدم كجزء من التثبيت الأيوني كأساس لتطبيقنا. (يمكنك تشغيل التطبيق النموذجي باستخدام الأمر ionic start myApp tabs
.)
افتح تطبيق tabs
النموذجية في IDE المفضل لديك (أنا أستخدم Webstorm) ودعنا نبدأ في تعديله لإنشاء تطبيق زملائنا في الغرفة.
بالنسبة إلى تطبيق Ionic و Firebase ، سنحتاج إلى الشاشات الثلاث التالية:
![]() | ![]() | ![]() |
قبل إنشاء هذه الشاشات ، دعنا نزيل "شاشة تفاصيل الأصدقاء" المقدمة افتراضيًا مع نموذج التطبيق على النحو التالي:
- احذف الملف
www/templates/friend-detail.html
. - في
www/js/app.js
، قم بإزالة (أو التعليق) حالةfriend-detail.html
. - في
www/js/controllers.js
، قم بإزالة وحدة التحكمFriendDetailCtrl
المشار إليها في الحالة التي قمنا بحذفها.
الآن دعنا نغير الرموز ونص محددات علامات التبويب في أسفل الشاشة ليكون على النحو التالي:
يتم ذلك ببساطة عن طريق إجراء التغييرات التالية في www/templates/tabs.html
:
<ion-tabs class="tabs-icon-top"> <!-- My Tab --> <ion-tab title="My Expense" icon="icon ion-log-in" href="#/tab/dash"> <ion-nav-view name="tab-dash"></ion-nav-view> </ion-tab> <!-- Friends Tab --> <ion-tab title="Roomie's" icon="icon ion-log-out" href="#/tab/friends"> <ion-nav-view name="tab-friends"></ion-nav-view> </ion-tab> <!-- Account --> <ion-tab title="Account" icon="icon ion-ios7-gear" href="#/tab/account"> <ion-nav-view name="tab-account"></ion-nav-view> </ion-tab> </ion-tabs>
قبل أن نربط بياناتنا بـ Firebase ، دعنا ننشئ قائمة ونربطها بمصفوفة تسمى expenses
عن طريق إضافة الكود التالي إلى www/templates/tab-dash.html
:
<ion-view title="My Expenses"> <ion-content> <ion-list> <ion-item ng-repeat="expense in expenses|filter:user.password.email" type="item-text-wrap"> {{expense.label}} <span class="badge badge-balanced">{{expense.cost}}</span> </ion-item> </ion-list> <div class="card assertive"> <div class="item item-text-wrap"> Total Spent <span class="badge badge-positive">{{getTotal()}}</span> </div> </div> </ion-content> <ion-footer-bar> <input ng-model='label' type='text' placeholder='Type a new expense...' /> <input ng-model='cost' type="number" placeholder='$' /> <button class="button icon-left ion-plus" ng-click="addExpense($event)">Add</button> </ion-footer-bar> </ion-view>
سنحتاج أيضًا إلى توسيع DashCtrl
في www/js/controllers.js
لتشمل مصفوفة expenses
، بالإضافة إلى طريقة addExpense
وطريقة getTotal
، على النحو التالي:
.controller('DashCtrl', function($scope) { $scope.expenses = [{ by: 'email', label: 'test', cost: 10 }]; $scope.addExpense = function(e) { $scope.expenses.push({ by: < some email > label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function() { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })
مصفوفة expenses
هي ما يخزن العناصر في قائمة المصروفات ، وتضيف طريقة addExpense()
قيمة جديدة إلى مصفوفة expenses
، وتعطينا طريقة getTotal()
إجمالي جميع العناصر في المصفوفة.
يجب الآن إجراء مجموعة مماثلة من التغييرات على tab-friends.html
. حاول القيام بذلك بنفسك ، ولكن إذا واجهت مشاكل ، أو تريد التحقق من قيامك بذلك بشكل صحيح ، فيمكنك الرجوع إلى تطبيقي على GitHub.
التثبيت في Firebase
ستحتاج إلى حساب Firebase. يمكنك الاشتراك هنا للحصول على "خطة القرصنة" المجانية من Firebase.
بمجرد قيامك بالتسجيل ، ستتلقى عنوان url الخاص بك ، والذي سيبدو مثل https://<yourfirebase>.firebaseio.com
.
يتطلب تمكين Firebase في تطبيقنا تعديلين صغيرين لتطبيقنا.
أولاً ، نحتاج إلى تضمين نصوص Firebase النصية في ملف www/index.html
الخاص بالتطبيق على النحو التالي:
<script src='https://cdn.firebase.com/js/client/1.1.1/firebase.js'></script> <script src='https://cdn.firebase.com/libs/angularfire/0.8.0/angularfire.min.js'></script> <script src="js/app.js"></script>
بعد ذلك ، نحتاج إلى إضافة وحدة Firebase إلى تطبيقنا عن طريق إضافة 'firebase'
إلى القائمة في وحدة AngularJS 'starter'
بنا:
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'firebase'])
تم تمكين Firebase الآن ، تمامًا مثل أي وحدة AngularJS أخرى.
سيعلمك البرنامج التعليمي AngularFire لمدة 5 دقائق إنشاء مراجع البيانات في وحدات التحكم. بالنسبة إلى التطبيق التجريبي الخاص بنا ، قررت الاحتفاظ بهذه المراجع في خدمة منفصلة (لأن هذا يجعل من السهل جدًا صيانتها وتحديثها إذا تم تغيير عنوان url الخاص بالجذر). لإنشاء هذه الخدمة ، أضف ما يلي إلى www/js/services.js
:

.factory('fireBaseData', function($firebase) { var ref = new Firebase("https://luminous-fire-3429.firebaseio.com/"), refExpenses = new Firebase("https://luminous-fire-3429.firebaseio.com/expenses"), refRoomMates = new Firebase("https://luminous-fire-3429.firebaseio.com/room-mates"); return { ref: function() { return ref; }, refExpenses: function() { return refExpenses; }, refRoomMates: function() { return refRoomMates; } } });
يضيف الكود أعلاه ثلاثة عناوين url مرجعية. واحد للجذر واثنان للمجموعات التي أطلقنا عليها اسم expenses
room-mates
.
تتم إضافة مجموعة جديدة إلى Firebase ببساطة عن طريق إضافة اسمها إلى نهاية عنوان url الخاص بالجذر . لذلك لإنشاء مجموعة expenses
التي نحتاجها ، كل ما نحتاجه هو ما يلي:
https://<yourfirebase>.firebaseio.com/expenses
سيؤدي ذلك إلى إنشاء مجموعة expenses
، ويمكننا بعد ذلك البدء في إضافة عناصر إليها.
حسنًا ، يمكننا الآن ربط مجموعة النفقات من Firebase لاستبدال مصفوفة النفقات "الوهمية" التي أنشأناها سابقًا. يتم ذلك عن طريق تعديل DashCtrl
في www/js/controllers.js
على النحو التالي:
.controller('DashCtrl', function($scope, fireBaseData, $firebase) { $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.addExpense = function(e) { $scope.expenses.$add({ by: < someemail > , label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function() { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })
يجب إجراء مجموعة مماثلة من التغييرات على FriendsCtrl
. أوصي مرة أخرى بمحاولة القيام بذلك بنفسك ، ولكن إذا واجهت مشاكل ، أو تريد التحقق من قيامك بذلك بشكل صحيح ، فيمكنك الرجوع إلى تطبيقي على GitHub.
للتحقق من أنه يعمل ، أثناء تشغيل التطبيق على عميلين مختلفين ، أضف مصروفًا جديدًا ، وتأكد من ظهوره في القائمة على كلا العميلين. إذا كان يعمل… woo-hoo! لقد نجحت الآن في توصيل تطبيق Ionic الخاص بك باستخدام Firebase!
يمكنك اختبار تطبيقك متعدد المنصات على أجهزة مختلفة عن طريق توصيل جهاز ionic run android
أو ionic emulate ios
. راجع وثائق Ionic للحصول على مزيد من المعلومات حول اختبار تطبيقك.
إدارة الحساب والأمان باستخدام Firebase
على الرغم من أن الوظائف الأساسية تعمل الآن ، إلا أن إحدى المشكلات الخطيرة هي أن تطبيقنا غير آمن تمامًا حاليًا. يمكن للعالم بأسره رؤية نفقاتك ، دون الحاجة إلى أي أذونات أو عمليات تسجيل دخول. من الواضح أن هذا يحتاج إلى معالجة.
يوفر Firebase إطار عمل مصادقة قويًا وبسيطًا باستخدام "القواعد". هناك الكثير الذي يمكن القيام به باستخدام لغة قواعد Firebase. (راجع وثائق أمان Firebase لمزيد من التفاصيل.)
في حالتنا ، سنكتب قاعدة بسيطة للغاية لمنع المستخدمين غير المصرح لهم من الوصول إلى بياناتنا. للقيام بذلك ، افتح عنوان url الخاص بك ، وانقر فوق "الأمان والقواعد" في شريط الإجراءات الأيسر ، والصق الرمز أدناه في القواعد الخاصة بك ، ثم انقر فوق "حفظ".
{ "rules": { ".read": "auth != null", ".write": "auth != null" } }
إذا قمت بتشغيل التطبيق الخاص بك الآن ، ستلاحظ عدم وجود بيانات. يمكنك حتى محاولة فحص طلبك باستخدام أدوات المتصفح وسترى رسالة في وحدة التحكم الخاصة بك تفيد بأنك غير مخول لعرض البيانات.
إنشاء حسابات المستخدمين وتمكين تسجيل الدخول
يمكنك مصادقة المستخدمين عن طريق السماح لهم بإنشاء تركيبة بريد إلكتروني / كلمة مرور خاصة بهم ، أو استخدام أي من بيانات اعتماد تسجيل الدخول الحالية إلى Google أو Facebook أو Twitter أو Github. لمصادقة البريد الإلكتروني / كلمة المرور ، يقدم Firebase مجموعة كاملة من طرق واجهة برمجة التطبيقات لتغيير كلمة المرور وإعادة تعيينها وما إلى ذلك. يمكن العثور على مزيد من المعلومات حول المصادقة باستخدام Firebase في دليل Firebase.
بالنسبة لتطبيقنا التجريبي ، سننشئ حسابين مستخدمين عبر واجهة Firebase. يمكن القيام بذلك عن طريق الانتقال إلى عنوان url الخاص بجذر Firebase والقيام بما يلي:
- انقر فوق تسجيل الدخول والمصادقة على شريط الإجراءات على الجانب الأيسر.
- حدد خانة الاختيار لتمكين مصادقة البريد الإلكتروني وكلمة المرور.
- قم بالتمرير لأسفل للعثور على "نموذج إضافة حسابات جديدة"
- أضف حساباتك باستخدام "إضافة مستخدم جديد".
لتمكين واجهة تسجيل الدخول للمستخدمين ، قم أولاً بإضافة الكود التالي إلى www/templates/tab-account.html
:
<ion-view title="Account"> <ion-content> <div class="list" ng-show="showLoginForm"> <label class="item item-input"> <span class="input-label">Email</span><input type="text" ng-model="em"/> </label> <label class="item item-input"> <span class="input-label">Password</span><input type="password" ng-model="pwd"/> </label> <button class="button button-block button-positive" ng-click="login(em, pwd)">Login</button> </div> <div class="card" ng-hide="showLoginForm"> <div class="item item-text-wrap">You are logged in as {{user.password.email}}</div> </div> <button class="button button-stable" ng-click="logout()" ng-hide="showLoginForm">Logout</button> </ion-content> </ion-view>
ثم أضف ما يلي إلى AccountCtrl
في www/controller.js
:
.controller('AccountCtrl', function($scope, fireBaseData) { $scope.showLoginForm = false; //Checking if user is logged in $scope.user = fireBaseData.ref().getAuth(); if (!$scope.user) { $scope.showLoginForm = true; } //Login method $scope.login = function (em, pwd) { fireBaseData.ref().authWithPassword({ email : em, password : pwd },function(error, authData) { if (error === null) { console.log("User ID: " + authData.uid + ", Provider: " + authData.provider); $scope.user = fireBaseData.ref().getAuth(); $scope.showLoginForm = false; $scope.$apply(); } else { console.log("Error authenticating user:", error); } }); }; // Logout method $scope.logout = function () { fireBaseData.ref().unauth(); $scope.showLoginForm = true; }; });
أحد الأشياء المهمة التي يجب أن تكون على دراية بها من وجهة نظر الأمان هو أن عمليات تسجيل الدخول إلى Firebase تكون مستمرة بشكل افتراضي . لذلك ، إذا كنت تريد أن يحتاج المستخدم إلى تسجيل الدخول في كل مرة يتم فيها تشغيل التطبيق ، فستحتاج إلى تعديل تكوين Firebase وفقًا لذلك. للقيام بذلك ، مرة واحدة فقط بعد تسجيل دخول ناجح ، قم بتنفيذ الكود التالي:
var r = $firebase(fireBaseData.refRoomMates()).$asArray(); // NOTE: Substitute the email addresses of your two user accounts in the line below r.$add(["[email protected]","[email protected]"]);
يمكنك إضافة هذا في وحدة التحكم في الحساب بعد تسجيل الدخول بنجاح ، أو وضع نقطة توقف بعد تسجيل الدخول بنجاح وتشغيله في مراقب وحدة التحكم الخاصة بك.
التصفية على أساس المستخدم
لا يزال تطبيق الأجهزة المحمولة متعدد الأنظمة الأساسية يفتقد ميزة مهمة واحدة. نريد تمييز نفقاتك عن نفقات زميلك في السكن. الآن وقد أنشأنا حسابين ، نحتاج فقط إلى تصفية البيانات من وجهات نظرنا.
نحتاج أولاً إلى تعديل dashCtrl
في www/js/controllers.js
من أجل (أ) الحصول على بيانات المستخدم الحالي في نطاق $ و (ب) حفظ أي نفقات مضافة للمستخدم الحالي:
.controller('DashCtrl', function($scope, fireBaseData, $firebase) { $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.user = fireBaseData.ref().getAuth(); // ADD MESSAGE METHOD $scope.addExpense = function(e) { $scope.expenses.$add({ by: $scope.user.password.email, label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function () { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })
بعد ذلك ، نحتاج إلى إضافة عامل تصفية في www/templates/tab-dash.html
لإظهار نفقات المستخدم الحالي فقط:
<ion-item ng-repeat="expense in expenses|filter:user.password.email" type="item-text-wrap">
حسنًا ، الشاشة الرئيسية مثالية الآن. يمكن للمستخدم مشاهدة وإضافة نفقاته الخاصة فقط.
الخطوة الأخيرة والأخيرة هي تمكين مشاركة قائمة النفقات الكاملة بين زملائك في الغرفة. للقيام بذلك ، قم بتغيير www/templates/tab-friends.html
لإضافة هذا الفلتر:
<ion-item ng-repeat="expense in expenses|filter:roomiesEmail" type="item-text-wrap">
ثم قم بتعديل FriendsCtrl
في www/controllers.js
على النحو التالي:
.controller('FriendsCtrl', function($scope, fireBaseData, $firebase) { $scope.user = fireBaseData.ref().getAuth(); $scope.expenses = $firebase(fireBaseData.refExpenses()).$asArray(); $scope.roomies = $firebase(fireBaseData.refRoomMates()).$asArray(); $scope.roomies.$loaded().then(function(array) { //array = [[set1_rm1_email, set1_rm2_email], [set2_rm1_email, set2_rm2_email] ...] for (var i = 0; i < array.length; i++) { if (array[i][0] === $scope.user.password.email) { $scope.roomiesEmail = array[i][1]; } else if (array[i][1] === $scope.user.password.email) { $scope.roomiesEmail = array[i][0]; } } $scope.$apply(); // NOTE: For simplicity, this demo only supports the 2-roommate use case }); $scope.addExpense = function(e) { $scope.expenses.$add({ by: $scope.roomiesEmail, label: $scope.label, cost: $scope.cost }); $scope.label = ""; $scope.cost = 0; }; $scope.getTotal = function () { var rtnTotal = 0; for (var i = 0; i < $scope.expenses.length; i++) { rtnTotal += $scope.expenses[i].cost; } return rtnTotal; }; })
هذا هو! قم بتثبيت / تحديث التطبيق على كل من جهازك وجهاز زميلك في الغرفة ويجب أن تكون جاهزًا!
يتم إحتوائه
يبدأ مثالنا البسيط في خدش سطح ما يمكن إنجازه - ومدى سهولة إنجازه - باستخدام Ionic و Firebase. إنهما حقًا ثنائي قوي لبناء تطبيقات هاتف ذكي متعددة الأنظمة في الوقت الفعلي باستخدام JavaScript و HTML5.