Building a Mobile Employee Directory – Step 6: Create a Search Interface using Android’s search dialog

| July 22, 2013 | 1 Comment

Continuing with the mobile employee directory example, I’ve added a Search Interface using Android’s search dialog.

MainActivity.java

package com.himebaugh.employeedirectory;

import java.util.List;

import android.annotation.TargetApi;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;

//	GOAL: Build a native android Mobile Employee Directory 

//	** The result is similar to the sample with Flex and Flash Builder 
//	see http://www.adobe.com/devnet/flex/articles/employee-directory-android-flex.html

//	PURPOSE: Learning how to build an Android App.

//	Step 6: Create a Search Interface using Android's search dialog.
//			1) Modify MainActivity (add SearchView to onCreateOptionsMenu, add onSearchRequested() to onOptionsItemSelected )
//			2) Modify EmployeeProvider (Add Search logic within the ContentProvider)
//			3) Create SearchableActivity
//			4) Create searchable.xml  (in res/xml)
//			5) Modify main.xml  (in res/menu)
//			6) Modify strings.xml  (in res/values)
//			7) Modify AndroidManifest.xml
//	Step 6B: Pass data to DetailActivity using Intent.ACTION_VIEW in place of intent.putExtra
//			1) Modify MainActivity (add Intent.ACTION_VIEW in onListItemClick )
//			2) Modify DetailActivity
//			3) Modify AndroidManifest.xml (add android:mimeType="vnd.android.cursor.item...)

public class MainActivity extends ListActivity  {

	public List<Employee> employees = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

        // Parse xml data in a non-ui thread
        new LoadEmployeesTask().execute();
	}

	private class LoadEmployeesTask extends AsyncTask<String, Void, Cursor> {

		@Override
		protected Cursor doInBackground(String... args) {

			Uri uri = EmployeeProvider.CONTENT_URI;
			String[] projection = { EmployeeDatabase.COLUMN_ID, EmployeeDatabase.COLUMN_FIRSTNAME, EmployeeDatabase.COLUMN_LASTNAME, EmployeeDatabase.COLUMN_TITLE, EmployeeDatabase.COLUMN_DEPARTMENT,
					EmployeeDatabase.COLUMN_CITY, EmployeeDatabase.COLUMN_OFFICE_PHONE, EmployeeDatabase.COLUMN_MOBILE_PHONE, EmployeeDatabase.COLUMN_EMAIL, EmployeeDatabase.COLUMN_PICTURE };
			String selection = null;
			String[] selectionArgs = null;
			String sortOrder = EmployeeDatabase.COLUMN_LASTNAME + " COLLATE LOCALIZED ASC";

			Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);						

			return cursor;
		}

		@Override
		protected void onPostExecute(Cursor cursor) {

			String[] dataColumns = { 
					EmployeeDatabase.COLUMN_FIRSTNAME, 
					EmployeeDatabase.COLUMN_TITLE, 
					EmployeeDatabase.COLUMN_DEPARTMENT, 
					EmployeeDatabase.COLUMN_CITY, 
					EmployeeDatabase.COLUMN_OFFICE_PHONE, 
					EmployeeDatabase.COLUMN_MOBILE_PHONE, 
					EmployeeDatabase.COLUMN_EMAIL, 
					EmployeeDatabase.COLUMN_PICTURE
					};
			int[] viewIDs = { 
					R.id.list_item_name, 
					R.id.list_item_title, 
					R.id.list_item_department, 
					R.id.list_item_city, 
					R.id.list_item_office_phone, 
					R.id.list_item_mobile_phone, 
					R.id.list_item_email, 
					R.id.list_item_picture 
					};

			SimpleCursorAdapter records = new SimpleCursorAdapter(getBaseContext(), R.layout.list_item, cursor, dataColumns, viewIDs, 0);
			setListAdapter(records);
		}

	}

	@Override
	protected void onListItemClick(ListView l, View view, int position, long id) {

//		// get values from selected ListItem
//		String empID = ((TextView) view.findViewById(R.id.list_item_emp_id)).getText().toString();
//		String name = ((TextView) view.findViewById(R.id.list_item_name)).getText().toString();
//		String title = ((TextView) view.findViewById(R.id.list_item_title)).getText().toString();
//		String department = ((TextView) view.findViewById(R.id.list_item_department)).getText().toString();
//		String city = ((TextView) view.findViewById(R.id.list_item_city)).getText().toString();
//		String officePhone = ((TextView) view.findViewById(R.id.list_item_office_phone)).getText().toString();
//		String mobilePhone = ((TextView) view.findViewById(R.id.list_item_mobile_phone)).getText().toString();
//		String email = ((TextView) view.findViewById(R.id.list_item_email)).getText().toString();
//		String picture = ((TextView) view.findViewById(R.id.list_item_picture)).getText().toString();
//
//		// Start new intent
//		Intent intent = new Intent(getApplicationContext(), DetailActivity.class);
//		intent.putExtra("empID", empID);
//		intent.putExtra("name", name);
//		intent.putExtra("title", title);
//		intent.putExtra("department", department);
//		intent.putExtra("city", city);
//		intent.putExtra("officePhone", officePhone);
//		intent.putExtra("mobilePhone", mobilePhone);
//		intent.putExtra("email", email);
//		intent.putExtra("picture", picture);
//		startActivity(intent);

		Uri details = Uri.withAppendedPath(EmployeeProvider.CONTENT_URI, "" + id);
		Intent detailsIntent = new Intent(Intent.ACTION_VIEW, details);
		startActivity(detailsIntent);
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	@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);

		// Get the SearchView and set the searchable configuration
		SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
		SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
		searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
		searchView.setIconifiedByDefault(false);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_search:
			onSearchRequested();
			return true;
		default:
			return false;
		}
	}

}

EmployeeProvider.java

package com.himebaugh.employeedirectory;

import java.util.HashMap;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

public class EmployeeProvider extends ContentProvider {

	private EmployeeDatabase mEmployeeDatabase;

	// Uri matcher to decode incoming URIs.
	private final UriMatcher mUriMatcher;

	private static final String AUTHORITY = "com.himebaugh.employeedirectory.EmployeeProvider";

	// content mime types
	public static final String BASE_DATA_NAME = "employees";
	public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.himebaugh.search." + BASE_DATA_NAME;
	public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.himebaugh.search." + BASE_DATA_NAME;

	// common URIs
	public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_DATA_NAME);
	public static final Uri SEARCH_SUGGEST_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_DATA_NAME + "/" + SearchManager.SUGGEST_URI_PATH_QUERY);

	// matcher
	private static final int EMPLOYEES = 1; // The incoming URI matches the main table URI pattern
	private static final int EMPLOYEE_ID = 2; // The incoming URI matches the main table row ID URI pattern
	private static final int SEARCH_SUGGEST = 3;

	private static final HashMap<String, String> SEARCH_SUGGEST_PROJECTION_MAP;
	static { 
		SEARCH_SUGGEST_PROJECTION_MAP = new HashMap<String, String>();
		SEARCH_SUGGEST_PROJECTION_MAP.put(EmployeeDatabase.COLUMN_ID, EmployeeDatabase.COLUMN_ID); 
		SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_1, EmployeeDatabase.COLUMN_FIRSTNAME + " AS "	+ SearchManager.SUGGEST_COLUMN_TEXT_1); 
		SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_2, EmployeeDatabase.COLUMN_LASTNAME + " AS "	+ SearchManager.SUGGEST_COLUMN_TEXT_2); 
		SEARCH_SUGGEST_PROJECTION_MAP.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, EmployeeDatabase.COLUMN_ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
	}

	public EmployeeProvider() {
		// Create and initialize URI matcher.
		mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		mUriMatcher.addURI(AUTHORITY, EmployeeDatabase.TABLE_EMPLOYEES, EMPLOYEES);
		mUriMatcher.addURI(AUTHORITY, EmployeeDatabase.TABLE_EMPLOYEES + "/#", EMPLOYEE_ID);

        // to get suggestions...
		mUriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
		mUriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
	}

	@Override
	public boolean onCreate() {
		mEmployeeDatabase = new EmployeeDatabase(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

		SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
		queryBuilder.setTables(EmployeeDatabase.TABLE_EMPLOYEES);

		switch (mUriMatcher.match(uri)) {
		case SEARCH_SUGGEST:
			selectionArgs = new String[] { "%" + selectionArgs[0] + "%", "%" + selectionArgs[0] + "%" };
			queryBuilder.setProjectionMap(SEARCH_SUGGEST_PROJECTION_MAP);
			break;
		case EMPLOYEES:
			// no filter
			break;
		case EMPLOYEE_ID:
			queryBuilder.appendWhere(EmployeeDatabase.COLUMN_ID + "=" + uri.getLastPathSegment());
			break;
		default:
			throw new IllegalArgumentException("Unknown URI");
		}

		Cursor cursor = queryBuilder.query(mEmployeeDatabase.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder);
		cursor.setNotificationUri(getContext().getContentResolver(), uri);
		return cursor;
	}

	@Override
	public String getType(Uri uri) {
		switch (mUriMatcher.match(uri)) {
		case EMPLOYEES:
			return CONTENT_TYPE;
		case EMPLOYEE_ID:
			return CONTENT_ITEM_TYPE;
		case SEARCH_SUGGEST:
			return null;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		return 0;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		return 0;
	}

}

SearchableActivity.java

package com.himebaugh.employeedirectory;

import android.annotation.TargetApi;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class SearchableActivity extends ListActivity {

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

		// implement Up Navigation with caret in front of App icon in the Action Bar
		getActionBar().setDisplayHomeAsUpEnabled(true);

		Intent intent = getIntent();
		checkIntent(intent);
	}

	@Override
	protected void onNewIntent(Intent newIntent) {
		// update the activity launch intent
		setIntent(newIntent);
		// handle it
		checkIntent(newIntent);
	}

	private void checkIntent(Intent intent) {
		String query = "";
		String intentAction = intent.getAction();
		if (Intent.ACTION_SEARCH.equals(intentAction)) {
			query = intent.getStringExtra(SearchManager.QUERY);
		} else if (Intent.ACTION_VIEW.equals(intentAction)) {

			Uri details = intent.getData();
			Intent detailsIntent = new Intent(Intent.ACTION_VIEW, details);
			startActivity(detailsIntent);

		}
		fillList(query);
	}

	private void fillList(String query) {

		String wildcardQuery = "%" + query + "%";

		Cursor cursor = getContentResolver().query(
				EmployeeProvider.CONTENT_URI, 
				null, 
				EmployeeDatabase.COLUMN_FIRSTNAME + " LIKE ? OR " + EmployeeDatabase.COLUMN_LASTNAME + " LIKE ?", 
				new String[] { wildcardQuery, wildcardQuery }, 
				null);

		ListAdapter adapter = new SimpleCursorAdapter(
				this, 
				android.R.layout.simple_list_item_2, 
				cursor, 
				new String[] { EmployeeDatabase.COLUMN_FIRSTNAME, EmployeeDatabase.COLUMN_LASTNAME },
				new int[] { android.R.id.text1, android.R.id.text2 },
				0);

		setListAdapter(adapter);
	}

	@Override
	protected void onListItemClick(ListView l, View view, int position, long id) {

		Uri details = Uri.withAppendedPath(EmployeeProvider.CONTENT_URI, "" + id);
		Intent detailsIntent = new Intent(Intent.ACTION_VIEW, details);
		startActivity(detailsIntent);

	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		if (item.getItemId() == android.R.id.home) {

			// This is called when the Home (Up) button is pressed
			// in the Action Bar.
			Intent parentActivityIntent = new Intent(this, MainActivity.class);
			parentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(parentActivityIntent);
			finish();
			return true;
		}

		return super.onOptionsItemSelected(item);

	}

}

DetailActivity.java

 

package com.himebaugh.employeedirectory;

import java.io.IOException;
import java.io.InputStream;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;

public class DetailActivity extends Activity implements OnClickListener {

	public TextView mName;
	public TextView mTitle;
	public TextView mDepartment;
	public TextView mCity;
	private TextView mOfficePhone;
	private TextView mMobilePhone;
	private TextView mSms;
	private TextView mEmail;
	private ImageView mPicture;

	private int mID;
	public Uri uri;

	@SuppressLint("NewApi")
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_detail);

		// implement Up Navigation with caret in front of App icon in the Action
		// Bar		
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			getActionBar().setDisplayHomeAsUpEnabled(true);
		}

		// getting intent data
		Intent intent = getIntent();

		Uri launchData = intent.getData();
		mID = Integer.parseInt(launchData.getLastPathSegment());

		uri = ContentUris.withAppendedId(EmployeeProvider.CONTENT_URI, mID);

		// Update values on the screen with XML values from previous intent
		mName = (TextView) findViewById(R.id.activity_detail_name);
		mTitle = (TextView) findViewById(R.id.activity_detail_title);
		mDepartment = (TextView) findViewById(R.id.activity_detail_department);
		mCity = (TextView) findViewById(R.id.activity_detail_city);
		mOfficePhone = (TextView) findViewById(R.id.activity_detail_office_phone);
		mMobilePhone = (TextView) findViewById(R.id.activity_detail_mobile_phone);
		mSms = (TextView) findViewById(R.id.activity_detail_sms);
		mEmail = (TextView) findViewById(R.id.activity_detail_email);
		mPicture = (ImageView) findViewById(R.id.activity_detail_picture);

		// listen for button clicks
		findViewById(R.id.activity_detail_call_office_button).setOnClickListener(this);
		findViewById(R.id.activity_detail_office_phone).setOnClickListener(this);
		findViewById(R.id.activity_detail_call_mobile_button).setOnClickListener(this);
		findViewById(R.id.activity_detail_mobile_phone).setOnClickListener(this);
		findViewById(R.id.activity_detail_send_sms_button).setOnClickListener(this);
		findViewById(R.id.activity_detail_sms).setOnClickListener(this);
		findViewById(R.id.activity_detail_send_email_button).setOnClickListener(this);
		findViewById(R.id.activity_detail_email).setOnClickListener(this);

		// add PhoneStateListener FROM
		// http://www.mkyong.com/android/how-to-make-a-phone-call-in-android/
		PhoneCallListener phoneListener = new PhoneCallListener();
		TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
		telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);

		// Parse xml data in a non-ui thread
		new LoadEmployeesTask().execute();

	}

	private class LoadEmployeesTask extends AsyncTask<String, Void, Cursor> {

		@Override
		protected Cursor doInBackground(String... args) {

			String[] projection = { EmployeeDatabase.COLUMN_ID, EmployeeDatabase.COLUMN_FIRSTNAME,
					EmployeeDatabase.COLUMN_LASTNAME, EmployeeDatabase.COLUMN_TITLE,
					EmployeeDatabase.COLUMN_DEPARTMENT, EmployeeDatabase.COLUMN_CITY,
					EmployeeDatabase.COLUMN_OFFICE_PHONE, EmployeeDatabase.COLUMN_MOBILE_PHONE,
					EmployeeDatabase.COLUMN_EMAIL, EmployeeDatabase.COLUMN_PICTURE };
			String selection = null;
			String[] selectionArgs = null;
			String sortOrder = null;

			Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);

			return cursor;
		}

		@Override
		protected void onPostExecute(Cursor cursor) {

			if (cursor != null && cursor.getCount() > 0) {
				cursor.moveToFirst();

				mName.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_FIRSTNAME)));
				mName.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_LASTNAME)));

				mTitle.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_TITLE)));
				mDepartment.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_DEPARTMENT)));
				mCity.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_CITY)));
				mOfficePhone.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_OFFICE_PHONE)));
				mMobilePhone.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_MOBILE_PHONE)));
				mSms.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_MOBILE_PHONE)));
				mEmail.setText(cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_EMAIL)));

				InputStream is;
				try {
					is = getAssets().open(
							"pics/" + cursor.getString(cursor.getColumnIndex(EmployeeDatabase.COLUMN_PICTURE)));
					Bitmap bit = BitmapFactory.decodeStream(is);
					mPicture.setImageBitmap(bit);
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the options menu from XML
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main, menu);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		if (item.getItemId() == android.R.id.home) {

			// This is called when the Home (Up) button is pressed in the Action
			// Bar.
			Intent parentActivityIntent = new Intent(this, MainActivity.class);
			parentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(parentActivityIntent);
			finish();
			return true;
		}

		return super.onOptionsItemSelected(item);

	}

	// @Override
	public void onClick(View view) {

		switch (view.getId()) {

		case R.id.activity_detail_call_office_button:
		case R.id.activity_detail_office_phone: // clicking on textView will
												// have same action as the
												// button

			Intent callIntent = new Intent(Intent.ACTION_CALL);
			callIntent.setData(Uri.parse("tel:" + mOfficePhone.getText().toString()));
			startActivity(callIntent);
			break;

		case R.id.activity_detail_call_mobile_button:
		case R.id.activity_detail_mobile_phone: // clicking on textView will
												// have same action as the
												// button

			Intent callIntent2 = new Intent(Intent.ACTION_CALL);
			callIntent2.setData(Uri.parse("tel:" + mMobilePhone.getText().toString()));
			startActivity(callIntent2);
			break;

		case R.id.activity_detail_send_sms_button:
		case R.id.activity_detail_sms: // clicking on textView will have same
										// action as the button

			Intent smsIntent = new Intent(Intent.ACTION_SENDTO);
			smsIntent.setData(Uri.parse("smsto:" + mMobilePhone.getText().toString()));
			// smsIntent.putExtra("sms_body", "Hello " +
			// mName.getText().toString() );
			startActivity(smsIntent);
			break;

		case R.id.activity_detail_send_email_button:
		case R.id.activity_detail_email: // clicking on textView will have same
											// action as the button

			String to = mEmail.getText().toString();
			String subject = "textSubject";
			String message = "textMessage";

			Intent email = new Intent(Intent.ACTION_SEND);
			email.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
			email.putExtra(Intent.EXTRA_SUBJECT, subject);
			email.putExtra(Intent.EXTRA_TEXT, message);

			// prompts email apps
			email.setType("message/rfc822");

			startActivity(Intent.createChooser(email, "Choose an Email client :"));
			break;

		}

	}

	// monitor phone call activities
	private class PhoneCallListener extends PhoneStateListener {

		private boolean isPhoneCalling = false;

		@Override
		public void onCallStateChanged(int state, String incomingNumber) {

			if (TelephonyManager.CALL_STATE_RINGING == state) {
				// phone ringing
			}

			if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
				// active
				isPhoneCalling = true;
			}

			if (TelephonyManager.CALL_STATE_IDLE == state) {
				// run when class initial and phone call ended,
				// need detect flag from CALL_STATE_OFFHOOK
				if (isPhoneCalling) {
					// restart app
					Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(
							getBaseContext().getPackageName());
					i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
					startActivity(i);

					isPhoneCalling = false;
				}

			}
		}
	}

}

main.xml  (in res/menu)

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/menu_search"
        android:actionViewClass="android.widget.SearchView"
        android:icon="@android:drawable/ic_menu_search"
        android:showAsAction="always|collapseActionView|withText"
        android:title="@string/menu_search"/>

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/action_settings"/>

</menu>

strings.xml  (in res/values)

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Employee Directory</string>
    <string name="employee_details">Employee Details</string>
    <string name="employee_photo">Employee Photo</string>
    <string name="detail_header1">Call Office</string>
    <string name="detail_header2">Call Mobile</string>
    <string name="detail_header3">SMS</string>
    <string name="detail_header4">Email</string>
    <string name="place_holder">Text will be replaced</string>
    <string name="action_settings">Settings</string>
    <string name="menu_search">Search</string>
    <string name="search_hint">"Search employees" </string>

</resources>

searchable.xml  (in res/xml)

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.himebaugh.employeedirectory.EmployeeProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestIntentData="content://com.himebaugh.employeedirectory.EmployeeProvider/employees"
    android:searchSuggestSelection="first_name LIKE ? OR last_name LIKE ?"
    android:searchSuggestThreshold="2"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
</searchable>

AndroidManifest.xml

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <!-- Main -->
        <activity
            android:name="com.himebaugh.employeedirectory.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>

        <!-- Detail -->
        <activity
            android:name="com.himebaugh.employeedirectory.DetailActivity"
            android:label="@string/employee_details" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="vnd.android.cursor.item/vnd.himebaugh.search.employees" />
            </intent-filter>
        </activity>

        <!-- Searchable -->
        <activity
            android:name=".SearchableActivity"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable" />
        </activity>

        <!-- Points to searchable activity so the whole app can invoke search. -->
        <meta-data
            android:name="android.app.default_searchable"
            android:value="com.himebaugh.employeedirectory.SearchableActivity" />

        <provider
            android:name="com.himebaugh.employeedirectory.EmployeeProvider"
            android:authorities="com.himebaugh.employeedirectory.EmployeeProvider"
            android:multiprocess="true" >
        </provider>
    </application>

</manifest>

Other files unchanged see Step 5

Screenshots of the application

App-EmployeeDirectory-01

 

App-EmployeeDirectory-01

 

App-EmployeeDirectory-01

 

Tags: , , ,

Category: Android Application Development

Comments (1)

Trackback URL | Comments RSS Feed

  1. Langdon Himebaugh says:

    The code has been place on GitHub. Download at https://github.com/langhimebaugh/EmployeeDirectory-Step-06

Leave a Reply to Langdon Himebaugh Cancel reply

Your email address will not be published. Required fields are marked *