Introduction

As in my previous article we have learned the basics of Services in Android and how to create them using the startService() method. Now in this article, we will learn about binding service to an activity, say MainActivity in our article.

What is bound service?

According to Google's Android docs "A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC)".
Now you are wondering how it could be a client and server architecture. Let's take an activity to say, MainActivity in our case, or any other activity you people can take, MainActivity communicates with a class say a LocalService and this class extends the Android's Service class.
Ways to create Bound Services

Using Binder Class

Now, In this article, we will focus only on the first one, which is extending the Binder class.
Some steps to do to establish communication with the service class, are as follows:
Lets have a look at code below activity_main.xml,
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. tools:context="com.example.gkumar.examplebindservice.MainActivity">
  11. <TextView
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="Fetching Result from Service..."
  15. android:id="@+id/textView"
  16. android:layout_marginTop="116dp"
  17. android:layout_below="@+id/button"
  18. android:layout_centerHorizontal="true"
  19. android:visibility="invisible"/>
  20. <Button
  21. style="?android:attr/buttonStyleSmall"
  22. android:layout_width="150dp"
  23. android:layout_height="wrap_content"
  24. android:text="Fetch Data"
  25. android:id="@+id/button"
  26. android:layout_alignParentTop="true"
  27. android:layout_centerHorizontal="true" />
  28. </RelativeLayout>
    You can see we have created a button and textview. On the click of the button, we will call the public method from service class and will set the response in that textview.
    Now find these views created above in MainActivity.java as given below.
    1. package com.example.gkumar.examplebindservice;
    2. import android.content.BroadcastReceiver;
    3. import android.content.ComponentName;
    4. import android.content.Context;
    5. import android.content.Intent;
    6. import android.content.IntentFilter;
    7. import android.content.ServiceConnection;
    8. import android.os.IBinder;
    9. import android.support.v7.app.AppCompatActivity;
    10. import android.os.Bundle;
    11. import android.view.View;
    12. import android.widget.Button;
    13. import android.widget.TextView;
    14. import android.widget.Toast;
    15. public class MainActivity extends AppCompatActivity {
    16. LocalService mService;
    17. boolean mBound = false;
    18. TextView fetchedText;
    19. Button mButton;
    20. MyReceiver mReciver;
    21. @Override
    22. protected void onCreate(Bundle savedInstanceState) {
    23. super.onCreate(savedInstanceState);
    24. setContentView(R.layout.activity_main);
    25. mButton = (Button) findViewById(R.id.button);
    26. fetchedText = (TextView) findViewById(R.id.textView);
    27. IntentFilter intentFilter = new IntentFilter();
    28. intentFilter.addAction(LocalService.MY_ACTION);
    29. mReciver = new MyReceiver();
    30. registerReceiver(mReciver,intentFilter);
    31. mButton.setOnClickListener(new View.OnClickListener() {
    32. @Override
    33. public void onClick(View v) {
    34. fetchedText.setVisibility(View.VISIBLE);
    35. onButtonClick(v);
    36. }
    37. });
    38. }
    39. @Override
    40. protected void onStart() {
    41. super.onStart();
    42. Intent intent = new Intent(this, LocalService.class);
    43. bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    44. }
    45. @Override
    46. protected void onStop() {
    47. super.onStop();
    48. unregisterReceiver(mReciver);
    49. if (mBound) {
    50. unbindService(mConnection);
    51. mBound = false;
    52. }
    53. }
    54. public void onButtonClick(View v) {
    55. if (mBound) {
    56. mService.getDataFromAPI();
    57. }
    58. }
    59. /**
    60. * Defines callbacks for service binding, passed to bindService()
    61. */
    62. private ServiceConnection mConnection = new ServiceConnection() {
    63. @Override
    64. public void onServiceConnected(ComponentName className,
    65. IBinder service) {
    66. Toast.makeText(MainActivity.this, "connected with service", Toast.LENGTH_LONG).show();
    67. // We've bound to LocalService, cast the IBinder and get LocalService instance
    68. LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
    69. mService = binder.getService();
    70. mBound = true;
    71. }
    72. @Override
    73. public void onServiceDisconnected(ComponentName arg0) {
    74. mBound = false;
    75. }
    76. };
    77. private class MyReceiver extends BroadcastReceiver {
    78. @Override
    79. public void onReceive(Context arg0, Intent arg1) {
    80. // TODO Auto-generated method stub
    81. String datapassed = arg1.getStringExtra(LocalService.FETCHIG_DATA);
    82. Toast.makeText(MainActivity.this,"successful response fetched from API",Toast.LENGTH_LONG).show();
    83. fetchedText.setText(String.valueOf(datapassed));
    84. }
    85. }
    86. }
    BroadCastReceiver is used to receive data and notifies MainActivity as well, after broadcasting from LocalService class, the fetched response from the API will be sent back from service to MainActivity and received in onReceive() method of BroadCastReceiver. Let's have a LocalService class code in which data fetching from API.
    LocalService.java
    1. package com.example.gkumar.examplebindservice;
    2. import android.app.Service;
    3. import android.content.Intent;
    4. import android.os.Binder;
    5. import android.os.IBinder;
    6. import android.util.Log;
    7. import com.android.volley.Request;
    8. import com.android.volley.Response;
    9. import com.android.volley.VolleyError;
    10. import com.android.volley.toolbox.StringRequest;
    11. /**
    12. * Created by gkumar on 4/11/2016.
    13. */
    14. public class LocalService extends Service {
    15. public final static String MY_ACTION = "MY_ACTION";
    16. public final static String FETCHIG_DATA = "fetchingapidata";
    17. private final IBinder mBinder = new LocalBinder();
    18. public class LocalBinder extends Binder {
    19. LocalService getService() {
    20. // Return this instance of LocalService so clients can call public methods
    21. return LocalService.this;
    22. }
    23. }
    24. @Override
    25. public IBinder onBind(Intent intent) {
    26. return mBinder;
    27. }
    28. /**
    29. * method for clients
    30. */
    31. public void getDataFromAPI() {
    32. String url = "http://theappguruz.in/php/DemoJSON/api/user/contacts";
    33. StringRequest sr = null;
    34. sr = new StringRequest(Request.Method.GET, url,
    35. new Response.Listener<String>() {
    36. @Override
    37. public void onResponse(String response) {
    38. if (response != null) {
    39. Intent intent = new Intent();
    40. intent.setAction(MY_ACTION);
    41. intent.putExtra(FETCHIG_DATA, response.toString());
    42. sendBroadcast(intent);
    43. }
    44. }
    45. }, new Response.ErrorListener() {
    46. @Override
    47. public void onErrorResponse(VolleyError error) {
    48. }
    49. });
    50. VolleySingleton.getInstance(this).getRequestQueue().add(sr);
    51. }
    52. }
      Now you are wondering if that data is fetched using Google's Volley Library. Volley is the most efficient way to fetch data from API and I am going to provide you the singleton class code of volley and build.gradle as well. So you will easily run the entire code written above.
      VolleySingleton.java
      This code will let you use the features of the volley library and add gradle dependencies of volley to your build.gradle as provided below this code.
      1. package com.example.gkumar.examplebindservice;
      2. import android.content.Context;
      3. import android.graphics.Bitmap;
      4. import android.support.v4.util.LruCache;
      5. import com.android.volley.RequestQueue;
      6. import com.android.volley.toolbox.ImageLoader;
      7. import com.android.volley.toolbox.Volley;
      8. public class VolleySingleton {
      9. private static VolleySingleton mInstance = null;
      10. private RequestQueue mRequestQueue;
      11. private ImageLoader mImageLoader;
      12. private VolleySingleton(Context context){
      13. mRequestQueue = Volley.newRequestQueue(context);
      14. mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
      15. private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
      16. public void putBitmap(String url, Bitmap bitmap) {
      17. mCache.put(url, bitmap);
      18. }
      19. public Bitmap getBitmap(String url) {
      20. return mCache.get(url);
      21. }
      22. });
      23. }
      24. public static VolleySingleton getInstance(Context context){
      25. if(mInstance == null){
      26. mInstance = new VolleySingleton(context);
      27. }
      28. return mInstance;
      29. }
      30. public RequestQueue getRequestQueue(){
      31. return this.mRequestQueue;
      32. }
      33. }
      Build.gradle (app)
      1. apply plugin: 'com.android.application'
      2. android {
      3. compileSdkVersion 23
      4. buildToolsVersion "23.0.2"
      5. defaultConfig {
      6. applicationId "com.example.gkumar.examplebindservice"
      7. minSdkVersion 15
      8. targetSdkVersion 23
      9. versionCode 1
      10. versionName "1.0"
      11. }
      12. buildTypes {
      13. release {
      14. minifyEnabled false
      15. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      16. }
      17. }
      18. }
      19. dependencies {
      20. compile fileTree(dir: 'libs', include: ['*.jar'])
      21. testCompile 'junit:junit:4.12'
      22. compile 'com.android.support:appcompat-v7:23.1.1'
      23. compile 'com.android.volley:volley:1.0.0'
      24. }
        Most important is AndroidManifest.xml file and don't forget to register the service in service tag as shown below and permission to access the internet is a must without it you cant fetch data from the network. put this <uses-permission android:name="android.permission.INTERNET" /> in code as we have done.
        1. <?xml version="1.0" encoding="utf-8"?>
        2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        3. package="com.example.gkumar.examplebindservice">
        4. <uses-permission android:name="android.permission.INTERNET" />
        5. <application
        6. android:allowBackup="true"
        7. android:icon="@mipmap/ic_launcher"
        8. android:label="@string/app_name"
        9. android:supportsRtl="true"
        10. android:theme="@style/AppTheme">
        11. <activity android:name=".MainActivity"
        12. android:screenOrientation="portrait">
        13. <intent-filter>
        14. <action android:name="android.intent.action.MAIN" />
        15. <category android:name="android.intent.category.LAUNCHER" />
        16. </intent-filter>
        17. </activity>
        18. <service
        19. android:name="com.example.gkumar.examplebindservice.LocalService"
        20. android:enabled="true"
        21. android:exported="false" />
        22. </application>
        23. </manifest>
          Running the Application
          You can see a button after and a toast show activity connected with service.
          Now click on the Button you will see data has been fetching.
          Response set on the textview as shown

          Summary

          In this article, we have learned how to bind service with activity and send data back to activity from service. In the next article, we will see binding activity with service using messenger.
          Read more articles on Android