个人感觉活动文件夹没有什么作用,跟主屏幕部件差不了多少,而且在avd (target:Android4.0.3)中没有找到活动文件夹,我在此avd的主页空白处进行长单击,看到的不是上下文菜单,而是选择桌面墙纸。今天发现在它妈的avd(target:Android2.1)还是存在可以找到活动文件夹的。这里就简单总结一下活动文件夹,以备忘吧。

Android中的活动文件夹对Content Provider的作用就相当于RSS阅读器对发布网站的作用。

项目结构:

活动文件夹 live folder_android

项目源码:

 AndroidManifest.xml:

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

    <uses-sdk android:minSdkVersion="7" />
     <uses-permission  android:name="android.permission.READ_CONTACTS"/>
    <application
        android:icon="@drawable/ic_launcher"
        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/ic_launcher"> <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.livefolder.contacts" android:multiprocess="true" android:name=".MyContactsProvider"></provider> </application> </manifest>

AllContactsLiveFolderCreatorActivity.java:担当活动文件夹的生成程序或创造程序。

package com.wl;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.LiveFolders;

public class AllContactsLiveFolderCreatorActivity extends Activity{
    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.CONTACT_URI, "Contact LF", R.drawable.ic_launcher));
        }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;
    }
    
}

MyContactsProvider.java:一个Content Provider

package com.wl;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.LiveFolders;
import android.util.Log;

public class MyContactsProvider extends ContentProvider{
    public static final String AUTHORITY = "com.ai.livefolder.contacts";
    public static final Uri CONTACT_URI = Uri.parse("content://" + AUTHORITY + "/contacts");
    
    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 int bulkInsert(Uri arg0, ContentValues[] values){
        return 0;
    }
    
    private static final String[] CURSOR_COLUMNS = new String[]{
        BaseColumns._ID,
        LiveFolders.NAME,
        LiveFolders.DESCRIPTION,
        LiveFolders.INTENT,
        LiveFolders.ICON_PACKAGE,
        LiveFolders.ICON_RESOURCE
    };
    private static final String[] CURSOR_ERROR_COLUMNS = new String[]{
        BaseColumns._ID,
        LiveFolders.NAME,
        LiveFolders.DESCRIPTION
    };
    private static final Object[] ERROR_MESSAGE_ROW = new Object[]{
        -1,
        "No contacts found",
        "Check your contacts database"
    };
    private static MatrixCursor sErrorCursor = new MatrixCursor(CURSOR_ERROR_COLUMNS);
    static{
        sErrorCursor.addRow(ERROR_MESSAGE_ROW);
    }
    private static final String[] CONTACTS_COLUMN_NAMES = new String[]{
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.Contacts.TIMES_CONTACTED,
        ContactsContract.Contacts.STARRED
    };
    
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
        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(ContactsContract.Contacts.CONTENT_URI, CONTACTS_COLUMN_NAMES, null, null, ContactsContract.Contacts.DISPLAY_NAME);
            while(allContacts.moveToNext()){
                String timesContacted = "Times contacted: " + allContacts.getInt(2);
                Object[] rowObject = new Object[]{
                        allContacts.getLong(0),
                        allContacts.getString(1),
                        timesContacted,
                        Uri.parse("content://contacts/people/" + allContacts.getLong(0)),
                        cp.getContext().getPackageName(),
                        R.drawable.ic_launcher        
                };
                mc.addRow(rowObject);
            }
            return mc;
        }
        finally{
            allContacts.close();
        }
    }
    
    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getType(Uri arg0) {
        // TODO Auto-generated method stub
        return ContactsContract.Contacts.CONTENT_TYPE;
    }

    @Override
    public Uri insert(Uri arg0, ContentValues arg1) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        return true;
    }


    @Override
    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
        // TODO Auto-generated method stub
        return 0;
    }
    
}

MyCursor.java:对MatrixCursor的包装

package com.wl;

import android.content.ContentProvider;
import android.database.MatrixCursor;

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();
                
    }
}

BetterCursorWrapper.java

package com.wl;

import android.content.ContentResolver;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.CrossProcessCursor;
import android.database.CursorWindow;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;

public class BetterCursorWrapper implements CrossProcessCursor{
    protected CrossProcessCursor internalCursor;
    public BetterCursorWrapper(CrossProcessCursor inCursor){
        this.setInternalCursor(inCursor);
    }
    
    public void setInternalCursor(CrossProcessCursor inCursor){
        this.internalCursor = inCursor;
    }
    public void fillWindow(int arg0, CursorWindow arg1){
        internalCursor.fillWindow(arg0, arg1);
    }

    public void close() {
        internalCursor.close();
    }

    public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
        internalCursor.copyStringToBuffer(columnIndex, buffer);
    }

    public void deactivate() {
        internalCursor.deactivate();
    }

    public byte[] getBlob(int columnIndex) {
        return internalCursor.getBlob(columnIndex);
    }

    public int getColumnCount() {
        return internalCursor.getColumnCount();
    }

    public int getColumnIndex(String columnName) {
        return internalCursor.getColumnIndex(columnName);
    }

    public int getColumnIndexOrThrow(String columnName)
            throws IllegalArgumentException {
        return internalCursor.getColumnIndexOrThrow(columnName);
    }

    public String getColumnName(int columnIndex) {
        return internalCursor.getColumnName(columnIndex);
    }

    public String[] getColumnNames() {
        return internalCursor.getColumnNames();
    }

    public int getCount() {
        return internalCursor.getCount();
    }

    public double getDouble(int columnIndex) {
        return internalCursor.getDouble(columnIndex);
    }

    public Bundle getExtras() {
        return internalCursor.getExtras();
    }

    public float getFloat(int columnIndex) {
        return internalCursor.getFloat(columnIndex);
    }

    public int getInt(int columnIndex) {
        return internalCursor.getInt(columnIndex);
    }

    public long getLong(int columnIndex) {
        return internalCursor.getLong(columnIndex);
    }

    public int getPosition() {
        return internalCursor.getPosition();
    }

    public short getShort(int columnIndex) {
        return internalCursor.getShort(columnIndex);
    }

    public String getString(int columnIndex) {
        return internalCursor.getString(columnIndex);
    }

    public boolean getWantsAllOnMoveCalls() {
        return internalCursor.getWantsAllOnMoveCalls();
    }

    public CursorWindow getWindow() {
        return internalCursor.getWindow();
    }

    public boolean isAfterLast() {
        return internalCursor.isAfterLast();
    }

    public boolean isBeforeFirst() {
        return internalCursor.isBeforeFirst();
    }

    public boolean isClosed() {
        return internalCursor.isClosed();
    }

    public boolean isFirst() {
        return internalCursor.isFirst();
    }

    public boolean isLast() {
        return internalCursor.isLast();
    }

    public boolean isNull(int columnIndex) {
        return internalCursor.isNull(columnIndex);
    }

    public boolean move(int offset) {
        return internalCursor.move(offset);
    }

    public boolean moveToFirst() {
        return internalCursor.moveToFirst();
    }

    public boolean moveToLast() {
        return internalCursor.moveToLast();
    }

    public boolean moveToNext() {
        return internalCursor.moveToNext();
    }

    public boolean moveToPosition(int position) {
        return internalCursor.moveToPosition(position);
    }

    public boolean moveToPrevious() {
        return internalCursor.moveToPrevious();
    }

    public boolean onMove(int oldPosition, int newPosition) {
        return internalCursor.onMove(oldPosition, newPosition);
    }

    public void registerContentObserver(ContentObserver observer) {
        internalCursor.registerContentObserver(observer);
    }

    public void registerDataSetObserver(DataSetObserver observer) {
        internalCursor.registerDataSetObserver(observer);
    }

    public boolean requery() {
        return internalCursor.requery();
    }

    public Bundle respond(Bundle extras) {
        return internalCursor.respond(extras);
    }

    public void setNotificationUri(ContentResolver cr, Uri uri) {
        internalCursor.setNotificationUri(cr, uri);
    }

    public void unregisterContentObserver(ContentObserver observer) {
        internalCursor.unregisterContentObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        internalCursor.unregisterDataSetObserver(observer);
    }
}

SimpleActivity.java:

package com.wl;

import android.app.Activity;
import android.os.Bundle;

public class SimpleActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

main.xml:

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

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

</LinearLayout>