Ch12 Listings
satya - Saturday, February 20, 2010 10:55:31 PM
Listing 12-1. AndroidManifest.xml File for a Live-Folder Definition
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ai.android.livefolders"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".SimpleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- LIVE FOLDERS -->
<activity
android:name=".AllContactsLiveFolderCreatorActivity"
android:label="New live folder "
android:icon="@drawable/icon">
<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider android:authorities="com.ai.livefolders.contacts"
android:multiprocess="true"
android:name=".MyContactsProvider" />
</application>
<uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
</manifest>
satya - Saturday, February 20, 2010 10:59:33 PM
Listing 12-2. AllContactsLiveFolderCreatorActivity Source Code
public class AllContactsLiveFolderCreatorActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
final String action = intent.getAction();
if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
setResult(RESULT_OK,
createLiveFolder(MyContactsProvider.CONTACTS_URI,
"Contacts LF",
R.drawable.icon)
);
}
else {
setResult(RESULT_CANCELED);
}
finish();
}
private Intent createLiveFolder(Uri uri, String name, int icon)
{
final Intent intent = new Intent();
intent.setData(uri);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
Intent.ShortcutIconResource.fromContext(this, icon));
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,
LiveFolders.DISPLAY_MODE_LIST);
return intent;
}
}
satya - Saturday, February 20, 2010 11:08:41 PM
Listing 12-3. MyContactsProvider Source Code
public class MyContactsProvider extends ContentProvider {
public static final String AUTHORITY = "com.ai.livefolders.contacts";
//Uri that goes as input to the live-folder creation
public static final Uri CONTACTS_URI = Uri.parse("content://" +
AUTHORITY + "/contacts" );
//To distinguish this URI
private static final int TYPE_MY_URI = 0;
private static final UriMatcher URI_MATCHER;
static{
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI(AUTHORITY, "contacts", TYPE_MY_URI);
}
@Override
public boolean onCreate() {
return true;
}
@Override
public int bulkInsert(Uri arg0, ContentValues[] values) {
return 0; //nothing to insert
}
//Set of columns needed by a live folder
//This is the live-folder contract
private static final String[] CURSOR_COLUMNS = new String[]
{
BaseColumns._ID,
LiveFolders.NAME,
LiveFolders.DESCRIPTION,
LiveFolders.INTENT,
LiveFolders.ICON_PACKAGE,
LiveFolders.ICON_RESOURCE
};
//In case there are no rows
//use this stand-in as an error message
//Notice it has the same set of columns of a live folder
private static final String[] CURSOR_ERROR_COLUMNS = new String[]
{
BaseColumns._ID,
LiveFolders.NAME,
LiveFolders.DESCRIPTION
};
//The error message row
private static final Object[] ERROR_MESSAGE_ROW =
new Object[]
{
-1, //id
"No contacts found", //name
"Check your contacts database" //description
};
//The error cursor to use
private static MatrixCursor sErrorCursor = new MatrixCursor(CURSOR_ERROR_COLUMNS);
static
{
sErrorCursor.addRow(ERROR_MESSAGE_ROW);
}
//Columns to be retrieved from the contacts database
private static final String[] CONTACTS_COLUMN_NAMES = new String[]
{
People._ID,
People.DISPLAY_NAME,
People.TIMES_CONTACTED,
People.STARRED
};
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder)
{
//Figure out the uri and return error if not matching
int type = URI_MATCHER.match(uri);
if(type == UriMatcher.NO_MATCH)
{
return sErrorCursor;
}
Log.i("ss", "query called");
try
{
MatrixCursor mc = loadNewData(this);
mc.setNotificationUri(getContext().getContentResolver(),
Uri.parse("content://contacts/people/"));
MyCursor wmc = new MyCursor(mc,this);
return wmc;
}
catch (Throwable e)
{
return sErrorCursor;
}
}
public static MatrixCursor loadNewData(ContentProvider cp)
{
MatrixCursor mc = new MatrixCursor(CURSOR_COLUMNS);
Cursor allContacts = null;
try
{
allContacts = cp.getContext().getContentResolver().query(
People.CONTENT_URI,
CONTACTS_COLUMN_NAMES,
null, //row filter
null,
People.DISPLAY_NAME); //order by
while(allContacts.moveToNext())
{
String timesContacted = "Times contacted: "+allContacts.getInt(2);
Object[] rowObject = new Object[]
{
allContacts.getLong(0), //id
allContacts.getString(1), //name
timesContacted,
//description
Uri.parse("content://contacts/people/"
+allContacts.getLong(0)), //intent uri
cp.getContext().getPackageName(), //package
R.drawable.icon //icon
};
mc.addRow(rowObject);
}
return mc;
}
finally
{
allContacts.close();
}
}
@Override
public String getType(Uri uri)
{
//indicates the MIME type for a given URI
//targeted for this wrapper provider
//This usually looks like
// "vnd.android.cursor.dir/vnd.google.note"
return People.CONTENT_TYPE;
}
public Uri insert(Uri uri, ContentValues initialValues) {
throw new UnsupportedOperationException(
"no insert as this is just a wrapper");
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException(
"no delete as this is just a wrapper");
}
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs)
{
throw new UnsupportedOperationException(
"no update as this is just a wrapper");
}
}
satya - Sunday, February 21, 2010 7:17:53 AM
Listing 12-4. Columns Needed to Fulfill the Live-Folder Contract
private static final String[] CURSOR_COLUMNS = new String[]
{
BaseColumns._ID,
LiveFolders.NAME,
LiveFolders.DESCRIPTION,
LiveFolders.INTENT,
LiveFolders.ICON_PACKAGE,
LiveFolders.ICON_RESOURCE
};
satya - Sunday, February 21, 2010 7:21:42 AM
Listing 12-5. Registering a URI with a Cursor
MatrixCursor mc = loadNewData(this);
mc.setNotificationUri(getContext().getContentResolver(),
Uri.parse("content://contacts/people/"));
satya - Sunday, February 21, 2010 7:26:16 AM
Listing 12-6. Wrapping a Cursor
MatrixCursor mc = loadNewData(this);
mc.setNotificationUri(getContext().getContentResolver(),
Uri.parse("content://contacts/people/"));
MyCursor wmc = new MyCursor(mc,this);
satya - Sunday, February 21, 2010 7:28:23 AM
Listing 12-7. MyCursor Source Code
public class MyCursor extends BetterCursorWrapper
{
private ContentProvider mcp = null;
public MyCursor(MatrixCursor mc, ContentProvider inCp)
{
super(mc);
mcp = inCp;
}
public boolean requery()
{
MatrixCursor mc = MyContactsProvider.loadNewData(mcp);
this.setInternalCursor(mc);
return super.requery();
}
}
satya - Sunday, February 21, 2010 7:31:02 AM
Listing 12-8. BetterCursorWrapper Source Code
public class BetterCursorWrapper implements CrossProcessCursor
{
//Holds the internal cursor to delegate methods to
protected CrossProcessCursor internalCursor;
//Constructor takes a crossprocesscursor as an input
public BetterCursorWrapper(CrossProcessCursor inCursor)
{
this.setInternalCursor(inCursor);
}
//You can reset in one of the derived class's methods
public void setInternalCursor(CrossProcessCursor inCursor)
{
internalCursor = inCursor;
}
//All delegated methods follow
public void fillWindow(int arg0, CursorWindow arg1) {
internalCursor.fillWindow(arg0, arg1);
}
// ..... other delegated methods
}
satya - Sunday, February 21, 2010 7:32:38 AM
Listing 12-9. SimpleActivity Source Code
public class SimpleActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
satya - Sunday, February 21, 2010 7:34:46 AM
Listing 12-10. Simple XML Layout File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Live Folder Example"
/>
</LinearLayout>