Before starting the walkthrough, it is recommended that you have followed these walkthroughs in order:
It is also recommended that you have read through these conceptual topics in order to get a better understanding:
- Working with Background Sync Service
- Using Push Notifications for Data Sync
- Preparing Google Cloud Messaging Service
- Preparing Apple Push Notification Service
To use this walkthrough, you will need to use at least Crosslight version 5.0.5000.626-experimental in order to achieve the desired result. You also need to have Mobile Studio for Windows installed. If you haven't done so, download here.
Let's get started.
Preparing the Project
In this tutorial, we're going to continue from the previous tutorial, where you've learned how to perform various data operations to SQLite storage. Download the sample here (from the previous tutorial). After you've downloaded the sample, you're ready to proceed.
We're going to modify the current database models and EDMX to associate each ToDo entry with a user. This requires us to change the app design a bit. For instance, when the user launches the app for the first time, we're going to check if the user has logged in to the application. If not, we'll present a modal screen that prompts user to enter his/her username before using the application. Then, upon each synchronization attempt in the server, we'll send a push notification to the other registered device, which will then trigger an auto-synchronization process by utilizing the background sync capabilities of each platform (SyncAdapter on Android and Background App Refresh on iOS).
Modifying the Database
Before attempting the said action, we'll need to change the database design a bit. Open the CrosslightDb.mdf inside CrosslightToDo.WebAPI/AppData folder. When you try to open the database, you might get the following error.
To resolve this issue, it's pretty simple. All you need to do is open Web.config file inside CrosslightToDo.WebAPI project and change the following connection string.
Which should look like the following.
Now you can open the MDF file. Right-click and Add New Table.
Use the following query.
Delete the other two unused databases.
Delete these three connection strings inside CrosslightToDo.WebApi/Web.config.
Next, open app.config inside CrosslightToDo.DomainModels project.
Delete the connection string here as well.
Delete the four files here as well.
Then re-add a new ToDo.edmx file, just the same way as you would in the previous tutorial. Don't forget to enable the Intersoft WebAPI Extension as well as setting other properties such as Code Generation Version, Repository Type, Logical Delete Property, and Synchronization Date Property. Also, when you're done, don't forget to configure the IIS Express binding as well so that the server is exposed to your local network.
Creating Login Page
Before we can test the new CreatedBy column, we need to create a login page for the user, if the user tries to use the app without logging in first. Open AppService.cs under CrosslightToDo.Core/Infrastructure folder and use the following code.
There are several notable changes inside AppService.cs, in the constructor, we've added several additional configurations to AppSettings, which defines the IdentityServiceUrl for the login target. The RestClient also receives additional configurations to allow authenticated requests. We've also initialized the EntityContainer which is an essential component for the synchronization process. Here, we've also added a new overridden method OnSync, which contains the logic for the sync process. We've also provided additional QueryDescriptor for the sync process to retrieve the ToDos based on the logged in user. When the app resumes from its suspended state, we call the OnSync one more time.
Proceed by adding a new ViewModel under CrosslightToDo.Core/ViewModels folder called LoginViewModel. Use the following code.
Here, we have two simple properties, which are TxtUsername as well as LoginCommand that will be used for the login process. When the user performs login, in the ExecuteLogin method, we utilize the AccountService registered in the AppService to create an encrypted account, then try to register the user. If the user already exists, then we simply sign in. Since this is used for demonstration purposes, this is not considered as best practice. This is just to show how you can sync ToDo items that will be associated to a user easily.
Create a new Crosslight Binding Provider called LoginBindingProvider and put it inside CrosslightToDo.Core/BindingProviders folder. Use the following code.
The BindingProvider contains nothing except for the text box that will be bound to the TxtUsername property in the LoginViewModel as well as the button to the LoginCommand property.
Proceed by creating a new Crosslight Android Material Fragment called LoginFragment inside CrosslightToDo.Android/Fragments folder. Use the following code.
This is just a simple layout that will be inflated for the login screen. Here, the action bar up button is also hidden. Proceed by creating the login_layout.axml inside CrosslightToDo.Android/Resources folder and use the following code.
This is just a simple layout for the login screen which contains an EditText as well as a Button. Then modify the SimpleViewModel.cs inside CrosslightToDo.Core/ViewModels folder and use the following code.
The ViewModel is pretty much unchanged except now when adding a ToDo item, we also specify the CreatedBy property. In the Navigated method, we've also detected whether the user has performed login or not. If not, then we'll display the LoginViewModel that prompts the user for a username to be used with the application.
Now that you've prepared the login screen for Android, let's prepare the one for iOS. Begin by adding a new Crosslight View Controller, give it a name of LoginViewController and use the following code.
As you can see, this is just an empty ViewController that will be used for the login screen. Next, open up MainStoryboard.storyboard inside CrosslightToDo.iOS/Views folder. Create a new ViewController for the LoginViewController. Up to this point, it is assumed that you have a working knowledge of how iOS storyboard works, due to prior experiences in following previous tutorials.
Simply create a UITextField for the user to enter his/her username, as well as a button with both outlets set to TxtUsername and BtnLogin.
Run the server, then try to run the application on simulators, and you should get the following result.
Now that you've successfully created the login screen, simply input any username of your choice and create a new to-do item. Once you've done that, go back to Visual Studio and check your database to see if the ToDo is successfully created and associated to a user. You should get a result similar to the following.
As you can see, now you've successfully created a ToDo list that is associated with a user and retains the same behavior as the previous application.
However, in this occasion, we would like to enhance this experience further by automatically updating the other device with new data with the help of push notifications and OS-level synchronization components (SyncAdapter on Android and Background App Refresh on iOS). Let's do this next.
Configuring Push Notifications
The next step to accomplish automated syncing is to enable push notifications across these devices. Start by modifying the SimpleViewModel.cs and add the following property.
Then modify the following code.
Here, in the DisplayLogin method, we perform register for push notifications. Also modify the following method.
Next, open up AppService.cs inside CrosslightToDo.Core/Infrastructure folder and add the following code.
This will handle when the device received device token from the Google and store it into our database. Next, we're going to configure the server to allow push notifications. Open up Google Cloud Console.
Select Create a project as shown in the shot above. Give an appropriate name for the project then select Create.
Once your project is created, choose Enable and manage APIs.
Then in the next screen, choose Google Cloud Messaging.
In the next screen, click on Enable.
Next, click on Go to Credentials.
In the next screen, from the dropdown, choose Web Server. Then click on What credentials do I need?
Then give an appropriate name for your key and click on Create API key.
In the next screen, you'll get your server API key. Copy this value, click Done, and open Global.asax.cs inside CrosslightToDo.WebAPI project.
At the bottom, you should see a code similar to the following. Insert your copied server key onto the placeholder.
Now you've successfully configured the server for Google Push Notifications. Also ensure that the following ports are not blocked on your network: 5229, 5229, 5230. Next we're going to configure the server for Apple push notification. Please follow step-by-step guidance from this documentation: Preparing Apple Push Notification Service. Once you've followed through the documentation, ultimately, you'll end up with a private key on your WebAPI project, as follows. Don't forget to set the Build Action as Embedded Resource.
Once you've done that, open Global.asax.cs inside CrosslightToDo.WebAPI project and uncomment this line.
Insert the following code block.
Note that you may need to configure the password as necessary. In this example, it's intersoft.
Sending Push Notifications from Server
Now that you've successfully configured push notifications from the server, we need to modify some codes that will trigger the push notifications each time changes to ToDo data is made. Create a new controller inside CrosslightToDo.WebAPI/Controllers folder.
Give it a name of ToDoController.cs.
Use the following code.
In the controller above, we've added two notable delegates: AfterSaveEntitiesDelegate and BeforeExecuteQueryDelegate. These two methods are added to the controller as they play important roles, in which AfterSaveEntitiesDelegate method is called after saving entities to the database. Here we want to trigger push notification to a specific user to be able to sync data automatically upon any changes made to the database. And in BeforeExecuteQueryDelegate, we've ensured that the user will get his/her ToDos (associated with the user Id) before any query is executed.
Next, we need to modify the clients to be able to receive push notifications properly. Open up AppService.cs inside CrosslightToDo.Core/Infrastructure folder. Use the following code.
Enabling Push Notifications on iOS
Next, open up Info.plist inside CrosslightToDo.iOS. Add the following snippet to enable push notifications.
Then, open AppInitializer.cs inside CrosslightToDo.iOS/Infrastructure folder and add the following line inside the InitializeServices method.
When you start up the application, you should get the following screen.
Enabling Push Notifications on Android
To enable push notifications on Android, follow these steps. Add a new empty class inside CrosslightToDo.Android/Infrastructure folder. Name the class NotificationBootReceiver and use the following code.
Then, still in the same folder, add another empty class called NotificationBroadcastReceiver and use the following code.
These two classes are required for the Android app to properly receive push notifications with appropriate permissions. Then, open up AndroidManifest.xml inside CrosslightToDo.Android/Properties folder. Paste the following code.
In the above code, we've added several required permissions that are necessary for the OS-level synchronization and push notifications to work properly. Now, let's move on by creating the sync adapters. In CrosslightToDo.Android project, add a new folder called Services, then a folder called Synchronization inside it.
Inside the Synchronization folder, create four empty classes, respectively as follows.
These are all the main components of creating a usable sync services on Android.
Next, open up the CrosslightToDo.Android/Resources folder. Create a new folder inside called xml. Then, create two new XML files inside it, respectively.
Once that's done, run the Android project on a real device. To test the iOS version, you'll need to deploy it on a device. You cannot use push notifications feature when running on an iOS simulator. You should get the following result. Here's an example running the sample on an Android device an a iOS simulator.
In the next tutorial, we're going to further enhance this sample with multiple sync channels.