ContentProvider是不同应用程序之间进行数据交换的标准API,ContentProvider以某种Uri的形式对外提供数据,允许其他应用访问或修改数据;其他应用程序使用ContentResolver根据Uri去访问操作指定数据。
人人网Android客户端也是使用ContentProvider对需要保存于Android客户端的数据进行管理。
1. renren.db
SQLLiteOpenHelper是Android提供的一个管理数据库的工具类,可用于管理数据库的创建和版本更新。一般的用法是创建SQLiteOpenHelper的子类,并扩展它的onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)方法。
人人网Android客户端使用该方法创建及修改用户手机中的人人网数据库(renren.db)。
下面是RenRenProvider$DatabaseHelper的代码:
public class RenRenProvider$DatabaseHelper extends SQLiteOpenHelper {
public RenRenProvider$DatabaseHelper(Context context) {
super(context, \”renren.db\”, null, 71);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(\”CREATE TABLE pic (_id INTEGER PRIMARY KEY,url TEXT UNIQUE ON CONFLICT REPLACE,_data TEXT,size INTEGER);\”);
db.execSQL(\”CREATE TABLE account (_id INTEGER PRIMARY KEY,uid INTEGET,account TEXT UNIQUE ON CONFLICT REPLACE,pwd TEXT,proxy INTEGER,sessionkey TEXT,srt_key TEXT,ticket TEXT,name TEXT,headphoto BLOB,isdefault INTEGER,last_login INTEGER,friend_count INTEGER);\”);
db.execSQL(\”CREATE TABLE home (_id INTEGER PRIMARY KEY,item_id INTEGER UNIQUE ON CONFLICT REPLACE,data BLOB);\”);
db.execSQL(\”CREATE TABLE profile (_id INTEGER PRIMARY KEY,type INTEGER UNIQUE ON CONFLICT REPLACE,data BLOB);\”);
db.execSQL(\”CREATE TABLE friends (_id INTEGER PRIMARY KEY,uid INTEGER UNIQUE ON CONFLICT REPLACE,username TEXT,headurl TEXT,doing TEXT,nameindex TEXT,namepinyin TEXT,friendgroup TEXT,network TEXT,gender TEXT,isfriend INTEGER,suggest_text_1 TEXT,suggest_intent_query TEXT);\”);
db.execSQL(\”CREATE TABLE messages (_id INTEGER PRIMARY KEY,messageid INTEGER UNIQUE ON CONFLICT REPLACE,message BLOB);\”);
db.execSQL(\”CREATE TABLE favorites (_id INTEGER PRIMARY KEY,favoriteid BIGINT UNIQUE ON CONFLICT REPLACE,favoriteowner INTEGER,type INTEGER,favorite BLOB);\”);
db.execSQL(\”CREATE TABLE emonticons (_id INTEGER PRIMARY KEY,url TEXT,emotion TEXT UNIQUE ON CONFLICT REPLACE,img BLOB,size INTEGER,_data TEXT);\”);
db.execSQL(\”CREATE TABLE favoritefriends (_id INTEGER PRIMARY KEY,owner INTEGER,uid INTEGER,name TEXT);\”);
db.execSQL(\”CREATE TABLE chathistory (_id INTEGER PRIMARY KEY,uid INTEGER,tochatid INTEGER,chatmessage TEXT,comefrom INTEGER,chatname TEXT,chattime LONG);\”);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(\”DROP TABLE IF EXISTS pic\”);
db.execSQL(\”DROP TABLE IF EXISTS account\”);
db.execSQL(\”DROP TABLE IF EXISTS home\”);
db.execSQL(\”DROP TABLE IF EXISTS profile\”);
db.execSQL(\”DROP TABLE IF EXISTS friends\”);
db.execSQL(\”DROP TABLE IF EXISTS messages\”);
db.execSQL(\”DROP TABLE IF EXISTS favorites\”);
db.execSQL(\”DROP TABLE IF EXISTS emonticons\”);
db.execSQL(\”DROP TABLE IF EXISTS favoritefriends\”);
db.execSQL(\”DROP TABLE IF EXISTS favoritefriends\”);
db.execSQL(\”DROP TABLE IF EXISTS chathistory\”);
onCreate(db);
}
}
从代码中我们可以看到人人网Android客户端在用户手机上创建了renren.db数据库,数据库中共有10张表,分别为pic、account、home、profile、friends、messages、favorites、emonticons、favoritefriends、chathistory。
2. RenRenProvider
前面我们已经提到过ContentProvider,下面我们来看看人人网Android客户端是如何开发ContentProvider的。开发ContentProvider的两步:1)开发一个ContentProvider的子类,该子类需要实现增、删、改、查等方法。2)在AndroidManifest.xml文件中注册该ContentProvider。
下面是RenRenProvider核心代码:
public class RenRenProvider extends ContentProvider {
public static final String AUTHORITY = \”com.renren.mobile.provider\”;
public static final class Account implements BaseColumns {
public static final Uri ACCOUNT_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/account\”);
}
public static final class ChatHistory implements BaseColumns {
public static final Uri CHAT_HISTORY_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/chathistory\”);
}
public static final class Emonticons implements BaseColumns {
public static final Uri EMONTICONS_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/emonticons\”);
}
public static final class Favorite implements BaseColumns {
public static final Uri FAVORITE_CONTENTURI = Uri
.parse(\”content://com.renren.mobile.provider/favorites\”);
}
public static final class FavoriteFriends implements BaseColumns {
public static final Uri FAVORITE_FRIENDS_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/favoritefriends\”);
}
public static final class Friends implements BaseColumns {
public static final Uri FRIENDS_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/friends\”);
}
public static final class Home implements BaseColumns {
public static final Uri HOME_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/home\”);
}
public static final class Messages implements BaseColumns {
public static final Uri MESSAGES_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/messages\”);
}
public static final class Pic implements BaseColumns {
public static final Uri PIC_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/pic\”);
}
public static final class Profile implements BaseColumns {
public static final Uri PROFILE_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/profile\”);
}
private static final UriMatcher URI_MATCHER;
private RenRenProvider.DatabaseHelper renrenDatabaseHelper;
static {
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI(AUTHORITY, \”pic\”, 3);
URI_MATCHER.addURI(AUTHORITY, \”pic/#\”, 4);
URI_MATCHER.addURI(AUTHORITY, \”account\”, 5);
URI_MATCHER.addURI(AUTHORITY, \”account/#\”, 6);
URI_MATCHER.addURI(AUTHORITY, \”home\”, 7);
URI_MATCHER.addURI(AUTHORITY, \”home/#\”, 8);
URI_MATCHER.addURI(AUTHORITY, \”profile\”, 9);
URI_MATCHER.addURI(AUTHORITY, \”profile/#\”, 10);
URI_MATCHER.addURI(AUTHORITY, \”friends\”, 11);
URI_MATCHER.addURI(AUTHORITY, \”friends/#\”, 12);
URI_MATCHER.addURI(AUTHORITY, \”search_suggest_query/*\”, 1);
URI_MATCHER.addURI(AUTHORITY, \”search_suggest_query\”, 2);
URI_MATCHER.addURI(AUTHORITY, \”messages\”, 13);
URI_MATCHER.addURI(AUTHORITY, \”messages/#\”, 14);
URI_MATCHER.addURI(AUTHORITY, \”favorites\”, 15);
URI_MATCHER.addURI(AUTHORITY, \”favorites/#\”, 16);
URI_MATCHER.addURI(AUTHORITY, \”emonticons\”, 17);
URI_MATCHER.addURI(AUTHORITY, \”emonticons/#\”, 18);
URI_MATCHER.addURI(AUTHORITY, \”favoritefriends\”, 19);
URI_MATCHER.addURI(AUTHORITY, \”favortiefriends/#\”, 20);
URI_MATCHER.addURI(AUTHORITY, \”chathistory\”, 21);
URI_MATCHER.addURI(AUTHORITY, \”chathistory/#\”, 22);
URI_MATCHER.addURI(AUTHORITY, \”chathistory/*/*\”, 23);
}
public boolean onCreate()
{
renrenDatabaseHelper = new RenRenProvider.DatabaseHelper(this.getContext());
return true;
}
//其它代码省略…
}
下面是人人网android客户端在AndroidMantifest.xml中对该ContentProvider的注册。
<providerandroid:nameproviderandroid:nameproviderandroid:nameproviderandroid:name=\”.contentprovider.RenRenProvider\” android:permission=\”com.renren.mobile.android.permission.PERMISSION_ADD_ACCOUNT\”
android:authorities=\”com.renren.mobile.provider\” />
从上面的分析我们了解到只要得到com.renren.mobile.android.permission.PERMISSION_ADD_ACCOUNT权限我们就可以通过特定Uri访问人人网Android客户端在用户手机上创建的renren.db中特定表了。
3. 开发Android应用访问renren.db中的数据
从上面分析中我们已经知道renren.db中表结构,及访问特定表对应的Uri,如我们可以通过content://com.renren.mobile.provider/account访问renren.db中的account表等等。下面我们写个很简单的例子来访问account表中的account和ticket字段。
main.xml根节点下简单添加2个TextView,如下:
<TextView
android:id=\”@+id/textView1\”
android:layout_width=\”fill_parent\”
android:layout_height=\”wrap_content\”
android:text=\”TextView\” />
<TextView
android:id=\”@+id/textView2\”
android:layout_width=\”fill_parent\”
android:layout_height=\”wrap_content\”
android:text=\”TextView\” />
将account和ticket信息显示到TextView中,类代码如下
public class RenRenExtActivity extends Activity {
private static final Uri ACCOUNT_CONTENT_URI = Uri
.parse(\”content://com.renren.mobile.provider/account\”);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textView1 = (TextView) findViewById(R.id.textView1);
textView1.setText(\”Sorry.\”);
TextView textView2 = (TextView) findViewById(R.id.textView2);
textView2.setText(\”Sorry2.\”);
Cursor cursor = getContentResolver().query(ACCOUNT_CONTENT_URI, null,
null, null, null);
List<Map<String, String>> resultList = converCursorToList(cursor);
if (!resultList.isEmpty()) {
Map<String, String> map = resultList.get(0);
textView1.setText(map.get(\”account\”));
textView2.setText(map.get(\”ticket\”));
}
}
private List<Map<String, String>> converCursorToList(Cursor cursor) {
List<Map<String, String>> result = new ArrayList<Map<String, String>>();
if (cursor == null) {
return Collections.emptyList();
}
// 遍历Cursor结果集
while (cursor.moveToNext()) {
// 将结果集中的数据存入ArrayList中
Map<String, String> map = new HashMap<String, String>();
map.put(\”account\”,
cursor.getString(cursor.getColumnIndex(\”account\”)));
map.put(\”ticket\”, cursor.getString(cursor.getColumnIndex(\”ticket\”)));
result.add(map);
}
return result;
}
}
需要指出的是,上面的应用程序需要操作人人网android客户端中的数据库,因此要记得在AndroidMantifest.xml文件中为该应用程序授权。也就是在该文件的根元素中添加如下元素:
<uses-permission android:name=\”com.renren.mobile.android.permission.PERMISSION_ADD_ACCOUNT\” />
如果你android手机中安装有人人网Android客户端且曾经使用过,那么renren.db中应该有数据存在,把上面应用打包为apk文件安装到你android手机中,运行它,应该能看到屏幕中将显示你的人人网账号及一串ticket,该ticket是人人网Andriod客户端部分功能与人人网服务器通信的sid。
同理,也可以使用其它特定Uri访问手机中renre.db中特定的表,如friends表等等,所有Uri详见RenRenProvider代码。
综合帖:http://www.apkway.com/forum.php?mod=viewthread&tid=4840