Android Database Content Provider Example using SQLite Database

Android applications can access data directly from a SQLite database using the database helper but for other applications to get access to the same data you have to create a Content Provider. Content Providers encapsulate the data access, provide security using the Android Manifest and standardize the access via a Content URI. If the data is used only by your application there is no need to create a content provider but you can always do that in case a need that arises in the future.

The contentProvider must implement the following methods query(), insert(), update(), delete(), getType() and onCreate() to provide access to the underlying data. If you don't implement the delete method just send an exception to let the application know or if you don't get an URI match. If you have done SQLite database access using the database helper you will find there is not much difference here. All you have to do it create a provider that matches URIs and then figures out what to do with the request.

In this example we will create a simple maintenance program to maintain a list of countries. The access to the country database will be thru the Content Provider that will implement all the CRUD functions. On the screen we will display an existing list of countries and let the user add, update and delete a country. Here is the step by step process to implement the above mentioned functionality using the Content Provider.

Android Database Content Provider Example
Android Database Content Provider Insert Record
Android ListView using CursorLoader and Content Provider

Step 1: Create the SQLite database Object - CountriesDb.java

package com.as400samplecode;

import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class CountriesDb {

 public static final String KEY_ROWID = "_id";
 public static final String KEY_CODE = "code";
 public static final String KEY_NAME = "name";
 public static final String KEY_CONTINENT = "continent";

 private static final String LOG_TAG = "CountriesDb";
 public static final String SQLITE_TABLE = "Country";

 private static final String DATABASE_CREATE =
  "CREATE TABLE if not exists " + SQLITE_TABLE + " (" +
   KEY_ROWID + " integer PRIMARY KEY autoincrement," +
   KEY_CODE + "," +
   KEY_NAME + "," +
   KEY_CONTINENT + "," +
   " UNIQUE (" + KEY_CODE +"));";

 public static void onCreate(SQLiteDatabase db) {
  Log.w(LOG_TAG, DATABASE_CREATE);
  db.execSQL(DATABASE_CREATE);
 }

 public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to "
    + newVersion + ", which will destroy all old data");
  db.execSQL("DROP TABLE IF EXISTS " + SQLITE_TABLE);
  onCreate(db);
 }

}

Step 2: Create the SQLite database Helper - MyDatabaseHelper.java

package com.as400samplecode;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabaseHelper extends SQLiteOpenHelper {

 private static final String DATABASE_NAME = "TheWorld";
 private static final int DATABASE_VERSION = 1;

 MyDatabaseHelper(Context context) {
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {
  CountriesDb.onCreate(db);
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  CountriesDb.onUpgrade(db, oldVersion, newVersion);
 }


}

Step 3: Create the ContentProvider - MyContentProvider.java

package com.as400samplecode;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class MyContentProvider extends ContentProvider{

 private MyDatabaseHelper dbHelper;

 private static final int ALL_COUNTRIES = 1;
 private static final int SINGLE_COUNTRY = 2;

 // authority is the symbolic name of your provider
 // To avoid conflicts with other providers, you should use 
 // Internet domain ownership (in reverse) as the basis of your provider authority. 
 private static final String AUTHORITY = "com.as400samplecode.contentprovider";

 // create content URIs from the authority by appending path to database table
 public static final Uri CONTENT_URI = 
  Uri.parse("content://" + AUTHORITY + "/countries");

 // a content URI pattern matches content URIs using wildcard characters:
 // *: Matches a string of any valid characters of any length.
    // #: Matches a string of numeric characters of any length.
 private static final UriMatcher uriMatcher;
 static {
  uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  uriMatcher.addURI(AUTHORITY, "countries", ALL_COUNTRIES);
  uriMatcher.addURI(AUTHORITY, "countries/#", SINGLE_COUNTRY);
 }

 // system calls onCreate() when it starts up the provider.
 @Override
 public boolean onCreate() {
  // get access to the database helper
  dbHelper = new MyDatabaseHelper(getContext());
  return false;
 }

 //Return the MIME type corresponding to a content URI
 @Override
 public String getType(Uri uri) {
  
  switch (uriMatcher.match(uri)) {
  case ALL_COUNTRIES: 
   return "vnd.android.cursor.dir/vnd.com.as400samplecode.contentprovider.countries";
  case SINGLE_COUNTRY: 
   return "vnd.android.cursor.item/vnd.com.as400samplecode.contentprovider.countries";
  default: 
   throw new IllegalArgumentException("Unsupported URI: " + uri);
  }
 }

 // The insert() method adds a new row to the appropriate table, using the values 
 // in the ContentValues argument. If a column name is not in the ContentValues argument, 
 // you may want to provide a default value for it either in your provider code or in 
 // your database schema. 
 @Override
 public Uri insert(Uri uri, ContentValues values) {
  
  SQLiteDatabase db = dbHelper.getWritableDatabase();
  switch (uriMatcher.match(uri)) {
  case ALL_COUNTRIES:
   //do nothing
   break;
  default:
   throw new IllegalArgumentException("Unsupported URI: " + uri);
  }
  long id = db.insert(CountriesDb.SQLITE_TABLE, null, values);
  getContext().getContentResolver().notifyChange(uri, null);
  return Uri.parse(CONTENT_URI + "/" + id);
 }

 // The query() method must return a Cursor object, or if it fails, 
 // throw an Exception. If you are using an SQLite database as your data storage, 
 // you can simply return the Cursor returned by one of the query() methods of the 
 // SQLiteDatabase class. If the query does not match any rows, you should return a 
 // Cursor instance whose getCount() method returns 0. You should return null only 
 // if an internal error occurred during the query process. 
 @Override
 public Cursor query(Uri uri, String[] projection, String selection,
   String[] selectionArgs, String sortOrder) {

  SQLiteDatabase db = dbHelper.getWritableDatabase();
  SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
  queryBuilder.setTables(CountriesDb.SQLITE_TABLE);

  switch (uriMatcher.match(uri)) {
  case ALL_COUNTRIES:
   //do nothing 
   break;
  case SINGLE_COUNTRY:
   String id = uri.getPathSegments().get(1);
   queryBuilder.appendWhere(CountriesDb.KEY_ROWID + "=" + id);
   break;
  default:
   throw new IllegalArgumentException("Unsupported URI: " + uri);
  }

  Cursor cursor = queryBuilder.query(db, projection, selection,
    selectionArgs, null, null, sortOrder);
  return cursor;

 }
 
 // The delete() method deletes rows based on the seletion or if an id is 
 // provided then it deleted a single row. The methods returns the numbers
 // of records delete from the database. If you choose not to delete the data
 // physically then just update a flag here.
 @Override
 public int delete(Uri uri, String selection, String[] selectionArgs) {

  SQLiteDatabase db = dbHelper.getWritableDatabase();
  switch (uriMatcher.match(uri)) {
  case ALL_COUNTRIES:
   //do nothing 
   break;
  case SINGLE_COUNTRY:
   String id = uri.getPathSegments().get(1);
   selection = CountriesDb.KEY_ROWID + "=" + id
   + (!TextUtils.isEmpty(selection) ? 
     " AND (" + selection + ')' : "");
   break;
  default:
   throw new IllegalArgumentException("Unsupported URI: " + uri);
  }
  int deleteCount = db.delete(CountriesDb.SQLITE_TABLE, selection, selectionArgs);
  getContext().getContentResolver().notifyChange(uri, null);
  return deleteCount;
 }

 // The update method() is same as delete() which updates multiple rows
 // based on the selection or a single row if the row id is provided. The
 // update method returns the number of updated rows.
 @Override
 public int update(Uri uri, ContentValues values, String selection,
   String[] selectionArgs) {
  SQLiteDatabase db = dbHelper.getWritableDatabase();
  switch (uriMatcher.match(uri)) {
  case ALL_COUNTRIES:
   //do nothing 
   break;
  case SINGLE_COUNTRY:
   String id = uri.getPathSegments().get(1);
   selection = CountriesDb.KEY_ROWID + "=" + id
   + (!TextUtils.isEmpty(selection) ? 
     " AND (" + selection + ')' : "");
   break;
  default:
   throw new IllegalArgumentException("Unsupported URI: " + uri);
  }
  int updateCount = db.update(CountriesDb.SQLITE_TABLE, values, selection, selectionArgs);
  getContext().getContentResolver().notifyChange(uri, null);
  return updateCount;
 }

}

Step 4: Row Layout for Country Display - country_info.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent" android:layout_height="wrap_content"
 android:orientation="vertical" android:padding="6dip">

 <TextView android:id="@+id/textView1" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_alignParentTop="true" android:text="Country:"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/textView2" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentTop="true"
  android:layout_toRightOf="@+id/textView1" android:text="("
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/code" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentTop="true"
  android:layout_toRightOf="@+id/textView2" android:text="Medium Text"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/textView3" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentTop="true"
  android:layout_toRightOf="@+id/code" android:text=")"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/name" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentTop="true"
  android:layout_toRightOf="@+id/textView3" android:text="Medium Text"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/textView4" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_below="@+id/textView1" android:text="Continent:"
  android:textAppearance="?android:attr/textAppearanceMedium" />

 <TextView android:id="@+id/continent" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignBaseline="@+id/textView4"
  android:layout_alignBottom="@+id/textView4" android:layout_toRightOf="@+id/textView4"
  android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

Step 5: Main Layout with ListView - activity_main.xml

<?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">

 <Button android:id="@+id/add" style="?android:attr/buttonStyleSmall"
  android:layout_width="fill_parent" android:layout_height="wrap_content"
  android:layout_alignParentLeft="true" android:layout_alignParentTop="true"
  android:text="@string/add_country" />

 <ListView android:id="@+id/countryList" android:layout_width="match_parent"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_below="@+id/add" />


</RelativeLayout>

Step 6: Main Activity using LoaderManager for Country List - MainActivity.java

The list of countries is displayed in a ListView using the CursorLoader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. After the loader has finished its loading just swap the new cursor from the Content Provider and return the old Cursor.
package com.as400samplecode;

import android.os.Bundle;
import android.app.Activity;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.app.LoaderManager;

public class MainActivity extends Activity implements
LoaderManager.LoaderCallbacks<Cursor>{

 private SimpleCursorAdapter dataAdapter;

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

  displayListView(); 

  Button add = (Button) findViewById(R.id.add);
  add.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    // starts a new Intent to add a Country
    Intent countryEdit = new Intent(getBaseContext(), CountryEdit.class);
    Bundle bundle = new Bundle();
    bundle.putString("mode", "add");
    countryEdit.putExtras(bundle);
    startActivity(countryEdit);
   }
  });

 }

 @Override
 protected void onResume() {
  super.onResume();
  //Starts a new or restarts an existing Loader in this manager
  getLoaderManager().restartLoader(0, null, this);
 }

 private void displayListView() {


  // The desired columns to be bound
  String[] columns = new String[] {
    CountriesDb.KEY_CODE,
    CountriesDb.KEY_NAME,
    CountriesDb.KEY_CONTINENT
  };

  // the XML defined views which the data will be bound to
  int[] to = new int[] { 
    R.id.code,
    R.id.name,
    R.id.continent,
  };

  // create an adapter from the SimpleCursorAdapter
  dataAdapter = new SimpleCursorAdapter(
    this, 
    R.layout.country_info, 
    null, 
    columns, 
    to,
    0);

  // get reference to the ListView
  ListView listView = (ListView) findViewById(R.id.countryList);
  // Assign adapter to ListView
  listView.setAdapter(dataAdapter);
  //Ensures a loader is initialized and active.
  getLoaderManager().initLoader(0, null, this);


  listView.setOnItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView<?> listView, View view, 
     int position, long id) {
    // Get the cursor, positioned to the corresponding row in the result set
    Cursor cursor = (Cursor) listView.getItemAtPosition(position);

    // display the selected country
    String countryCode = 
     cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CODE));
    Toast.makeText(getApplicationContext(),
      countryCode, Toast.LENGTH_SHORT).show();

    String rowId = 
     cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_ROWID));
    
    // starts a new Intent to update/delete a Country
    // pass in row Id to create the Content URI for a single row
    Intent countryEdit = new Intent(getBaseContext(), CountryEdit.class);
    Bundle bundle = new Bundle();
    bundle.putString("mode", "update");
    bundle.putString("rowId", rowId);
    countryEdit.putExtras(bundle);
    startActivity(countryEdit);

   }
  });

 }

 // This is called when a new Loader needs to be created.
 @Override
 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
  String[] projection = { 
    CountriesDb.KEY_ROWID,
    CountriesDb.KEY_CODE, 
    CountriesDb.KEY_NAME, 
    CountriesDb.KEY_CONTINENT};
  CursorLoader cursorLoader = new CursorLoader(this,
    MyContentProvider.CONTENT_URI, projection, null, null, null);
  return cursorLoader;
 }

 @Override
 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
  // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        dataAdapter.swapCursor(data);
 }

 @Override
 public void onLoaderReset(Loader<Cursor> loader) {
  // This is called when the last Cursor provided to onLoadFinished()
  // above is about to be closed.  We need to make sure we are no
  // longer using it.
  dataAdapter.swapCursor(null);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }
}


Step 7: Detail Layout for Insert,Update and Delete - detail_page.xml

<?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" android:paddingLeft="10dp">

 <TextView android:id="@+id/textView1" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_alignParentTop="true" android:text="@string/country_info"
  android:textAppearance="?android:attr/textAppearanceMedium"
  android:textStyle="bold" />

 <TextView android:id="@+id/choose_text" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_below="@+id/textView1" android:text="@string/choose_text"
  android:textAppearance="?android:attr/textAppearanceMedium"
  android:layout_marginTop="10dp" />

 <Spinner android:id="@+id/continentList" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_below="@+id/textView1"
  android:layout_marginTop="10dp" android:layout_toRightOf="@id/choose_text" />

 <TextView android:id="@+id/textView2" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_below="@+id/continentList" android:text="@string/country_code"
  android:textAppearance="?android:attr/textAppearanceMedium"
  android:layout_marginTop="10dp" />

 <TextView android:id="@+id/textView3" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignParentLeft="true"
  android:layout_below="@+id/textView2" android:layout_marginTop="13dp"
  android:text="@string/country_name" android:textAppearance="?android:attr/textAppearanceMedium" />

 <EditText android:id="@+id/code" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignBottom="@+id/textView2"
  android:layout_alignLeft="@+id/name" android:layout_toRightOf="@+id/textView2"
  android:ems="3" android:maxLength="3" android:inputType="textCapCharacters"
  android:paddingLeft="10dp">

  <requestFocus />
 </EditText>

 <EditText android:id="@+id/name" android:layout_width="wrap_content"
  android:layout_height="wrap_content" android:layout_alignBottom="@+id/textView3"
  android:layout_toRightOf="@+id/textView3" android:ems="30"
  android:inputType="text" android:paddingLeft="10dp" />

 <Button android:id="@+id/save" style="?android:attr/buttonStyleSmall"
  android:layout_width="wrap_content" android:layout_height="wrap_content"
  android:layout_alignParentRight="true" android:layout_below="@+id/name"
  android:layout_marginRight="21dp" android:layout_marginTop="13dp"
  android:text="@string/save_country" />

 <Button android:id="@+id/delete" style="?android:attr/buttonStyleSmall"
  android:layout_width="wrap_content" android:layout_height="wrap_content"
  android:layout_alignBaseline="@+id/save" android:layout_alignBottom="@+id/save"
  android:layout_toLeftOf="@+id/save" android:text="@string/del_country" />

</RelativeLayout>

Step 8: Detail Activity implementing CRUD operations - CountryEdit.java

package com.as400samplecode;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

public class CountryEdit extends Activity implements OnClickListener{

 private Spinner continentList;
 private Button save, delete;
 private String mode;
 private EditText code, name;
 private String id;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.detail_page);

  // get the values passed to the activity from the calling activity
  // determine the mode - add, update or delete
  if (this.getIntent().getExtras() != null){
   Bundle bundle = this.getIntent().getExtras();
   mode = bundle.getString("mode");
  }

  // get references to the buttons and attach listeners
  save = (Button) findViewById(R.id.save);
  save.setOnClickListener(this);
  delete = (Button) findViewById(R.id.delete);
  delete.setOnClickListener(this);

  code = (EditText) findViewById(R.id.code);
  name = (EditText) findViewById(R.id.name);

  
  // create a dropdown for users to select various continents
  continentList = (Spinner) findViewById(R.id.continentList);
  ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
    R.array.continent_array, android.R.layout.simple_spinner_item);
  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
  continentList.setAdapter(adapter);

  // if in add mode disable the delete option
  if(mode.trim().equalsIgnoreCase("add")){
   delete.setEnabled(false);
  }
  // get the rowId for the specific country 
  else{
   Bundle bundle = this.getIntent().getExtras();
   id = bundle.getString("rowId");
   loadCountryInfo();
  }

 }

 public void onClick(View v) {

  // get values from the spinner and the input text fields
  String myContinent = continentList.getSelectedItem().toString();
  String myCode = code.getText().toString();
  String myName = name.getText().toString();

  // check for blanks
  if(myCode.trim().equalsIgnoreCase("")){
   Toast.makeText(getBaseContext(), "Please ENTER country code", Toast.LENGTH_LONG).show();
   return;
  }

  // check for blanks
  if(myName.trim().equalsIgnoreCase("")){
   Toast.makeText(getBaseContext(), "Please ENTER country name", Toast.LENGTH_LONG).show();
   return;
  }

  
  switch (v.getId()) {
  case R.id.save:
   ContentValues values = new ContentValues();
   values.put(CountriesDb.KEY_CODE, myCode);
   values.put(CountriesDb.KEY_NAME, myName);
   values.put(CountriesDb.KEY_CONTINENT, myContinent);
   
   // insert a record
   if(mode.trim().equalsIgnoreCase("add")){
    getContentResolver().insert(MyContentProvider.CONTENT_URI, values);
   }
   // update a record
   else {
    Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
    getContentResolver().update(uri, values, null, null);
   }
   finish();
   break;

  case R.id.delete:
   // delete a record
   Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
   getContentResolver().delete(uri, null, null);
   finish();
   break;

   // More buttons go here (if any) ...

  }
 }

 // based on the rowId get all information from the Content Provider 
 // about that country
 private void loadCountryInfo(){

  String[] projection = { 
    CountriesDb.KEY_ROWID,
    CountriesDb.KEY_CODE, 
    CountriesDb.KEY_NAME, 
    CountriesDb.KEY_CONTINENT};
  Uri uri = Uri.parse(MyContentProvider.CONTENT_URI + "/" + id);
  Cursor cursor = getContentResolver().query(uri, projection, null, null,
    null);
  if (cursor != null) {
   cursor.moveToFirst();
   String myCode = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CODE));
   String myName = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_NAME));
   String myContinent = cursor.getString(cursor.getColumnIndexOrThrow(CountriesDb.KEY_CONTINENT));
   code.setText(myCode);
   name.setText(myName);
   continentList.setSelection(getIndex(continentList, myContinent));
  }


 }

 // this sets the spinner selection based on the value 
 private int getIndex(Spinner spinner, String myString){

  int index = 0;

  for (int i=0;i<spinner.getCount();i++){
   if (spinner.getItemAtPosition(i).equals(myString)){
    index = i;
   }
  }
  return index;
 }

}

Step 9: Define Strings and Arrays - strings.xml

<resources>

    <string name="app_name">SQLite Database Content Provider</string>
   <string name="menu_settings">Settings</string>
   
    <string name="add_country">Add a new Country</string>
    <string name="country_info">Country Information</string>
    <string name="country_code">Code</string>
    <string name="country_name">Name</string>
    <string name="save_country">Save</string>
    <string name="del_country">Delete</string>
    <string name="choose_text">Choose Continent</string>
    
    <string-array name="continent_array">
        <item>Africa</item>
        <item>Antartica</item>
        <item>Asia</item>
        <item>Europe</item>
        <item>North America</item>
        <item>Oceania</item>
        <item>South America</item>
    </string-array>

</resources>

Step 10: Define Android Manifest file

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

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

 <application android:icon="@drawable/ic_launcher"
  android:label="@string/app_name" android:theme="@style/AppTheme">
  <activity android:name=".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>
  <activity android:name=".CountryEdit" android:label="@string/app_name" />

  <provider android:name=".MyContentProvider" android:exported="true"
   android:readPermission="true" android:writePermission="true"
   android:authorities="com.as400samplecode.contentprovider" />
 </application>

</manifest>

References