• facebook
  • twitter
  • google+
  • pinterest
  • rss

Thursday, June 5, 2014

Android Background Service, IntentService Example

Android IntentService sample img
In this post I'll try to make a simple android app that uses an IntentService to execute a task in the background, the UI thread call the IntentService and then give it a task to be executed in the background service. When the task is complete, the IntentService (Background Service) will send the result back to the caller (UI thread).

What exactly IntentService is? check this link to find out more about IntentService and Service in Android.

In this sample app I used the IntentService to perform a reading operation in the background Service. First, user will choose a text file from the android storages, and then the file will be sent to the IntentService to be read (reading operation is executed in the background service). When the task or operation is complete, the content of the file will be shown as a final result through a TextView on UI thread and the IntentService will stop itself.

The sample app was built using eclipse, java 1.7, and can run on Android 2.1 Eclair (API 7) - Android 4.4 KitKat (API 19).


Note:
  • > The sample app uses a support library (android-support-v7-appcompat), see how to set up a support library on eclipse.
  • > The sample app needs a third-party app to select a text file from the android storages, such as a File Manager.

Download: IntentServiceSample.zip (source), IntentServiceSample.apk (Apk).

src/com.me.intentservicesample/MainActivity.java
package com.me.intentservicesample;

import java.net.URISyntaxException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

	private static final int REQ_CODE = 0;
	//private ResponseReciever mResponseReciever = new ResponseReciever();
	
	private BroadcastReceiver reciever = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			Bundle bundle = intent.getExtras();
			if (bundle != null) {
				String data = bundle.getString(Services.DATA);
				int status = bundle.getInt(Services.STATUS);
				if (status == RESULT_OK) {
					//MainActivity mainActivity = new MainActivity();
					Toast.makeText(MainActivity.this, "Finished",
							Toast.LENGTH_LONG).show();
					updateTextView(data);
				}
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_main);

		if (savedInstanceState == null) {
			getSupportFragmentManager().beginTransaction()
					.add(R.id.container, new PlaceholderFragment()).commit();
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		IntentFilter intentFilter = new IntentFilter(Services.ACTION_BROADCAST);
		//intentFilter.addDataScheme("text/plain");
		
		LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver(
				reciever, intentFilter);
	}

	@Override
	protected void onPause() {
		super.onPause();
		LocalBroadcastManager.getInstance(MainActivity.this)
				.unregisterReceiver(reciever);
	}
	
	/**
	private class ResponseReciever extends BroadcastReceiver {

		@Override
		public void onReceive(Context ctx, Intent intent) {
			// TODO Auto-generated method stub
			Bundle bundle = intent.getExtras();
			if (bundle != null) {
				String data = bundle.getString(Services.DATA);
				int status = bundle.getInt(Services.STATUS);
				if (status == RESULT_OK) {
					//MainActivity mainActivity = new MainActivity();
					Toast.makeText(MainActivity.this, "Finished",
							Toast.LENGTH_LONG).show();
					//mainActivity.updateTextView(data);
				}
			}

		}

	}
	*/

	protected void updateTextView(String data) {
		TextView tv = (TextView) findViewById(R.id.textView);
		tv.setText(data.toString());
	}

	/** called when button "Open a File" clicked */
	public void openFile(View v) {

		// use implicit Intent to open a file
		Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
		intent.setType("*/.txt");
		intent.addCategory(Intent.CATEGORY_OPENABLE);

		try {
			startActivityForResult(
					Intent.createChooser(intent, "Select a file txt"), REQ_CODE);
		} catch (android.content.ActivityNotFoundException ex) {
			Toast.makeText(getBaseContext(), "You a need a File Manager",
					Toast.LENGTH_LONG).show();
			ex.printStackTrace();
		}
	}

	@Override
	protected void onActivityResult(int reqCode, int resultCode, Intent data) {

		// check activity result base on reqCode
		// reqCode must be same as REQ_CODE
		switch (reqCode) {
		case REQ_CODE:
			if (resultCode == RESULT_OK) {

				// get Uri data from intent
				Uri uri = data.getData();

				String path = null;
				try {

					// convert Uri to file path (String)
					path = getPath(getBaseContext(), uri);

					// send the file path to Service
					this.sendToService(path);
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/** called to start the Service */
	private void sendToService(String s) {

		// create an explicit Intent for the Service
		Intent intentService = new Intent(MainActivity.this, Services.class);
		intentService.putExtra(Services.PATH, s);
		startService(intentService);
	}

	public static String getPath(Context context, Uri uri)
			throws URISyntaxException {
		if ("content".equalsIgnoreCase(uri.getScheme())) {
			String[] projection = { "_data" };
			Cursor cursor = null;

			try {
				cursor = context.getContentResolver().query(uri, projection,
						null, null, null);
				int column_index = cursor.getColumnIndexOrThrow("_data");
				if (cursor.moveToFirst()) {
					return cursor.getString(column_index);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if ("file".equalsIgnoreCase(uri.getScheme())) {
			return uri.getPath();
		}

		return null;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment {

		public PlaceholderFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_main, container,
					false);
			return rootView;
		}
	}

}


src/com.me.intentservicesample/Services.java
package com.me.intentservicesample;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;

public class Services extends IntentService {

	private static int mStatus = Activity.RESULT_CANCELED;
	public static final String PATH = "com.me.intentservicesample.PATH";
	public static final String ACTION_BROADCAST = "com.me.intentservicesample.BROADCAST";
	public static final String STATUS = "com.me.intentservicesample.STATUS";
	public static final String DATA = "com.me.intentservicesample.DATA";

	public Services() {
		super("Services");
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub

		// get data from incoming intent
		String filePath = intent.getStringExtra(PATH);

		String fileContent = this.readFile(filePath);
		if (fileContent != null) {

			// report the work status to registered components
			publishResult(mStatus, fileContent);

		}
	}

	private void publishResult(int status, String data) {
		Intent localIntent = new Intent(Services.ACTION_BROADCAST);
		localIntent.putExtra(Services.STATUS, status);
		localIntent.putExtra(Services.DATA, data);
		LocalBroadcastManager.getInstance(Services.this).sendBroadcast(
				localIntent);
	}

	/** read the incoming file to get the file content as String */
	private String readFile(String path) {
		File file = new File(path);
		int i, j = 0;
		byte[] data = new byte[(int) file.length()];
		String string = null;
		InputStream in = null;
		try {
			in = new BufferedInputStream(new FileInputStream(file));
			while ((i = in.read()) != -1) {
				data[j++] = (byte) i;
			}
			string = byteToString(data).toString();
			mStatus = Activity.RESULT_OK;
			return string;
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			// TODO Auto-generated catch block
			ex.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return string;

	}

	/** called to cast byte array to String */
	private static String byteToString(byte[] b) {
		char[] c = new char[b.length];
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < c.length; i++) {
			c[i] = (char) b[i];
			sb.append(c[i]);
		}

		return sb.toString();
	}
}


res/layout/activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.me.intentservicesample.MainActivity"
    tools:ignore="MergeRootFrame" />



res/layout/fragment_main.xml
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.me.intentservicesample.MainActivity$PlaceholderFragment" >

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:onClick="openFile"
        android:text="Open a File" />

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/button"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="10dp"
            android:singleLine="false"
            android:text="@string/hello_world" />
    </LinearLayout>

</RelativeLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.me.intentservicesample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service
            android:name="com.me.intentservicesample.Services"
            android:exported="false" >
        </service>

        <activity
            android:name="com.me.intentservicesample.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


When you launch the sample app:

Android IntentService sample img


When the button "Open a File" was clicked:

Android IntentService sample img


After completing the operation, show the final result to the user:



Source: Android Developer (Background Service).

2 comments:

  1. Webnet is the best mobile app development company in Karachi, Pakistan. We are pushing more relationship in sensible rates, for occasion, SEO, SMO, LOGO masterminding and so on.

    ReplyDelete
  2. There are a lot of web designing companies in Faisalabad but In my opinion Bizline is the best one.

    ReplyDelete