Login Authentication in Android Using Database
Mobile apps need a backend. They store settings & data, high scores, check licenses and generate statistics. All these use cases have one thing in common: they use a central database. Coding a full-blown backend takes a lot of time. Think about end-to-end security, communication interfaces and database structure. When you then get to details like concurrent access, it gets tricky. Luckily,Google Firebasetakes care of all these issues for you. It's a ready-to-use cloud-hosted database with full authentication support. In contrast to a traditional SQL database, Google Firebase stores JSON data sets (->NoSQL). This gives you more flexibility in your data structure. On top of that, you can subscribe to real-time data changes. You'll get notified about updates made to the data, for example by other users. The service does offer a simpleREST API. But the most efficient communication is a publish & subscribe model via websockets. That sounds complicated? Google offers a separate SDK for each platform. With Felgo & Qt, you don't need to worry about platform differences. Felgo includes a cross-platformGoogle Firebase Realtime Database plugin. The same QML / JavaScript-based API works for both Android & iOS. If you need help with that, consult or outsource yourapp development with Felgo. In this Firebase tutorial, you'll complete the full journey from start to end. You start with a project template of Qt Creator. Next, you'll set up the Firebase service in the cloud. Another important task is user authentication. Most impressive: live database updates from & to your cross-platform app. The scenario is a simple shopping list. It's a generic app that includes everything most apps need. Authentication, plus adding, updating and deleting items. Once you understand the concepts, it's easy to adapt them to your own scenario. If you're impatient, skip right to the final project source code onGitHub. You can also watch the video version of this tutorial on YouTube. It is very much in-depth and covers every single step of the process. Curious to dive right into the cloud database? Well, you will need your "app package name" for Android and the "iOS bundle ID" when setting up Firebase. Thus, start with the app and make your life easier. Open Qt Creator and create a new project. Use the "Felgo Apps" > "Master-Detail Application". This gives you great boilerplate code for any list-type app. In step 2, choose the kits for the target platforms: Android and/or iOS. Take special note of the "Felgo Project Properties" page (step 3). Here, you define the app identifier, which you will also need for the Firebase setup. In this case, choose com.vplay.ShoppingList. Google offers different Firebase samples for individual platforms & tools. With Felgo, you run the same code across Android & iOS. Activate the "Google Firebase" plugin. It includes ready-made cross-platform code to interact with the Google cloud! If you target both Android and iOS, you'll want to test your app on both platforms. Felgo Live immediately deploys and executes any code changes on any connected phone. You can even connect and test on iOS phones while developing on Windows. You save an incredible amount of time: no more re-building, deploying and testing. To get started, download the Felgo Live app from the app store:Android/iOS. Next, make sure your development computer and the phone are on the same local network. Start the Felgo Live app on your phone and connect it to your Live Server. If your Live Server is not running yet, click on "Live Run" in Qt Creator, to start developing with live code reloading! Your app currently shows a watermark that you're running a trial of the Firebase plugin. That's fine for your first testing steps! To get rid of the trial watermark and the license reminders, you need the Felgo Indie license. If you do not have an Indie license, you can continue using the Firebase plugin in trial mode, without generating a license key. Authorization works through a license key for your app. Go tohttps://felgo.com/upgradeLicense. Select the "Google Firebase" plugin. Next, click the green "Generate License Key" button at the bottom of the page. Next, enter your app identifier (e.g., "com.vplay.ShoppingList"). The suggested version "1" is correct – it's the default in every new project. Copy the new license key to your code, add it to the licenseKey property in your Main.qml file. The watermark disappears. This video shows the original Master-Detail sample app. When inserting the license key to the code, the app instantly reloads – without the watermark. Afterwards, you see a brief demo of the initial app functionality. Congratulations, your master-detail app is running on the phone! Now, it's time to create the Google Firebase Realtime database. This serves as complete lightweight backend for the shopping list example app. To create a Firebase account, go to theFirebase homepage. Login with your Google Account to see the empty console. The project you create runs great with the free account. You don't need to worry about payments. First, click on "Add project". Give your project a name to recognize it in your console: "ShoppingList". The "Project ID" is auto-generated with a number, as it needs to be globally unique. You can customize the ID if you like. Note that your users will never see this ID, though – so don't spend too much time here. Click on "CREATE PROJECT". In a few seconds, the project dashboard greets you with the overview: Your shopping list app stores the items in the cloud. Grant your app access to the Firebase project. Click on the big circle for your target platform: iOS or Android. Enter the package name again. The optional "app nickname" is only for internal use inside your dashboard. The Firebase wizard now prompts to download the config file. Download this file and store it somewhere on your computer. The major parts of the config file look like this. They contain all the information you need to connect your app to Firebase. For your Felgo project, you could use this config file. But it's easier to copy the API keys to the plugin config, as you will see below. So, skip steps 3 + 4 of the Firebase wizard. In Qt Creator's "Projects" view, right-click the "qml" folder. Select "Add new…". Choose the "Felgo Apps" -> "Item" template. In the following "Item details" dialog, enter: The generated file is almost empty. Change the default generated ID from "item" to "dataModel". As you are using the Firebase plugin, add the following line to the import section at the beginning of the file: TheFirebaseConfig QML elementencapsulates all connection settings – for both Android and iOS. Add it to your item. Your data model now looks like this: Item { FirebaseConfig { projectId : "<your project ID, from project_info | project_number, e.g., 82701038584 or shoppinglist-vplay>" applicationId : Qt.platform.os == = "android" Your app will store a list of items in the database. Firebase is a JSON-basedNoSQL database. What does it do? This is what your database will look like: The database is a tree of items. Each can have children and any structure. That makes the database much more flexible than tables in traditional SQL. Some of the structure is pre-defined by Firebase; some is coming from your app. A quick overview, before you dive in: In your browser, return to the Firebase dashboard. Select "Database" on the left. Next, click on "Get Started" in the "Realtime Database" block. The Cloud Firestore is currently still in beta. That's why it's not recommended for production use yet. We will take a closer look in a future tutorial. Next up is the "Security rules for Realtime Database" dialog. It's a good idea to start with proper authentication right away, instead of plugging it in later. Your app needs to recognize, differentiate and securely authorize users. TheFirebase Authentication servicemakes this easy. It supports multiple authorization providers: Facebook, Google Account, Twitter, GitHub and even a phone-based user authentication per SMS. Firebase even lets you use "anonymous" authentication. This means the user does not have to do any authentication step in order to use the Firebase Database. To get started, we will use the Email / Password variant. Firebase takes care of managing users and even supports sending password reset emails. To activate it, go to the Authentication section (1) of your Firebase dashboard. Next, choose "Sign-In Method" (2). Click on "Email/Password" (3) to expand this section. Enable it (4) and save the changes (5). In the "Templates" section, you could further customize the behavior. E.g., a custom confirmation email text when a user signs up. Felgo simplifies the authentication process. The engine includes a predefined itemFirebaseAuththat handles the cloud communication. The app architecture is clear: You start by adding the FirebaseAuth item to your DataModel. It is simple to use: assign an ID and give it a reference to the config item you created before. Also, add two signals ("loggedIn", "loggedOut") to your DataModel. They inform the app about the user's login status. FirebaseAuth { onLoggedIn : { onAuthenticatedChanged : if(authenticated) dataModel.loggedIn() FirebaseAuth offers three important slots for reacting to cloud responses: Now, your app already handles the status change responses coming from Firebase. But, you still need to trigger the login! The FirebaseAuth item includes convenient methods for triggering authentication tasks. Your DataModel.qml encapsulates the communication with Firebase. So, you include simple methods that forward the requests to Firebase. function loginUser(email, password) { function logoutUser() { You might wonder why you should do this. After all, the new methods are an exact replica of the existing. Once you expand your app, you might want to surround these calls with extra checks. E.g., you could test if the email address is valid. So, it's a good idea to think of a good architecture right from the start. The example app already includes two sample pages for Firebase, which we will not use however. They are a concise essence of what you can do with Firebase. In our sample, we use Firebase as part of the complete app architecture. Create a new page: LoginPage.qml. It's will be a simple page with 2 text boxes and a button. A checkbox switches between login and new user registration. Copy the source codefrom the GitHub sampleinto your new page. Important for the concept is that the page emits a signal once the user taps the button: "login(bool isRegister, string email, string password)". The parameters include everything Firebase needs to perform the login. Main.qml wires this signal to your DataModel. This connection establishes the link from the UI to the Firebase cloud. Replace the current contents of Main.qml with: App { DataModel { NavigationStack { LoginPage { onLogin : { Component { In the code snippet above, you see that the App also owns the DataModel item with id "dataModel". The "App" item connects your app's components. Here, you establish a direct connection: LoginPage's "onLogin"-slot -> methods of the DataModel (registerUser / loginUser). Once the login process completes, the "onLoggedIn" slot within the DataModel pushes the "shoppingListPage" to the navigation stack. Remember: that's the ID of the MasterPage from the template. With this approach, navigating back in the Android / iPhone-UI pops the page. This automatically triggers the logout process in Firebase. Your app also returns to the previous page on the navigation stack – the LoginPage. Test your app! You can already register a new user in Google Firebase and log in: The Firebase Realtime Database is a NoSQL DB. It's efficient and low-latency, and especially targeted towards mobile clients. The Realtime Database stores all data in a JSON tree. Unlike a SQL database, there are no tables and rows. That makes Firebaseefficient for simple and rather flat data. It's the ideal target for many apps, like our shopping list example. What about pricing? You get charged for bandwidth and storage. The free "Spark Plan" already grants you 100 simultaneous connections, 1 GB of data storage and 10 GB / month data transfer. Upgrades to the "Flame Plan" and the "Blaze Plan" give you even more data allowance. Google has agood comparison table, highlighting the differences between different Firebase plans. The following video shows a screen recording of what's happening behind the scenes: The hierarchy of the JSON model is as follows: This is the default hierarchy, based on customizable rules. But, you have full control tocustomize every aspect. The interface to Firebase is powerful. All connected clients get real-time updates. Plus, it offers full offline-support. When the user goes online again, the changes sync to the cloud. Felgo includes a single item that works across Android and iOS. Especially for multi-platform scenarios, you'll love this. TheFirebaseDatabase QML typeoffers methods to retrieve and update the JSON tree in the Firebase cloud. Callbacks inform you whenever the items changed and when operations complete. In your app architecture, you set up a data flow from the user interface to the Firebase database in the cloud: A "+" button in the navigation bar (1) triggers an input dialog (2). It sends the new shopping item name to the DataModel. The DataModel abstracts the Firebase Realtime database (3). The FirebaseDatabase item from Felgo performs the cloud interaction (4). Whenever the model data in the cloud changes, your app gets a callback (5). This updates the cached list of shopping items (6). Add the following code snippet to your DataModel: FirebaseDatabase { realtimeUserValueKeys : [dbKeyAllShoppingItems] // If the last shopping item gets deleted, the database returns null function shoppingItemsLoaded(value) { TheFirebaseDatabaseitem (with id database) requires a reference (config) to the generic Firebase connection configuration item with your app keys. Your app registers for real time updates by adding keys to therealtimeUserValueKeysproperty. TherealtimeUserValueChanged signalfires every time the monitored keys change. E.g., by another family member sharing your shopping list account. The signal is also emitted when the connection to the database is ready after a successful login. So, it's the only method we need to retrieve & update the shopping list items! The shoppingItemsLoaded(value) function then assigns the items to a public property of the DataModel. It also ensures the list never gets null by using an empty array "{}" in case no shopping items have been created so far. For debugging, you can print the raw JSON data to the console. During development, this helps to see what Firebase transmits to your app. In the video example above, this would be: The Felgo wizard already created the basic structure of a master list / detail app. You can use this as a base for customizing it to the shopping list scenario. You need the following functionality: You assign the keys of the dataModel.shoppingItems array as the model for the list view. The "ListPage" instantiates rows for each item in the model. The minimal code of the MasterPage: model : Object.keys(dataModel.shoppingItems) signal addNewShoppingItem(string text) rightBarItem : IconButtonBarItem { onClicked : { You start with adding shopping items to your Firebase Realtime Database. The "+" button appears in the navigation bar. You achieve this through therightBarItem, provided by the basePage QML type. Make your life even easier by using the predefined IconType.plus symbol. Thanks to Felgo's multi-platform support, the button is always placed in the correct screen area for Android and iOS. To enjoy even more pre-built functionality, use theListPage QML typeas base item of this QML file. "ListPage" derives from the more genericPage type. On top of the generic Page, it includes a full-screenAppListView item. It'll contain all your shopping items. Plus, it even offers advanced features like fully-animated pull-to-refresh. When the user taps the "+" button, your app shows a simple single-line text entry dialog (InputDialog). For a good architecture, you send the user's new shopping item via a signal to the DataModel. So, define a signal addNewShoppingItem(string text) in the ListPage (with id masterPage). The callback function of the InputDialog then emits the signal. It sends the text entered by the user as parameter. Now, connect the MasterPage's signal to the DataModel's slot. Like before for the login, define it in Main.qml. Extend your previous MasterPage definition in Main.qml: Again, the most interesting code is in DataModel. It stores the new shopping item in the Firebase Realtime Database. Add this method to your DataModel: function loadingFinished() { The addShoppingItem function constructs an object "shoppingItem". The method database.setUserValue() serializes it to JSON. Next, it's sent to the Firebase database in the cloud. The setUserValue() method has three parameters: Your app already adds items to the real time database in the cloud. The last major feature is the UI to show the shopping items! Back in MasterPage.qml, extend the code of ListPage with a delegate. The delegate instantiates for each individual item in your shopping list. // modelData == key of shopping item in data model SimpleRow { text : container.shoppingItem.text || "" TheSwipeOptionsContainer QML itemsupports swipeable list rows in Android and iOS apps. In the next step, you will add the feature to delete the item through the swipe gesture. Usually, list items have a very simple structure: one or two lines of text, plus an optional image. The Felgo itemSimpleRowprovides a ready-made layout. The three corresponding properties are: text, detailText and icon. There's one simple trick you need to be aware of. How to access the entire individual properties of the currently shown item? The model you assigned to the ListPage only contained the keys. But, the line needs to access the full data of the shopping item! This includes the name and the date. Where can you get the complete data? It's stored in the DataModel. Thus, you access it based on the key stored in the list view model. The relevant item data is then available through the readonly property shoppingItem. Its declaration is part of the delegate you inserted a moment ago. This is the relevant line, for reference: Here, you see your app in action: After the user logs in to the app on the phone, he adds an item with the text "Felgo" to the shopping items list. Thanks to the real-time database features, the item immediately appears in the web view. Google highlights it in green to make you aware of the change. Even more amazing: real-time changes also work in the other direction. Try deleting a shopping item in the database view on the web. It'll immediately disappear on the smartphone. No extra code was necessary. In DataModel, Felgo's FirebaseDatabase item emits a signal every time the remote database changes. In your app, you reload the data based on its new contents. Your app already handles real-time updates from the web. Now, the final extension for you to write: let the user delete the shopping items from the phone! The SwipeOptionsContainer for the ListPage items contains useful out-of-the-box functionality. Like many other advanced apps, users can swipe the item to a side. In your QML, you specify the item to appear. In this case, choose a SwipeButton with red background color and an "X" icon. Now, whenever the user swipes and clicks on the delete button, its onClicked slot executes. backgroundColor : "red" // Date is also the unique ID In the onClicked slot, you must inform the real-time database about the deleted item. For this, add a second new signal for the ListPage item in the MasterPage: As parameter, your code sends the ID of the item to delete. Remember – we used the creation date as unique ID! The app must forward the signal to the data model. This architecture keeps the view separated from the model. So, extend the MasterPage component in Main.qml to forward the signal. For reference, this is what the complete component definition looks like now: Like adding a shopping item, the signal triggers a JavaScript function in the data model. To stick to the naming scheme, call it deleteShoppingItem(id). As a final step, jump into DataModel.qml and add the function implementation. It's only one line and resembles the call to add an item. The only difference: instead of setting the item data as value in the database, you now send null. The result: the item is deleted. The animation below shows how deleting item on the phone works. Again, the left side shows the real-time database view of Firebase on the web. Items instantly disappear in the web view when the user has deleted them on the phone. Your cross-platform shopping list app is powerful: For shopping lists, it's not needed too often. But, for other use cases you might also want to include functionality to edit items. As a bonus, we've added the necessary code to the full example on GitHub. Check it out to see how modifying existing items works! Also, the open source example is a great reference, as it includes extra code comments. By combining the Firebase real-time database with Qt and Felgo, you gain support foruser authenticationandshared NoSQL-databaseswith a few lines of code. If you'd also like to store larger files in the cloud, check out theFirebaseStorage QML type. Getting Started
Watch this Tutorial on YouTube
Master-Detail UI for your Cloud Backend
Live Testing on Android & iOS
Felgo Plugin License
Create the Firebase Project
Connect Your App to Firebase
{
"project_info" : {
"project_number" : "766025596428",
"firebase_url" : "https : //shoppinglist-vplay.firebaseio.com",
"project_id" : "shoppinglist-vplay",
"storage_bucket" : "shoppinglist-vplay.appspot.com"
},
"client" : [
{
"client_info" : {
"mobilesdk_app_id" : "1 : 766000006428 : android : a28d200000001c88",
"android_client_info" : {
"package_name" : "com.vplay.ShoppingList"
}
},
"api_key" : [
{
"current_key" : "AIzaSyCvAzxxxxxxxxxxxxxxxxxEXg-cv8TikY0"
}
]
}
],
"configuration_version" : "1"
}
import Felgo 3.0
import QtQuick 2.0
import Felgo 3.0
id : dataModel
id : fbConfig
databaseUrl : "<your database URL, from project_info | firebase_url, e.g.,: https : //shoppinglist-vplay.firebaseio.com>"
apiKey : Qt.platform.os == = "android"
? "<your Android API key, from client | api_key | current_key>"
: "<your iOS API key>"
? "<your Android application ID, from client | client_info | mobilesdk_app_id>"
: "<your iOS application ID>"
}
} Firebase Database Setup
Create the Cloud Database
Firebase Authentication
Firebase Login from Your Client App: Architecture
Its onLoggedIn slot triggers navigating from the LoginPage to the ShoppingListPage.
Its onLogin slot executes when the user taps the button to login / register.Firebase Authentication: Callbacks from the Cloud
signal loggedIn
signal loggedOut
id : auth
config : fbConfig
if(!success) nativeUtils.displayMessageBox(qsTr("Login failed"), qsTr("Reason : %1").arg(message), 1)
}
onUserRegistered : {
if(!success) nativeUtils.displayMessageBox(qsTr("Register failed"), qsTr("Reason : %1").arg(message), 1)
}
}
Firebase: Triggering Login, User Registration and Logout
function registerUser(email, password) {
auth.registerUser(email, password)
}
auth.loginUser(email, password)
}
// logout is instant and always works (there is no callback)
auth.logoutUser()
} Firebase Login Flow in the App
import Felgo 3.0
import QtQuick 2.5
import "model"
id : app
licenseKey : "<The Felgo Plugin license key you generated earlier>"
id : dataModel
onLoggedIn : stack.push(shoppingListPage)
}
id : stack
id : loginPage
if(isRegister) {
// Call the user registration method from our data model,
// which then forwards the request to Google Firebase
dataModel.registerUser(email, password)
} else {
// Similar approach sending a user login request to Firebase.
dataModel.loginUser(email, password)
}
}
}
}
id : shoppingListPage
MasterPage {
// User navigated back in the UI - send logout request to Firebase
onPopped : dataModel.logoutUser()
}
}
} Firebase Realtime Database & Pricing
Firebase Database Structure & Live Updates
Connect to the Firebase Realtime Database
Firebase Database Configuration & Item Storage
// Stores a list of all shopping items for the user
property var shoppingItems : ( { })
// Name of the root node for the user's shopping items in the Firebase database
readonly property string dbKeyAllShoppingItems : "shoppinglist-user"
id : database
config : fbConfig
// the plugin then gives success==false, so don't check the success parameter
onRealtimeUserValueChanged : if(key == = dbKeyAllShoppingItems) shoppingItemsLoaded(value)
onFirebaseReady : console.log("db ready")
onWriteCompleted : console.log("write completed")
}
// When the last item is deleted, firebase deletes the whole structure, returning null
dataModel.shoppingItems = value || { }
console.log(JSON.stringify(dataModel.shoppingItems))
} Firebase Realtime Updates
{ "1529230812085" : { "date" : 1529230812085,"text" : "Milk" },"1529230821894" : { "date" : 1529230821894,"text" : "Apples" } }
Prepare the Shopping List Page (MasterPage)
Add Shopping Items
import Felgo 3.0
import QtQuick 2.5
ListPage {
id : masterPage
title : qsTr("Shopping Items")
icon : IconType.plus
InputDialog.inputTextSingleLine(app,
"What to add to the list?", // message text
"Input here", // placeholder text
function(ok, text) {
if(ok) {
masterPage.addNewShoppingItem(text)
}
})
}
}
} Store Shopping Items in the Firebase Realtime Database
Component {
id : shoppingListPage
MasterPage {
onAddNewShoppingItem : dataModel.addShoppingItem(text)
// User navigated back in the UI - send logout request to Firebase
onPopped : dataModel.logoutUser()
}
}
function addShoppingItem(text) {
var time = new Date().getTime()
var shoppingItem = {
date : time,
text : text
}
console.log("Adding item...")
// Use date milliseconds as unique ID in DB
database.setUserValue(dbKeyAllShoppingItems + "/" + time, shoppingItem, loadingFinished)
}
console.log("Loading finished")
}
List Shopping Items in Your App
delegate : SwipeOptionsContainer {
id : container
readonly property var shoppingItem : dataModel.shoppingItems[modelData] || { }
width : parent.width
detailText : new Date(container.shoppingItem.date).toLocaleString() || ""
}
}
readonly property var shoppingItem : dataModel.shoppingItems[modelData] || { }
Delete Items from the NoSQL Firebase Database
rightOption : SwipeButton {
anchors.fill : parent
icon : IconType.remove
onClicked : {
container.hideOptions()
masterPage.deleteShoppingItem(container.shoppingItem.date)
}
}
signal deleteShoppingItem(real id)
Component {
id : shoppingListPage
MasterPage {
onAddNewShoppingItem : dataModel.addShoppingItem(text)
onDeleteShoppingItem : dataModel.deleteShoppingItem(id)
// User navigated back in the UI - send logout request to Firebase
onPopped : dataModel.logoutUser()
}
}
function deleteShoppingItem(id) {
database.setUserValue(dbKeyAllShoppingItems + "/" + id, null, loadingFinished)
}
Going Further
More Posts Like This
Machine Learning: Add Image Classification for iOS and Android with Qt and TensorFlow
Qt AR: Why and How to Add Augmented Reality to Your Mobile App
Release 2.17.0: Firebase Cloud Storage, Downloadable Resources at Runtime and Native File Access on All Platforms
Login Authentication in Android Using Database
Source: https://blog.felgo.com/cross-platform-app-development/firebase-qml-tutorial-android-ios-create-an-app-with-realtime-database-and-login
0 Response to "Login Authentication in Android Using Database"
Post a Comment