Tuesday, August 29, 2017

Android services

Android Services

What is a service?



Normally, when trying to execute an operation in Android it is, in some way, related and linked to a user interface. However, sometimes it would be better to run some long operations on the background, and just notify the user at the end. Or maybe just keep something running all the time, such as a music player. For these cases we can use a Service.


A service is a component which runs in the background without a user interface. Services will continue running even if the user changes to another application, ensuring the long operations are not interrupted by mistake.


There are many kinds of services at our disposal on android, so let’s see what are the main differences.


Services types



Started service



This is the basic type of service. It is usually used to perform a single operation, without returning a final result to the caller. It is created when “startService” is called for the first time and will be destroyed when “stopService” is executed. While “startService” can be called many times while the service is still running (and it will execute the “onStartCommand” function every time), it will not be re-created and will be destroyed when the “stopService” is ran for the first time. It does not matter how many times “startService” is called, it will end when “stopService” is executed once.


Started services can either be Sticky or not Sticky. The difference between a sticky and a not sticky service is what happens when the system kills the service. If the service is not a sticky service, it will not be recreated unless there are pending intents to be delivered. Meanwhile, a sticky service will be recreated regardless of if there are pending intents or not. In case there are none, it will be recreated with a null intent.


Not sticky services should be used when the it is possible to re-start the operation if unfinished and necessary, so the system can manage it appropriately. If it is vital that the service keeps running until stopped manually, you can use a sticky service.


There is also a started service called “redeliver intent”, which is useful when doing long operations that shouldn’t be interrupted. In this type of service, when the system kills it it will be re-created using the last intent that was delivered, and will use the pending intents subsequently. This allows for operations to be continued with the same intent instead of cancelling them altogether.


Bound service



Another type of service is the bound service. In this, instead of calling “startService”, when an activity wants to use this service it “binds” to it. The service is created when the first bind is made, and it continues running. This service can be binded to multiple times by different activities. When this service is binded to it returns an object that implements the “IBinder” interface to be used.


When the service is no longer required by an activity that is binded to it, the activity should call “unbind” to that service. After all activities which were bound to the service call “unbind” (meaning there are no more activities binded to this service), the service is destroyed.


Note: Bound Started service



It is possible to have a service that is both bound and started. This can be useful for some really specific situations but it is not commonly used and it normally leads to more confusion and problems than it is worth. Consider if this is exactly what you want before using it.


Scheduled service



A scheduled service is basically what the name suggests. It is a service that is scheduled to run at a later time. This can be done by using the JobScheduler class, and it allows you to set when to run this service, and even conditions to see if the service should be executed or not depending on status of the device when the scheduled time is reached.


Life cycle



A service follows a simple life cycle during its use. This lifecycle is used in both started services and bound services, although they have some differences in the middle. However, the general concept is the same.


First, the service is created. This is done by calling “startService” or “bindService” depending on the type of service. At this point is when it calls the “onCreate” function which can be used for initial setup on either type of service.


Immediately after creation, it starts executing the “onStartCommand” or “onBind” function (dependin on the case). Here is where the main processing of the service is executed and where it will continue until the service is stopped. In case of bound services, “onBind” will be called every time a new activity binds itself to the service, and “onUnbind” will be called when any activity unbinds itself.


When the service is stopped (either by calling “stopService” or the last “unbind”), the function “onDestroy” is called. Finall, the service is shut down and the life cycle comes to an end.


Creating a service



Now let’s see how to actually create a service. For this exampl, we will create a started service, but creating a bound service is not really that different.


To create a service you need to create a new class that extends from “Service”. This will force us to override the method “onBind”, which is for bound services. Since we will now create a simple started service, we can return null here and move on.


Now we can implement the methods we wish. As explained earlier, we can implement “onCreate”, “onStartCommand”, or “onDestroy” depending on what we need. There are others that we could implement but those are not important for this basic tutorial. The one that we should implement to actually have a started service as we want is the “onStartCommand” one. Here is also where we can choose which type of started service we want to create. This is determined by what we return at the end. Return either “START_NOT_STICKY”, “START_STICKY”, or “START_REDELIVER_INTENT”, depending on what you wish to do.


Here you can see the code for creating a started not sticky service:

package com.servicesexample.innuy.servicesexample; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; import android.widget.Toast; /** * Created by Innuy. */ public class ExampleService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "Here the service is started", Toast.LENGTH_LONG).show(); return START_NOT_STICKY; } }
What we need to do now is add our new service to the Android manifest. Just add the following line changing the name of the service to yours:


<service android:name=".ExampleService"></service>
The last step is to call this service. For this you just need to create an appropriate intent and call “startService” from an activity as it is shown in the code below:

startService(new Intent(getBaseContext(), ExampleService.class));
And there it goes! If you use the above code you will see the Toast being shown whenever you start the service. To stop this service just call “endService” with an intent of the same service.


Sources

Services Documentation - Android Developers https://developer.android.com/guide/components/services.html


Secondary links:


Wednesday, August 2, 2017

Ionic - Secure Storage


This post is not meant as a guide nor as a tutorial on how to use storage with Ionic. This post will explain a possible problem you may have when using the Secure Storage plugin as described in Ionic docs. Also, this is a problem that only shows itself on Android and not on iOS, so if you are facing issues on an Apple device this is probably not the problem you are encountering.

‘Native Storage’ and ‘Secure Storage’ plugins



Native Storage and Secure Storage are the two main ways for you to store information on mobile with Ionic, without needing to set up your own database and instead delegating the handling to the OS.


As the name suggests, the latter is normally used when the information to be saved is really sensitive.


This doesn’t mean Native Storage by itself is insecure. Data stored in this way should only be accessible by your app, which leaves it pretty safe in its own right. However, it is still possible to access it if the backup of the data is enabled or on an Android device if it is rooted. So, for cases in which security is a top priority, Secure Storage can shine.


But, when using the “Secure Storage” plugin on Android, sometimes it may fail when starting or when using it. It may even delete previously stored information. So now we have to make the decision on which one to use. Before that, however, it would be good to know why this happens, and how often it happens.


Secure Storage on Android



The “Secure Storage” plugin on Android only works correctly when the user has a block screen activated for their device. Be it with a pattern or with a code, the plugin uses the KeyStore associated with the lock to encrypt the data to be safely stored.


What this means for a user using our application with secure storage, is that it will only work if the device has this safety measures in place. If they don’t, the plugin will fail to initialize, and all storage or retrieval operations will subsequently fail.


And this is not the worst case scenario. The worst case scenario comes when the user removes or updates their password or pattern. If this happens, all previously stored information will be basically deleted since the key associated with it will change.


iOS, on the other hand, doesn’t have this problem since it uses KeyChain to store the information with this plugin, and this does not depend on the user actually having security enabled for their device.


Solutions



Now we need to make a decision on what to use, and the answer should change depending on what your App needs. Some options would be the following:


  • If the data to be stored is not sensitive enough, just use Native Storage. It is secure enough for many cases since it needs a special scenario to be compromised.
  • If data is really sensible, and its use can be avoided, you can use Secure Storage. You need to check before using it in case it was deleted, but this will ensure everything is secure.
  • If data is sensible but temporary (as a short session token) you can try using both. Start by using Secure Storage and just default to Native Storage when that fails. This will allow most users to have the full security without annoying the other users. You can also try migrating data from Native Storage to Secure Storage if it is detected through the App that the user activated their screen lock security.
  • If data is sensible, you could also use Secure Storage and actively ask the user to enable screen lock. This will make sure your data is safe and that your app can access it (unless the user later disables it), but it may annoy the user. You also need to check for possible disappearance of data in every storage operation.
  • You could also choose to use neither. You can try using your own database and handle its security on your own. This can be done either mobile or server side, depending on your needs, but remember that this will probably be more time consuming than just using one of the other plugins.

Conclusion



Unluckily there is not a definitive solution to your problem, but it is something important to have in mind when using these plugins. You just need to make sure you know the needs of your app, your users and the information to be stored and make an informed decision.

We hope this quick post was useful to you!




Sources