Reading
and updating Contacts
Using the Contacts API
Starting from Android 2.0 (API Level 5), the Android platform
provides an improved Contacts API for managing and integrating
contacts from multiple accounts and from other data sources. To
handle overlapping data from multiple sources, the contacts content
provider aggregates similar contacts and presents them to users as a
single entity. This article describes how to use the new API to
manage contacts.
The new Contacts API is defined in the
If you'd like to look at an applied example of how to use the new Contacts API, including how to support both the new and older API in a single app, please see the Business Card sample application.
The system automatically aggregates contacts by default. However, if needed, your application can control how the system handles aggregation or it can disable aggregation altogether, as described in the sections below.
Two raw contacts are considered to be a match if at least one of these conditions is met:
Automatic aggregation is not permanent; any change of a constituent raw contact may create a new aggregate or break up an existing one.
Aggregation modes
You can set an aggregation mode for each raw contact individually. To do so, add a mode constant as the value of the
To keep two raw contacts unconditionally together or unconditionally apart, you can add a row to the
The lookup key helps resolve the contact in this case. The key is a string that concatenates the server-side identities of the raw contacts. Your application can use that string to find a contact, regardless whether the raw contact is aggregated with others or not.
If performance is a concern for your application, you might want to store both the lookup and the long ID of a contact and construct a lookup URI out of both IDs, as shown here:
Android itself uses lookup URIs whenever there is a need to reference a contact, such as with shortcuts or Quick Contact, and also during editing or even viewing a contact. The latter case is less obvious — why would a contact ID change while we are simply viewing the contact? It could change because there might be a sync going in the background, and the contact might get automatically aggregated with another while being viewed.
In summary: whenever you need to reference a contact, we recommend that you do so by its lookup URI.
Even if the application currently runs, you don't want to leave it like this for long. The main reason is that it will only have access to contacts from one account, namely the first Google account on the device. If the user opens other accounts in addition to or instead of a Google account, your application will not be able to access those contacts.
Go through the existing application and factor out all access to
Create a new abstract class ContactAccessor, make sure the abstract class has all method signatures from ContactAccessorOldApi. Make ContactAccessorOldApi extend ContactAccessor:
The new Contacts API is defined in the
android.provider.ContactsContract
and related classes. The older API is still supported, although
deprecated. If you have an existing application that uses the older
API, see Considerations
for legacy apps, below, for ideas on how to support the Contacts
API in your app.If you'd like to look at an applied example of how to use the new Contacts API, including how to support both the new and older API in a single app, please see the Business Card sample application.
Data structure of Contacts
In the new Contacts API, data is laid out in three primary tables: contacts, raw contacts, and data, a structure that is slightly different from that used in the older API. The new structure allows the system to more easily store and manage information for a specific contact from multiple contacts sources.Data
is a generic table that stores all of the data points associated with a raw contact. Each row stores data of a specific kind — for example name, photo, email addresses, phone numbers, and group memberships. Each row is tagged with a MIME type to identify what type of data it can contain, across the entire column. Columns are generic and the type of data they contain is determined by the kind of data stored in each row. For example, if a row's data kind isPhone.CONTENT_ITEM_TYPE
, then the first column stores the phone number, but if the data kind isEmail.CONTENT_ITEM_TYPE
, then the column stores the email address.
TheContactsContract.CommonDataKinds
class provides subclasses corresponding to common MIME types for contacts data. If needed, your application or other contacts sources can define additional MIME types for data rows. For more information about the Data table and examples of how to use it, seeandroid.provider.ContactsContract.Data
.
- A row in the
RawContacts
table represents the set ofData
and other information describing a person and associated with a single contacts source. For example, a row might define the data associated with a person's Google or Exchange account or Facebook friend. For more information, seeContactsContract.RawContacts
.
- A row in the
Contacts
table represents an aggregate of one or moreRawContacts
describing the same person (or entity).
As mentioned above, the Contacts content provider automatically aggregates Raw Contacts into a single Contact entry, where possible, since common data fields (such as name or email address) are likely to be stored in each raw contact. Since the aggregation logic maintains the entries in the Contact rows, the entries can be read but should not be modified. See the section Aggregation of contacts, below, for more details, including and information on how to control aggregation.
Example: Inserting a Phone Number
To insert a phone number using the new APIs you'll need the ID of the Raw Contact to attach the phone number to, then you'll need to create a Data row:import android.provider.ContactsContract.CommonDataKinds.Phone; ... ContentValues values = new ContentValues(); values.put(Phone.RAW_CONTACT_ID, rawContactId); values.put(Phone.NUMBER, phoneNumber); values.put(Phone.TYPE, Phone.TYPE_MOBILE); Uri uri = getContentResolver().insert(Phone.CONTENT_URI, values);
Aggregation of contacts
When users sync contacts from multiple sources, several contacts might refer to the same person or entity, but with slightly different (or overlapping) data. For example, "Bob Parr" might be a user's co-worker and also his personal friend, so the user might have his contact information stored in both a corporate email account and a personal account. To provide a simplified view for the user, the system locates such overlapping contacts and combines them into a single, aggregate contact.The system automatically aggregates contacts by default. However, if needed, your application can control how the system handles aggregation or it can disable aggregation altogether, as described in the sections below.
Automatic aggregation
When a raw contact is added or modified, the system looks for matching (overlapping) raw contacts with which to aggregate it. It may not find any matching raw contacts, in which case it will create an aggregate contact that contains just the original raw contact. If it finds a single match, it creates a new contact that contains the two raw contacts. And it may even find multiple similar raw contacts, in which case it chooses the closest match.Two raw contacts are considered to be a match if at least one of these conditions is met:
- They have matching names.
- Their names consist of the same words but in different order (for example, "Bob Parr" and "Parr, Bob")
- One of them has a common short name for the other (for example, "Bob Parr" and "Robert Parr")
- One of them has just a first or last name and it matches the other raw contact. This rule is less reliable, so it only applies if the two raw contacts are also sharing some other data like a phone number, an email address or a nickname (for example, Helen ["elastigirl"] = Helen Parr ["elastigirl"])
- At least one of the two raw contacts is missing the name
altogether and they are sharing a phone number, an email address or
a nickname (for example, Bob Parr [incredible@android.com] =
incredible@android.com).
Automatic aggregation is not permanent; any change of a constituent raw contact may create a new aggregate or break up an existing one.
Explicit aggregation
In some cases, the system's automatic aggregation may not meet the requirements of your application or sync adapter. There are two sets of APIs you can use to control aggregation explicitly: aggregation modes allow you to control automatic aggregation behaviors and aggregation exceptions allow you to override automated aggregation entirely.Aggregation modes
You can set an aggregation mode for each raw contact individually. To do so, add a mode constant as the value of the
AGGREGATION_MODE column
in the
RawContact
row. The mode constants
available include:
AGGREGATION_MODE_DEFAULT
— normal mode, automatic aggregation is allowed.AGGREGATION_MODE_DISABLED
— automatic aggregation is not allowed. The raw contact will not be aggregated.AGGREGATION_MODE_SUSPENDED
— automatic aggregation is deactivated. If the raw contact is already a part of an aggregated contact when aggregation mode changes to suspended, it will remain in the aggregate, even if it changes in such a way that it no longer matches the other raw contacts in the aggregate.
To keep two raw contacts unconditionally together or unconditionally apart, you can add a row to the
ContactsContract.AggregationExceptions
table. Exceptions defined in the table override all automatic
aggregation rules.
Loookup URI
The new Contacts API introduces the notion of a lookup key for a contact. If your application needs to maintain references to contacts, you should use lookup keys instead of the traditional row ids. You can acquire a lookup key from the contact itself, it is a column on theContactsContract.Contacts
table. Once you have a lookup key, you can construct a URI in this
way:Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey)and use it like you would use a traditional content URI, for example:
Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, ...); try { c.moveToFirst(); String displayName = c.getString(0); } finally { c.close(); }The reason for this complication is that regular contact row IDs are inherently volatile. Let's say your app stored a long ID of a contact. Then the user goes and manually joins the contact with some other contact. Now there is a single contact where there used to be two, and the stored long contact ID points nowhere.
The lookup key helps resolve the contact in this case. The key is a string that concatenates the server-side identities of the raw contacts. Your application can use that string to find a contact, regardless whether the raw contact is aggregated with others or not.
If performance is a concern for your application, you might want to store both the lookup and the long ID of a contact and construct a lookup URI out of both IDs, as shown here:
Uri lookupUri = getLookupUri(contactId, lookupKey)When both IDs are present in the URI, the system will try to use the long ID first. That is a very quick query. If the contact is not found, or if the one that is found has the wrong lookup key, the content provider will parse the lookup key and track down the constituent raw contacts. If your app bulk-processes contacts, you should maintain both IDs. If your app works with a single contact per user action, you probably don't need to bother with storing the long ID.
Android itself uses lookup URIs whenever there is a need to reference a contact, such as with shortcuts or Quick Contact, and also during editing or even viewing a contact. The latter case is less obvious — why would a contact ID change while we are simply viewing the contact? It could change because there might be a sync going in the background, and the contact might get automatically aggregated with another while being viewed.
In summary: whenever you need to reference a contact, we recommend that you do so by its lookup URI.
Considerations for legacy applications
If you have an existing application that uses the older Contacts API, you should consider upgrading it to use the new API. You have four options:- Leave it as-is and rely on the Contacts compatibility mode.
- Upgrade the app and discontinue support of pre-Android 2.0 platforms.
- Build a new version of the app for the new API, while keeping the old version available.
- Make the app use the right set of APIs depending on the
platform where it is deployed.
Using compatibility mode
Compatibility mode is the easiest option because you just leave the application as is, and it should run on Android 2.0 as long as it only uses public APIs. A couple examples of the use of non-public API include the use of explicit table names in nested queries and the use of columns that were not declared as public constants in theContacts
class.
Even if the application currently runs, you don't want to leave it like this for long. The main reason is that it will only have access to contacts from one account, namely the first Google account on the device. If the user opens other accounts in addition to or instead of a Google account, your application will not be able to access those contacts.
Upgrading to the new API and dropping support for older platforms
If your application will no longer target platforms older than Android 2.0, you can upgrade to the new API in this way:- Replace all usages of
Contacts
with calls to new API. After you are done, you should not see any deprecation warnings during application build. The new application will be able to take full advantage of multiple accounts and other new features of Android 2.0.
- In the application's manifest, update (or add) the
android:minSdkVersion
attribute to the<uses-sdk>
element. To use the new Contacts API, you should set the value of the attribute to "5" (or higher, as appropriate). For more information aboutandroid:minSdkVersion
, see the documentation for the<uses-sdk>
element. For more information about the value of theminSdkVersion
, see API Levels.
Maintaining two applications
You may decide to have two different applications: one for pre-Android 2.0 platforms and one for Android 2.0 and beyond. If so, here's what you'll need to do:- Clone your existing app.
- Change the old application:
- At launch time, check the version of the SDK. The version of the SDK is available as
android.os.Build.VERSION.SDK
. - If the SDK version is greater or equal to 5 (Android 2.0), show a dialog suggesting to the user that it's time to go to Google Play and find a new version of the app. You can even provide a link to the new app on Google Play (see Using Intents to Launch Google Play).
- Change the new application:
- Replace all usages of the older Contacts API with calls to new API. The new application will be able to take full advantage of multiple accounts and other new features of Android 2.0.
- Modify that application's AndroidManifest.xml file:
- Give the application a new name and a new package name. Currently Google Play does not allow you to have two applications with the same name/package.
- Update (or add) the
android:minSdkVersion
attribute to the<uses-sdk>
element. To use the new Contacts API, you should set the value of the attribute to "5" (or higher, as appropriate).
- Publish both apps on Google Play, the old app one as an
upgrade and the other as new. Make sure to explain the difference
between the apps in their descriptions.
- The new application will not be able to read the old application's data. Application data can only be accessed by code living in the same package. So databases, shared preferences, and so on, will need to be populated from scratch.
- The upgrade process is too clunky for the user. Some users
may choose to either stay with the crippled old version or
uninstall altogether.
Supporting the old and new APIs in the same application
This is a bit tricky, but the result is worth the effort. You can build a single package that will work on any platform:Go through the existing application and factor out all access to
Contacts
into one class, such as ContactAccessorOldApi. For example, if you
have code like this:
protected void pickContact() { startActivityForResult(new Intent(Intent.ACTION_PICK, People.CONTENT_URI), 0); }it will change to:
private final ContactAccessorOldApi mContactAccessor = new ContactAccessorOldApi(); void pickContact() { startActivityForResult(mContactAccessor.getContactPickerIntent(), 0); }The corresponding method on ContactAccessorOldApi will look like this:
public Intent getContactPickerIntent() { return new Intent(Intent.ACTION_PICK, People.CONTENT_URI); }Once you are done, you should see deprecation warnings coming only from ContactAccessorOldApi.
Create a new abstract class ContactAccessor, make sure the abstract class has all method signatures from ContactAccessorOldApi. Make ContactAccessorOldApi extend ContactAccessor:
public abstract class ContactAccessor { public abstract Intent getContactPickerIntent(); ... }Create a new subclass of ContactAccessor, ContactAccessorNewApi and implement all methods using the new API:
public class ContactAccessorNewApi extends ContactAccessor { @Override public Intent getContactPickerIntent() { return new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); } ... }At this point, you have two implementations of the same API, one using the old API and another using the new API. Let's plug them in. Add this code to the ContactAccessor class:
private static ContactAccessor sInstance; public static ContactAccessor getInstance() { if (sInstance == null) { String className; int sdkVersion = Integer.parseInt(Build.VERSION.SDK); if (sdkVersion < Build.VERSION_CODES.ECLAIR) { className = "ContactAccessorOldApi"; } else { className = "ContactAccessorNewApi"; } try { Class<? extends ContactAccessor> clazz = Class.forName(ContactAccessor.class.getPackage() + "." + className) .asSubclass(ContactAccessor.class); sInstance = clazz.newInstance(); } catch (Exception e) { throw new IllegalStateException(e); } } return sInstance; }Now replace references to ContactsAccessorOldApi with references to ContactsAccessor:
private final ContactAccessor mContactAccessor = ContactAccessor.getInstance();
public final class
java.lang.Object |
|
↳ |
android.provider.ContactsContract |
Class Overview
The contract between the contacts provider and applications. Contains definitions for the supported URIs and columns. These APIs supersedeContactsContract.Contacts
.
Overview
ContactsContract defines an extensible database of contact-related information. Contact information is stored in a three-tier data model:- A row in the
ContactsContract.Data
table can store any kind of personal data, such as a phone number or email addresses. The set of data kinds that can be stored in this table is open-ended. There is a predefined set of common kinds, but any application can add its own data kinds. - A row in the
ContactsContract.RawContacts
table represents a set of data describing a person and associated with a single account (for example, one of the user's Gmail accounts). - A row in the
ContactsContract.Contacts
table represents an aggregate of one or more RawContacts presumably describing the same person. When data in or associated with the RawContacts table is changed, the affected aggregate contacts are updated as necessary.
Constants
public static final String AUTHORITY
Since: API Level 5The authority for the contacts provider
Constant Value: "com.android.contacts"
public static final String CALLER_IS_SYNCADAPTER
Since: API Level 5An optional URI parameter for insert, update, or delete queries that allows the caller to specify that it is a sync adapter. The default value is false. If true
DIRTY
is not automatically set and the "syncToNetwork" parameter
is set to false when calling notifyChange(android.net.Uri,
android.database.ContentObserver, boolean)
. This prevents
an unnecessary extra synchronization, see the discussion of the
delete operation in ContactsContract.RawContacts
.
Constant Value: "caller_is_syncadapter"
public static final String DIRECTORY_PARAM_KEY
Since: API Level 11Query parameter that should be used by the client to access a specific
ContactsContract.Directory
.
The parameter value should be the _ID of the corresponding directory,
e.g.
content://com.android.contacts/data/emails/filter/acme?directory=3
Constant Value: "directory"
public static final String LIMIT_PARAM_KEY
Since: API Level 11A query parameter that limits the number of results returned. The parameter value should be an integer.
Constant Value: "limit"
public static final String PRIMARY_ACCOUNT_NAME
Since: API Level 14A query parameter specifing a primary account. This parameter should be used with
PRIMARY_ACCOUNT_TYPE
.
The contacts provider handling a query may rely on this information
to optimize its query results. For example, in an email composition
screen, its implementation can specify an account when obtaining
possible recipients, letting the provider know which account is
selected during the composition. The provider may use the "primary
account" information to optimize the search result.
Constant Value: "name_for_primary_account"
public static final String PRIMARY_ACCOUNT_TYPE
Since: API Level 14A query parameter specifing a primary account. This parameter should be used with
PRIMARY_ACCOUNT_NAME
.
See the doc in PRIMARY_ACCOUNT_NAME
.
Constant Value: "type_for_primary_account"
Fields
public static final Uri AUTHORITY_URI
Since: API Level 5A content:// style uri to the authority for the contacts provider
Public Constructors
public ContactsContract ()
Since: API Level 5Public Methods
public static boolean isProfileId (long id)
Since: API Level 14This method can be used to identify whether the given ID is associated with profile data. It does not necessarily indicate that the ID is tied to valid data, merely that accessing data using this ID will result in profile access checks and will only return data from the profile.
Parameters
id
|
The ID to check. |
---|
Returns
- Whether the ID is associated with profile data.
Using
SQLite Database
Android
provides several ways to store user and app data. SQLite is one way
of storing user data. SQLite is a very light weight database which
comes with Android OS. In this tutorial I’ll be discussing how to
write classes to handle all SQLite operations.
In
this tutorial I am taking an example of storing user contacts in
SQLite database. I am using a table called Contacts to store user
contacts. This table contains three columns id (INT),
name (TEXT), phone_number(TEXT).Following is the structure of contacts table.
Writing Contact Class
Before you go further you need to write your Contact class with all getter and setter methods to maintain single contact as an object.
Contact.java
package
com.androidhive.androidsqlite;
public class
Contact { //private
variables int
_id; String
_name; String
_phone_number; //
Empty constructor public
Contact(){ } //
constructor public
Contact(int id,
String name, String _phone_number){ this._id
= id; this._name
= name; this._phone_number
= _phone_number; } //
constructor public
Contact(String name, String _phone_number){ this._name
= name; this._phone_number
= _phone_number; } //
getting ID public
int getID(){ return
this._id; } //
setting id public
void setID(int
id){ this._id
= id; } //
getting name public
String getName(){ return
this._name; } //
setting name public
void setName(String
name){ this._name
= name; } //
getting phone number public
String getPhoneNumber(){ return
this._phone_number; } //
setting phone number public
void setPhoneNumber(String
phone_number){ this._phone_number
= phone_number; } } |
We need to write our own class to handle all database CRUD(Create, Read, Update and Delete) operations.
1. Create a new project by going to File ⇒ New Android Project.
2. Once the project is created, create a new class in your project src directory and name it as DatabaseHandler.java ( Right Click on src/package ⇒ New ⇒ Class)
3. Now extend your DatabaseHandler.java class from SQLiteOpenHelper.
public class
DatabaseHandler extends
SQLiteOpenHelper { |
onCreate() – These is where we need to write create table statements. This is called when database is created.
onUpgrade() – This method is called when database is upgraded like modifying the table structure, adding constraints to database etc.,
public class
DatabaseHandler extends
SQLiteOpenHelper { //
All Static variables //
Database Version private
static final
int DATABASE_VERSION
= 1; //
Database Name private
static final
String DATABASE_NAME = "contactsManager"; //
Contacts table name private
static final
String TABLE_CONTACTS = "contacts"; //
Contacts Table Columns names private
static final
String KEY_ID = "id"; private
static final
String KEY_NAME = "name"; private
static final
String KEY_PH_NO = "phone_number"; public
DatabaseHandler(Context context) { super(context,
DATABASE_NAME, null, DATABASE_VERSION); } //
Creating Tables @Override public
void onCreate(SQLiteDatabase
db) { String
CREATE_CONTACTS_TABLE = "CREATE TABLE " +
TABLE_CONTACTS + "(" +
KEY_ID + " INTEGER PRIMARY KEY," +
KEY_NAME + " TEXT," +
KEY_PH_NO + " TEXT" + ")"; db.execSQL(CREATE_CONTACTS_TABLE); } //
Upgrading database @Override public
void onUpgrade(SQLiteDatabase
db, int oldVersion, int
newVersion) { //
Drop older table if existed db.execSQL("DROP
TABLE IF EXISTS " +
TABLE_CONTACTS); //
Create tables again onCreate(db); } |
Now we need to write methods for handling all database read and write operations. Here we are implementing following methods for our contacts table.
// Adding new contact public void
addContact(Contact contact) {} // Getting single contact public Contact
getContact(int id) {} // Getting All Contacts public List<Contact>
getAllContacts() {} // Getting contacts Count public int
getContactsCount() {} // Updating single contact public int
updateContact(Contact contact) {} // Deleting single contact public void
deleteContact(Contact contact) {} |
The addContact() method accepts Contact object as parameter. We need to build ContentValues parameters using Contact object. Once we inserted data in database we need to close the database connection.
addContact()
//
Adding new contact public void
addContact(Contact contact) { SQLiteDatabase
db = this.getWritableDatabase(); ContentValues
values = new ContentValues(); values.put(KEY_NAME,
contact.getName()); // Contact Name values.put(KEY_PH_NO,
contact.getPhoneNumber()); // Contact Phone Number //
Inserting Row db.insert(TABLE_CONTACTS,
null, values); db.close();
// Closing database connection } |
The following method getContact() will read single contact row. It accepts id as parameter and will return the matched row from the database.
getContact()
//
Getting single contact public Contact
getContact(int id) { SQLiteDatabase
db = this.getReadableDatabase(); Cursor
cursor = db.query(TABLE_CONTACTS, new String[]
{ KEY_ID, KEY_NAME,
KEY_PH_NO }, KEY_ID + "=?", new
String[] { String.valueOf(id) }, null,
null, null, null); if
(cursor != null) cursor.moveToFirst(); Contact
contact = new
Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1),
cursor.getString(2)); //
return contact return
contact; } |
getAllContacts()
//
Getting All Contacts public
List<Contact> getAllContacts() { List<Contact>
contactList = new ArrayList<Contact>(); //
Select All Query String
selectQuery = "SELECT * FROM " +
TABLE_CONTACTS; SQLiteDatabase
db = this.getWritableDatabase(); Cursor
cursor = db.rawQuery(selectQuery, null); //
looping through all rows and adding to list if
(cursor.moveToFirst()) { do
{ Contact
contact = new Contact(); contact.setID(Integer.parseInt(cursor.getString(0))); contact.setName(cursor.getString(1)); contact.setPhoneNumber(cursor.getString(2)); //
Adding contact to list contactList.add(contact); }
while (cursor.moveToNext()); } //
return contact list return
contactList; } |
getContactsCount()
// Getting contacts Count public
int getContactsCount()
{ String
countQuery = "SELECT * FROM " +
TABLE_CONTACTS; SQLiteDatabase
db = this.getReadableDatabase(); Cursor
cursor = db.rawQuery(countQuery, null); cursor.close(); //
return count return
cursor.getCount(); } |
updateContact() will update single contact in database. This method accepts Contact class object as parameter.
updateContact()
//
Updating single contact public int
updateContact(Contact contact) { SQLiteDatabase
db = this.getWritableDatabase(); ContentValues
values = new ContentValues(); values.put(KEY_NAME,
contact.getName()); values.put(KEY_PH_NO,
contact.getPhoneNumber()); //
updating row return
db.update(TABLE_CONTACTS, values, KEY_ID +
" = ?", new
String[] { String.valueOf(contact.getID())
}); } |
deleteContact() will delete single contact from database.
deleteContact()
//
Deleting single contact public void
deleteContact(Contact contact) { SQLiteDatabase
db = this.getWritableDatabase(); db.delete(TABLE_CONTACTS,
KEY_ID + " = ?", new
String[] { String.valueOf(contact.getID())
}); db.close(); } |
DatabaseHandler.java
package
com.androidhive.androidsqlite; import java.util.ArrayList; import java.util.List; import
android.content.ContentValues; import android.content.Context; import android.database.Cursor; import
android.database.sqlite.SQLiteDatabase; import
android.database.sqlite.SQLiteOpenHelper; public class
DatabaseHandler extends
SQLiteOpenHelper { //
All Static variables //
Database Version private
static final
int DATABASE_VERSION
= 1; //
Database Name private
static final
String DATABASE_NAME = "contactsManager"; //
Contacts table name private
static final
String TABLE_CONTACTS = "contacts"; //
Contacts Table Columns names private
static final
String KEY_ID = "id"; private
static final
String KEY_NAME = "name"; private
static final
String KEY_PH_NO = "phone_number"; public
DatabaseHandler(Context context) { super(context,
DATABASE_NAME, null, DATABASE_VERSION); } //
Creating Tables @Override public
void onCreate(SQLiteDatabase
db) { String
CREATE_CONTACTS_TABLE = "CREATE TABLE " +
TABLE_CONTACTS + "(" +
KEY_ID + " INTEGER PRIMARY KEY," +
KEY_NAME + " TEXT," +
KEY_PH_NO + " TEXT" + ")"; db.execSQL(CREATE_CONTACTS_TABLE); } //
Upgrading database @Override public
void onUpgrade(SQLiteDatabase
db, int oldVersion, int
newVersion) { //
Drop older table if existed db.execSQL("DROP
TABLE IF EXISTS " +
TABLE_CONTACTS); //
Create tables again onCreate(db); } /** *
All CRUD(Create, Read, Update, Delete) Operations */ //
Adding new contact void
addContact(Contact contact) { SQLiteDatabase
db = this.getWritableDatabase(); ContentValues
values = new ContentValues(); values.put(KEY_NAME,
contact.getName()); // Contact Name values.put(KEY_PH_NO,
contact.getPhoneNumber()); // Contact Phone //
Inserting Row db.insert(TABLE_CONTACTS,
null, values); db.close();
// Closing database connection } //
Getting single contact Contact
getContact(int id) { SQLiteDatabase
db = this.getReadableDatabase(); Cursor
cursor = db.query(TABLE_CONTACTS, new String[]
{ KEY_ID, KEY_NAME,
KEY_PH_NO }, KEY_ID + "=?", new
String[] { String.valueOf(id) }, null,
null, null, null); if
(cursor != null) cursor.moveToFirst(); Contact
contact = new
Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1),
cursor.getString(2)); //
return contact return
contact; } //
Getting All Contacts public
List<Contact> getAllContacts() { List<Contact>
contactList = new ArrayList<Contact>(); //
Select All Query String
selectQuery = "SELECT * FROM " +
TABLE_CONTACTS; SQLiteDatabase
db = this.getWritableDatabase(); Cursor
cursor = db.rawQuery(selectQuery, null); //
looping through all rows and adding to list if
(cursor.moveToFirst()) { do
{ Contact
contact = new Contact(); contact.setID(Integer.parseInt(cursor.getString(0))); contact.setName(cursor.getString(1)); contact.setPhoneNumber(cursor.getString(2)); //
Adding contact to list contactList.add(contact); }
while (cursor.moveToNext()); } //
return contact list return
contactList; } //
Updating single contact public
int updateContact(Contact
contact) { SQLiteDatabase
db = this.getWritableDatabase(); ContentValues
values = new ContentValues(); values.put(KEY_NAME,
contact.getName()); values.put(KEY_PH_NO,
contact.getPhoneNumber()); //
updating row return
db.update(TABLE_CONTACTS, values, KEY_ID +
" = ?", new
String[] { String.valueOf(contact.getID())
}); } //
Deleting single contact public
void deleteContact(Contact
contact) { SQLiteDatabase
db = this.getWritableDatabase(); db.delete(TABLE_CONTACTS,
KEY_ID + " = ?", new
String[] { String.valueOf(contact.getID())
}); db.close(); } //
Getting contacts Count public
int getContactsCount()
{ String
countQuery = "SELECT * FROM " +
TABLE_CONTACTS; SQLiteDatabase
db = this.getReadableDatabase(); Cursor
cursor = db.rawQuery(countQuery, null); cursor.close(); //
return count return
cursor.getCount(); } } |
AndroidSQLiteTutorialActivity
package
com.androidhive.androidsqlite; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class
AndroidSQLiteTutorialActivity extends
Activity { @Override public
void onCreate(Bundle
savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); DatabaseHandler
db = new DatabaseHandler(this); /** *
CRUD Operations *
*/ //
Inserting Contacts Log.d("Insert:
", "Inserting .."); db.addContact(new
Contact("Ravi", "9100000000")); db.addContact(new
Contact("Srinivas",
"9199999999")); db.addContact(new
Contact("Tommy", "9522222222")); db.addContact(new
Contact("Karthik",
"9533333333")); //
Reading all contacts Log.d("Reading:
", "Reading all contacts.."); List<Contact>
contacts = db.getAllContacts();
for
(Contact cn : contacts) { String
log = "Id: "+cn.getID()+" ,Name: " +
cn.getName() + " ,Phone: " +
cn.getPhoneNumber(); //
Writing Contacts to log Log.d("Name:
", log); } } } |
I am writing output to Log report. You can see your log report by going to Windows ⇒ Show View ⇒ Other.. ⇒ Android ⇒ Log Cat.
No comments:
Post a Comment