Using RealmRecyclerView Adapter to show list of recorded sensor data from Realm Database

In previous blog Storing Recorded Sensor Data in Realm Database we have stored the data fetched from sensors into the Realm Database by defining model classes. In this blog, we will use the data stored in the Realm to display a list of recorded experiments in the form of well defining card view items so that it is easier for the user to understand. For showing the list we will make use of RecyclerView  widget provided by Android which is a more advanced version of the List view and is used to display large data sets in a vertical list, horizontal list, grid, staggered grid etc. RecyclerView  works in accordance with RecyclerView Adapter which is core engine that is responsible of inflating the layout of list items, populating the items with data, recycling of list item views when they go out of viewing screen and much more. For this blog, we are going to use a special RecyclerView Adapter provided by Realm itself because it integrates properly with the Realm Database and handles modifying, addition, deletion or updating of Realm data automatically and efficiently.    Step 1 Adding the dependencies As always first we need to add the following code in our build.gradle file to add the dependency of Realm database and RealmRecyclerViewAdapter. dependencies { implementation"com.android.support:recyclerview-v7:27.1.1 " implementation 'io.realm:android-adapters:2.1.1' } Step 2 Adding RecyclerView widget in our Activity layout file First, we need to create an activity and name it as “DataLoggerActivity”, inside the layout of the Activity add the <RecyclerView> widget. This RecyclerView will act as a container of our list item. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".activity.DataLoggerActivity"> <android.support.v7.widget.RecyclerView android:layout_below="@id/top_app_bar_layout" android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> Step 3 Creating the layout and View holder for the list item We have to create the layout of the list item which will be inflated by the Adapter. So for this create an XML file in res folder and name it “data_list_item.xml”. For the list of the experiments, we want to show Name of the experiment, recording time, recording date for every list item. For this we will make use of <CardView> and <TextView>. This gist shows the code of xml file. The layout of the list item created is shown in Figure 2 Now we need to create a view holder for this layout which we need to pass to the Adapter, the following code shows the implementation of View Holder for above list item layout. public class ViewHolder extends RecyclerView.ViewHolder { private TextView sensor, dateTime; ImageView deleteIcon; private CardView cardView; public ViewHolder(View itemView) { super(itemView); dateTime = itemView.findViewById(R.id.date_time); sensor = itemView.findViewById(R.id.sensor_name); deleteIcon = itemView.findViewById(R.id.delete_item); cardView = itemView.findViewById(R.id.data_item_card); } } Step 4 Creating the adapter for RecyclerView   In this step, we will start by creating a class called “SensorLoggedListAdpater” and for using use the RecyclerView adapter provided by Realm we need to make this class extend the RealmRecyclerViewAdpater class. But for that we need to pass two generic parameter: Model Class : This is class which define a…

Continue ReadingUsing RealmRecyclerView Adapter to show list of recorded sensor data from Realm Database

Option to add description to an image in the Phimpme Android app

In the Phimpme Android application, users can perform various operations on images such as editing an image, sharing an image, moving the image to another folder, printing a pdf version of the image and many more. However, another important functionality that has been implemented is the option to add some description to the image. So in this blog post, I will be discussing how we achieved the functionality to add a description to any image. Step 1 First, we need to add an option in the overflow menu to add description for the image being viewed. The option to add description to an image has been achieved by adding the following lines of code in the  menu_view_pager.xml file. <item   android:id="@+id/action_description"   android:title="Description"   app:showAsAction="never" /> Step 2 Now after the user chooses the option to add description to the image, an alertdialog with an edittext would be displayed to the user to enter the description. The dialog box with edittext has been implemented with the following lines of XML code. <android.support.v7.widget.CardView   android:layout_width="match_parent"   android:layout_height="wrap_content"   app:cardCornerRadius="2dp"   android:id="@+id/description_dialog_card">   <ScrollView       android:layout_width="match_parent"       android:layout_height="match_parent">       <LinearLayout           android:layout_width="match_parent"           android:layout_height="wrap_content"           android:orientation="vertical">           <TextView               android:id="@+id/description_dialog_title"               android:layout_width="match_parent"               android:textColor="@color/md_dark_primary_text"               android:layout_height="wrap_content"               android:background="@color/md_dark_appbar"               android:padding="24dp"               android:text="@string/type_description"               android:textSize="18sp"               android:textStyle="bold" />           <LinearLayout               android:id="@+id/rl_description_dialog"               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:orientation="horizontal"               android:padding="15dp">               <EditText                   android:id="@+id/description_edittxt"                   android:layout_width="fill_parent"                   android:layout_height="wrap_content"                   android:padding="15dp"                   android:hint="@string/description_hint"                   android:textColorHint="@color/grey"                   android:layout_margin="20dp"                   android:gravity="top|left"                   android:inputType="textCapSentences|textMultiLine"                   android:maxLength="2000"                   android:maxLines="4"                   android:selectAllOnFocus="true"/>               <ImageButton                   android:layout_width="@dimen/mic_image"                   android:layout_height="@dimen/mic_image"                   android:layout_alignRight="@+id/description_edittxt"                   app2:srcCompat="@drawable/ic_mic_black"                   android:layout_gravity="center"                   android:background="@color/transparent"                   android:paddingEnd="10dp"                   android:paddingTop="12dp"                   android:id="@+id/voice_input"/>           </LinearLayout>       </LinearLayout>   </ScrollView> </android.support.v7.widget.CardView> The screenshot of the dialog to enter description has been provided below. Step 3 Now after retrieving the description added by the user, the description is saved in the realm database using the realm model object ImageDescModel which will contain the path of the image and the description added as its attributes. The path of the image has been used as the primary key for the description table. The realm model class used for the above-mentioned operation is described below. public class ImageDescModel extends RealmObject {   @PrimaryKey   private String path;   private String desc;   public ImageDescModel() {   }   public ImageDescModel(String path, String title) {       this.path = path;       this.desc = title;   }   public String getId() {       return path;   }   public void setId(String path) {       this.path = path;   }   public String getTitle() {       return desc;   }   public void setTitle(String description) {       this.desc = description;   } } This is how we have implemented the functionality to add description to images in the Phimpme Android application. To get the full source code, please refer to the Phimpme Android Github repository listed in the resource section below. Resources 1.Realm for Android - https://realm.io/blog/realm-for-android/ 2.Github-Phimpme Android Repository - https://github.com/fossasia/phimpme-android/ 3.Working with realm tutorial - https://www.androidhive.info/2016/05/android-working-with-realm-database-replacing-sqlite-core-data/

Continue ReadingOption to add description to an image in the Phimpme Android app

Adding option to Unfavourite image in Phimp.Me

This blog is in accordance with the P.R #1900. Here I have implemented the option to unfavourite image in the Phimp.Me android application. Implementation In the Phimp.Me app there are the following modes present: 1. all_photos: All the photos are displayed in this mode irrespective of where they are saved. 2. fav_photos: The photos which are added to favourites are displayed in the fav_photos. 3. Albums_mode: All the albums which are present in the app are displayed in the albums_mode. The main idea here is to find whether the selected image is already FAVOURITE or not. If it is already FAVORITED then it can be removed from that mode by removing its path form the Realm Database. If it isn’t already FAVORITED then the image is ignored and the next image is taken into consideration. The process of removing the images from favourites can be an expensive one as the user can select myriad images which would ultimately block the Main UI. So it is better handled asynchronously and is implemented using the AsyncTask. Whenever the user adds an image to the FAVOURITES, it gets added to the Realm Database where the model class being used is the FavouriteImagesModel.The selected media in the all_photos and fav_photos mode can be accessed via by selectedMedia.size()  and the number of selected media in the albums_mode can be accessed by getAlbum().getSelectedCount(). So in the execute method of doInBackground() a condition check is initially made and then 2 separate loops are run depending upon the mode in which the selected images exist. Initially it is checked whether the selected image is already a FAVOURITE one or not by the following code. If it belongs to the favourite mode then the size of the favouriteImageModels would become 1. RealmResults<FavouriteImagesModel> favouriteImagesModels = realm.where                                                (FavouriteImagesModel.class).equalTo("path", selectedMedias.get(i).getPath( )).findAll( ); If ( favouriteImagesModels.size( ) == 1) {             favouriteImagePresent = true;              imagesUnfavourited++;    } Now as the image belongs to the favourite mode we ultimately use the following code to remove the image from FAVOURITES.  favouriteImagesModels.deleteAllFromRealm(); The full code which handle the option to unfavourite an image is shown below. @Override                    protected Boolean doInBackground(String... arg0) {                              if ( all_photos || fav_photos )   {                            realm = Realm.getDefaultInstance();                            realm.executeTransaction ( new Realm.Transaction( ) {                                                                @Override                                public void execute (Realm realm)  {                                    for (int i = 0 ;  i < selectedMedias.size( ) ;  i++) {                                        RealmResults<FavouriteImagesModel> favouriteImagesModels = realm.where                                                (FavouriteImagesModel.class).equalTo("path", selectedMedias.get(i).getPath( )).findAll( );                                        If ( favouriteImagesModels.size( ) == 1) {                                            favouriteImagePresent = true;                                            imagesUnfavourited++;                                        }                                        favouriteImagesModels.deleteAllFromRealm();                                    }                                }                            });                        }          else if ( !fav_photos && !albumsMode ) {                            realm = Realm.getDefaultInstance();                            realm.executeTransaction(new Realm.Transaction() {                                                           @Override                                public void execute(Realm realm) {                                    for (int i = 0;  i < getAlbum().getSelectedCount();  i++) {                                        RealmResults<FavouriteImagesModel> favouriteImagesModels = realm.where                                                (FavouriteImagesModel.class).equalTo("path", getAlbum( ).getSelectedMedia(i).getPath( ) ).findAll( );                                        If ( favouriteImagesModels.size() == 1) {                                            favouriteImagePresent = true;                                            imagesUnfavourited++;                                        }                                        favouriteImagesModels.deleteAllFromRealm();                                    }                                }                    } After the doInBackground( ) method has been executed the onPostExecute( ) comes into play and some other UI related changes are done such as a SnackBar message…

Continue ReadingAdding option to Unfavourite image in Phimp.Me

How to use Realm in SUSI Android to Save Data

Sometimes we need to store information on the device locally so that we can use information offline and also query data faster. Initially, SQLite was only option to store information on the device. But working with SQLite is difficult sometimes and also it makes code difficult to understand. Also, SQL queries take a long time. But now we have realm a better alternative of SQLite. The Realm is a lightweight mobile database and better substitute of SQLite. The Realm has own C++ core and store data in a universal, table-based format by a C++ core. This allows Realm to allow data access from multiple languages as well as a range of queries. In this blog post, I will show you why we used Realm and how we save data in SUSI Android using Realm. “How about performance? Well, we’re glad you asked :) For all the API goodness & development productivity we give you, we’re still up to 100x faster than some SQLite ORMs and on average ~10x faster than raw SQLite and common ORMs for typical operations.” (compare: https://blog.realm.io/realm-for-android/) Advantages of Realm over SQLite are following: It is faster than SQLite as explained on the Realm blog. One of the reasons realm is faster than SQLite is, the traditional SQLite + ORM abstraction is leaky because ORM simply converts  Objects and their methods into SQL statements. Realm, on the other hand, is an object database, meaning your objects directly reflect your database. It is easier to use as it uses objects for storing data. When we use SQLite we need boilerplate code to convert values to and from the database, setting up mappings between classes and tables, fields and columns, foreign keys, etc. Whereas in Realm data is directly exposed as objects and can be queried without any conversion. Prerequisites To include this library in your project you need Android studio version 1.5.1 or higher. JDK version 7.0 or higher. Android API level 9 or higher. How to use realm in Android To use Realm in your project we must add the dependency of the library in build.gradle(project) file   dependencies {        classpath "io.realm:realm-gradle-plugin:3.3.1"    } and build.gradle(module) file. apply plugin: 'realm-android' dependencies { compile 'io.realm:android-adapters:1.3.0’ } Now you have to instantiate Realm in your application class. Setting a default configuration in your Application class, will ensure that it is available in the rest of your code. RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)                                                               .deleteRealmIfMigrationNeeded().build(); Realm.setDefaultConfiguration(realmConfiguration); Now we need to create a model class. A model class is use to save data in Realm and retrieve saved data and it must extend RealmObject class. For eg. public class Person extends RealmObject {    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    } } Field in the model class uses to define columns. For eg. ‘name’ is a column name. Method like setName() use to save data  and getName() use to retrieve saved data. Now create an instance of the Realm in the activity where you…

Continue ReadingHow to use Realm in SUSI Android to Save Data

Showing only Logged-in Accounts in the Sharing Page of Phimpme Android

In Phimpme Android application, users can edit their pictures and share them to a number of platforms ranging from social networking sites like Facebook, Twitter etc to cloud storage and image hosting sites like Box, Dropbox, Imgur etc. Desired flow of the application According to the flow of the application, the user has to add an account first i.e. log in to the particular account that needs to be connected to the application. After that when the user enters the share page for sharing the image, a button corresponding to the connected account is visible in that page which on clicking will share the image to that platform directly. What was happening previously? The list of accounts which is present in the account manager of Phimpme Android application is also getting displayed in the share image page. As the list is large, it is difficult for the user to find the connected account from the list. There is not even an indicator whether a particular account is connected or not. On clicking the button corresponding to the non-connected account, an error dialog instructing the user to log in from the account manager first, will get displayed. How we solved it? We first thought of just adding an indicator on the buttons in the accounts page to show whether it is connected or not. But this fix solves only a single issue. Find the connected account in that large list will be difficult for the user even then. So we decided to remove the whole list and show only the accounts which are connected previously in account manager. This cleans the flow of the accounts and share in  Phimpme Android application When a user logins from the account manager, the credentials, tokens and other details corresponding to that accounts gets saved in database. We used realm database for saving the details in our application. As the details are present in this database, the list can be dynamically generated when the user opens share image page. We implemented a function in Utils class for getting the list of logged in accounts. Its implementation is shown below. public static boolean checkAlreadyExist(AccountDatabase.AccountName s) {   Realm realm = Realm.getDefaultInstance();   RealmQuery<AccountDatabase> query = realm.where(AccountDatabase.class);   query.equalTo("name", s.toString());   RealmResults<AccountDatabase> result1 = query.findAll();   return (result1.size() > 0); } public static ArrayList<AccountDatabase.AccountName> getLoggedInAccountsList(){   ArrayList<AccountDatabase.AccountName> list = new ArrayList<>();   for (AccountDatabase.AccountName account : AccountDatabase.AccountName.values()){       if (checkAlreadyExist(account))           list.add(account);   }   return list; } Additional changes There are few accounts which don’t need authentication. Those accounts need their respective application to be installed in the user’s device. So for adding those accounts to the list, we added another function which checks whether a particular package is installed in user’s device or not. Using that it adds the account to the list. The implementation for checking whether a package is installed or not is shown below. public static boolean isAppInstalled(String packageName, PackageManager pm) {   boolean installed;   try {       pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);       installed = true;   } catch (PackageManager.NameNotFoundException e) {       installed = false;   }   return installed; }…

Continue ReadingShowing only Logged-in Accounts in the Sharing Page of Phimpme Android

Uploaded Images History in Phimpme Android

In Phimpme Android one core feature is of sharing images to many different platforms. After sharing we usually wants to look in the our past records, where we uploaded what pictures? Which image we uploaded? What time it was? So I added a feature to view the upload history of images. User can go to the Upload history tab, present in the navigation drawer of the app. From there he can browse the repository. How I added history feature in Phimpme Store the data when User initiate an upload To get which data uploading is in progress. I am storing its name, date, time and image path. When user approve to upload image from Sharing Activity. Created a database model public class UploadHistoryRealmModel extends RealmObject{   String name;   String pathname;   String datetime;   public String getName() {       return name;   }   public void setName(String name) {       this.name = name;   }   public String getPathname() {       return pathname;   }   public void setPathname(String pathname) {       this.pathname = pathname;   }   public String getDatetime() {       return datetime;   }   public void setDatetime(String datetime) {       this.datetime = datetime;   } } This is the realm model for storing the name, date, time and image path. Saving in database UploadHistoryRealmModel uploadHistory; uploadHistory = realm.createObject(UploadHistoryRealmModel.class); uploadHistory.setName(sharableAccountsList.get(position).toString()); uploadHistory.setPathname(saveFilePath); uploadHistory.setDatetime(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date())); realm.commitTransaction(); Creating realm object and setting the details in begin and commit Transaction block Added upload history entry in Navigation Drawer <LinearLayout   xmlns:android="http://schemas.android.com/apk/res/android"   android:id="@+id/ll_drawer_uploadhistory"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:background="@drawable/ripple"   android:clickable="true"   android:orientation="horizontal">   <com.mikepenz.iconics.view.IconicsImageView       android:id="@+id/Drawer_Upload_Icon"       android:layout_width="@dimen/icon_width_height"       android:layout_height="@dimen/icon_width_height"       app:iiv_icon="gmd-file-upload"/>   <TextView       android:id="@+id/Drawer_Upload_Item"       android:layout_width="wrap_content"       android:layout_height="wrap_content"       android:text="@string/upload_history"       android:textColor="@color/md_dark_background"       android:textSize="16sp"/> </LinearLayout> It consist of an ImageView and TextView in a horizontal oriented Linear Layout Showing history in Upload History Activity Added recyclerview in layout. <android.support.v7.widget.RecyclerView   android:id="@+id/upload_history_recycler_view"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:layout_below="@id/toolbar"> </android.support.v7.widget.RecyclerView> Query the database and updated the adapter of Upload History uploadResults = realm.where(UploadHistoryRealmModel.class); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); uploadHistoryRecyclerView.setLayoutManager(layoutManager); uploadHistoryRecyclerView.setAdapter(uploadHistoryAdapter); Added the adapter for recycler view and created an Item using Constraint layout. Resources Realm Docs : https://realm.io/docs/java/latest/?gclid=Cj0KEQjw6-PJBRCO_br1qoOB4LABEiQAEkqcVWPnl36QeBPNq00Y87fuLAeKXAylrsVZML2pwDdluDYaAqKF8P8HAQ#getting-started Recycler View adapter:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html Writing in Realm database: https://realm.io/docs/java/latest/?gclid=Cj0KEQjw6-PJBRCO_br1qoOB4LABEiQAEkqcVWPnl36QeBPNq00Y87fuLAeKXAylrsVZML2pwDdluDYaAqKF8P8HAQ#writes Query in Realm Database: https://realm.io/docs/java/latest/?gclid=Cj0KEQjw6-PJBRCO_br1qoOB4LABEiQAEkqcVWPnl36QeBPNq00Y87fuLAeKXAylrsVZML2pwDdluDYaAqKF8P8HAQ#queries

Continue ReadingUploaded Images History in Phimpme Android

Export Sensor Data from the PSLab Android App

The PSLab Android App allows users to log data from the sensors connected to the PSLab hardware device. Sensor Data is stored locally but can be exported in various formats. Currently the app supports exporting data in .txt and .csv (comma-separated values) format. Exported data can be used by other users or scientists to study or analyze the data. Data can also be used by other softwares like Python, GNU octave, Matlab to further process it or visualise it in 3D. In this post, we will discuss how to export the locally stored realm data in .txt or .csv format. We will take the data of MPU6050 sensor as an example for understanding how locally logged data is exported. Query Local Realm Data We have attached a long click listener to sensor list view that detects which list item is selected. Clicking any sensor from sensor list for slightly longer than usual would result in a dialog popping up with the option to Export Data: Results in exporting data in a format which is selected in App settings Share Data: Shares sensor data with other users or on social media (yet to be implemented) As soon as the Export Data option is selected from the dialog, sensor data of the corresponding sensor is queried. The data model of the sensor and how it's saved in the local realm database is discussed in the post Sensor Data Logging in the PSLab Android App. RealmResults<DataMPU6050> results = realm.where(DataMPU6050.class).findAll(); Once we get the required data, we need to write it in .txt or .csv format depending on what the user has selected as a preference in App Settings. Getting User Preference from App Settings The format in which the sensor data should be exported is presented to the user as a preference in App Settings. Currently the app supports two formats .txt and .csv. private String format; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); String formatValue = preferences.getString("export_data_format_list", "0"); if ("0".equals(formatValue))   format = "txt"; else   format = "csv"; Export Data in .txt Format To export the sensor data in .txt format, we need to create a .txt file in the external storage. folder variable is a path to PSLab Android folder in the external storage. If the folder doesn’t exist, it will be created. File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "PSLab Android"); After getting reference of the app folder in the external storage, we would create a text file in the PSLab Android folder. As soon as the text file is created, we initialize the FileOutputStream object to write data into the text file. The sensor data that was queried in the previous section is written into the text file just created. Finally after the complete sensor data is written, the stream is closed by stream.close() method. FileOutputStream stream = null; File file = new File(folder, "sensorData.txt"); try {   stream = new FileOutputStream(file);   for (DataMPU6050 temp : results) {       stream.write((String.valueOf(temp.getAx()) + " " + temp.getAy() + " " + temp.getAz() + " " +               temp.getGx()…

Continue ReadingExport Sensor Data from the PSLab Android App

Sensor Data Logging in the PSLab Android App

The PSLab Android App allows users to log data from sensors connected to the PSLab hardware device. The Connected sensors should support I2C, SPI communication protocols to communicate with the PSLab device successfully. The only prerequisite is the additional support for the particular sensor plugin in Android App. The user can log data from various sensors and measure parameters like temperature, humidity, acceleration, magnetic field, etc. These parameters are useful in predicting and monitoring the environment and in performing many experiments. The support for the sensor plugins was added during the porting python communication library code to Java. In this post,  we will discuss how we logged real time sensor data from the PSLab Hardware Device. We used Realm database to store the sensor data locally. We have taken the MPU6050 sensor as an example to understand the complete process of logging sensor data. Creating Realm Object for MPU6050 Sensor Data The MPU6050 sensor gives the acceleration and gyroscope readings along the three axes X, Y and Z. So the data object storing the readings of the mpu sensor have variables to store the acceleration and gyroscope readings along all three axes. public class DataMPU6050 extends RealmObject {   private double ax, ay, az;   private double gx, gy, gz;   private double temperature;   public DataMPU6050() {  }   public DataMPU6050(double ax, double ay, double az, double gx, double gy, double gz, double temperature) {       this.ax = ax;       this.ay = ay;       this.az = az;       this.gx = gx;       this.gy = gy;       this.gz = gz;       this.temperature = temperature;   }  // getter and setter for all variables } Creating Runnable to Start/Stop Data Logging To sample the sensor data at 500ms interval, we created a runnable object and passed it to another thread which would prevent lagging of the UI thread. We can start/stop logging by changing the value of the boolean loggingThreadRunning on button click. TaskMPU6050 is an AsyncTask which reads each sample of sensor data from the PSLab device, it gets executed inside a while loop which is controlled by boolean loggingThreadRunning. Thread.sleep(500) pauses the thread for 500ms, this is also one of the reason to transfer the logging to another thread instead of logging the sensor data in UI thread. If such 500ms delays are incorporated in UI thread, app experience won’t be smooth for the users. Runnable loggingRunnable = new Runnable() {   @Override   public void run() {       try {           MPU6050 sensorMPU6050 = new MPU6050(i2c);           while (loggingThreadRunning) {               TaskMPU6050 taskMPU6050 = new TaskMPU6050(sensorMPU6050);               taskMPU6050.execute();              // use lock object to synchronize threads               Thread.sleep(500);           }       } catch (IOException   InterruptedException e) {           e.printStackTrace();       }   } }; Sampling of Sensor Data We created an AsyncTask to read each sample of the sensor data from the PSLab device in the background thread. The getRaw() method read raw values from the sensor and returned an ArrayList containing the acceleration and gyro values. After the values were read successfully, they were updated in the data card in the foreground which was visible to the user. This data card acts as a…

Continue ReadingSensor Data Logging in the PSLab Android App

Save Chat Messages using Realm in SUSI iOS

Fetching data from the server each time causes a network load which makes the app depend on the server and the network in order to display data. We use an offline database to store chat messages so that we can show messages to the user even if network is not present which makes the user experience better. Realm is used as a data storage solution due to its ease of usability and also, since it’s faster and more efficient to use. So in order to save messages received from the server locally in a database in SUSI iOS, we are using Realm and the reasons for using the same are mentioned below. The major upsides of Realm are: It’s absolutely free of charge, Fast, and easy to use. Unlimited use. Work on its own persistence engine for speed and performance Below are the steps to install and use Realm in the iOS Client: Installation: Install Cocoapods Run `pod repo update` in the root folder In your Podfile, add use_frameworks! and pod 'RealmSwift' to your main and test targets. From the command line run `pod install` Use the `.xcworkspace` file generated by Cocoapods in the project folder alongside `.xcodeproj` file After installation we start by importing `Realm` in the `AppDelegate` file and start configuring Realm as below: func initializeRealm() {         var config = Realm.Configuration(schemaVersion: 1,             migrationBlock: { _, oldSchemaVersion in                 if (oldSchemaVersion < 0) {                     // Nothing to do!                 }         })         config.fileURL = config.fileURL?.deletingLastPathComponent().appendingPathComponent("susi.realm")         Realm.Configuration.defaultConfiguration = config } Next, let’s head over to creating a few models which will be used to save the data to the DB as well as help retrieving that data so that it can be easily used. Since Susi server has a number of action types, we will cover some of the action types, their model and how they are used to store and retrieve data. Below are the currently available data types, that the server supports. enum ActionType: String { case answer case websearch case rss case table case map case anchor } Let’s start with the creation of the base model called `Message`. To make it a RealmObject, we import `RealmSwift` and inherit from `Object` class Message: Object { dynamic var queryDate = NSDate() dynamic var answerDate = NSDate() dynamic var message: String = "" dynamic var fromUser = true dynamic var actionType = ActionType.answer.rawValue dynamic var answerData: AnswerAction? dynamic var mapData: MapAction? dynamic var anchorData: AnchorAction? } Let’s study these properties of the message one by one. `queryDate`: saves the date-time the query was made `answerDate`: saves the date-time the query response was received `message`: stores the query/message that was sent to the server `fromUser`: a boolean which keeps track who created the message `actionType`: stores the action type `answerData`, `rssData`, `mapData`, `anchorData` are the data objects that actually store the respective action’s data To initialize this object, we need to create a method that takes input the data received from the server. // saves…

Continue ReadingSave Chat Messages using Realm in SUSI iOS

Realm database in Loklak Wok Android for Persistent view

Loklak Wok Android provides suggestions for tweet searches. The suggestions are stored in local database to provide a persistent view, resulting in a better user experience. The local database used here is Realm database instead of sqlite3 which is supported by Android SDK. The proper way to use an sqlite3 database is to first create a contract where the schema of the database is defined, then a database helper class which extends from SQLiteOpenHelper class where the schema is created i.e. tables are created and finally write ContentProvider so that you don’t have to write long SQL queries every time a database operation needs to be performed. This is just a lot of hard work to do, as this includes a lot of steps, debugging is also difficult. A solution to this can be using an ORM that provides a simple API to use sqlite3, but the currently available ORMs lack in terms of performance, they are too slow. A reliable solution to this problem is realm database, which is faster than raw sqlite3 and has really simple API for database operations. This blog explains the use of realm database for storing tweet search suggestions. Adding Realm database to Android project In project level build.gradle buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath "io.realm:realm-gradle-plugin:3.3.1" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }   And at the top of app/build.gradle "apply plugin: 'realm-android'"  is added. Using Realm Database Let’s start with a simple example. We have a Student class that has only two attributes name and age. To create the model for the database, the Student class is simply extended to RealmObject. public class Student extends RealmObject { private String name; private int age; // A constructor needs to be explicitly defined, be it an empty constructor public Student(String name, int age) { this.name = name; this.age = age; } // getters and setters }   To push data to the database, Java objects are created, a transaction is initialized, then copyToRealm method is used to push the data and finally the transaction is committed. But before all this, the database is initialized and a Realm instance is obtained. Realm.init(context); // Database initialized Realm realm = Realm.getDefaultInstance(); // realm instance obtained Student student = new Student("Rahul Dravid", 22); // Simple java object created realm.beginTransaction() // initialization of transaction realm.copyToRealm(student); // pushed to database realm.commitTransaction(); // transaction committed   copyToRealm takes only a single parameter, the parameter can be an object or an Iterable. Off course, the passed parameter should extend RealmObject. A List of Student can be passed as a parameter to copyToRealm to push multiple data into the database. The above way of inserting data is synchronous. Realm also supports asynchronous transactions, you guessed it right, you don’t have to depend on AsyncTaskLoader. The same operation can be performed asynchronously as realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Student student = new Student("Rahul Dravid",…

Continue ReadingRealm database in Loklak Wok Android for Persistent view