/*
* $Id: RSSReaderProvider.java 114 2008-02-14 05:09:23Z jasta00 $
*
* Copyright (C) 2007 Josh Guilfoyle <jasta@devtcg.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package org.devtcg.rssreader.provider;
import org.devtcg.rssreader.provider.RSSReaderProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import org.devtcg.rssreader.R;
import android.content.ContentProvider;
import android.database.sqlite.SQLiteOpenHelper;
import android.content.ContentUris;
import android.content.UriMatcher;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteQueryBuilder;
import android.content.Resources;
import android.database.ArrayListCursor;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;
public class RSSReaderProvider extends ContentProvider
{
private SQLiteDatabase mDB;
private static final String TAG = "RSSReaderProvider";
private static final String DATABASE_NAME = "rss_reader.db";
private static final int DATABASE_VERSION = 9;
private static HashMap<String, String> CHANNEL_LIST_PROJECTION_MAP;
private static HashMap<String, String> POST_LIST_PROJECTION_MAP;
private static final int CHANNELS = 1;
private static final int CHANNEL_ID = 2;
private static final int POSTS = 3;
private static final int POST_ID = 4;
private static final int CHANNEL_POSTS = 5;
private static final int CHANNELICON_ID = 6;
private static final UriMatcher URL_MATCHER;
private static class DatabaseHelper extends SQLiteOpenHelper
{
protected void onCreateChannels(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE rssreader_channel (_id INTEGER PRIMARY KEY," +
" title TEXT UNIQUE, url TEXT UNIQUE, " +
" icon TEXT, icon_url TEXT, logo TEXT);");
}
protected void onCreatePosts(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE rssreader_post (_id INTEGER PRIMARY KEY," +
" channel_id INTEGER, title TEXT, url TEXT, " +
" posted_on DATETIME, body TEXT, author TEXT, read INTEGER(1) DEFAULT '0');");
/* TODO: Should we narrow this more to just URL _or_ title? */
db.execSQL("CREATE UNIQUE INDEX unq_post ON rssreader_post (title, url);");
/* Create an index to efficiently access posts on a particular channel. */
db.execSQL("CREATE INDEX idx_channel ON rssreader_post (channel_id);");
}
@Override
public void onCreate(SQLiteDatabase db)
{
onCreateChannels(db);
onCreatePosts(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
assert(newVersion == DATABASE_VERSION);
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + "...");
switch(oldVersion)
{
case 7:
db.execSQL("ALTER TABLE rssreader_channel ADD COLUMN icon_url TEXT;");
break;
default:
Log.w(TAG, "Version too old, wiping out database contents...");
db.execSQL("DROP TABLE IF EXISTS rssreader_channel;");
db.execSQL("DROP TABLE IF EXISTS rssreader_post;");
onCreate(db);
break;
}
}
}
@Override
public boolean onCreate()
{
DatabaseHelper dbHelper = new DatabaseHelper();
mDB = dbHelper.openDatabase(getContext(), DATABASE_NAME, null, DATABASE_VERSION);
return (mDB == null) ? false : true;
}
@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort)
{
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String defaultSort = null;
switch(URL_MATCHER.match(url))
{
case CHANNELS:
qb.setTables("rssreader_channel");
qb.setProjectionMap(CHANNEL_LIST_PROJECTION_MAP);
defaultSort = RSSReader.Channels.DEFAULT_SORT_ORDER;
break;
case CHANNEL_ID:
qb.setTables("rssreader_channel");
qb.appendWhere("_id=" + url.getPathSegments().get(1));
break;
/*
case POSTS:
qb.setTables("rssreader_post");
qb.setProjectionMap(POST_LIST_PROJECTION_MAP);
defaultSort = RSSReader.Posts.DEFAULT_SORT_ORDER;
break;
*/
case CHANNEL_POSTS:
qb.setTables("rssreader_post");
qb.appendWhere("channel_id=" + url.getPathSegments().get(1));
qb.setProjectionMap(POST_LIST_PROJECTION_MAP);
defaultSort = RSSReader.Posts.DEFAULT_SORT_ORDER;
break;
case POST_ID:
qb.setTables("rssreader_post");
qb.appendWhere("_id=" + url.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
String orderBy;
if (TextUtils.isEmpty(sort))
orderBy = defaultSort;
else
orderBy = sort;
Cursor c = qb.query(mDB, projection, selection, selectionArgs,
null, null, orderBy);
c.setNotificationUri(getContext().getContentResolver(), url);
return c;
}
@Override
public String getType(Uri url)
{
switch(URL_MATCHER.match(url))
{
case CHANNELS:
return "vnd.android.cursor.dir/vnd.rssreader.channel";
case CHANNEL_ID:
return "vnd.android.cursor.item/vnd.rssreader.channel";
case CHANNELICON_ID:
return "image/x-icon";
case POSTS:
case CHANNEL_POSTS:
return "vnd.android.cursor.dir/vnd.rssreader.post";
case POST_ID:
return "vnd.android.cursor.item/vnd.rssreader.post";
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
}
private String getIconFilename(long channelId)
{
return "channel" + channelId + ".ico";
}
private String getIconPath(long channelId)
{
return getContext().getFileStreamPath(getIconFilename(channelId)).getAbsolutePath();
}
private void copyDefaultIcon(String path)
throws FileNotFoundException, IOException
{
FileOutputStream out = new FileOutputStream(path);
InputStream ico =
getContext().getResources().openRawResource(R.drawable.feedicon);
byte[] buf = new byte[1024];
int n;
while ((n = ico.read(buf)) != -1)
out.write(buf, 0, n);
ico.close();
out.close();
}
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException
{
switch(URL_MATCHER.match(uri))
{
case CHANNELICON_ID:
long id = Long.valueOf(uri.getPathSegments().get(1));
String path = getIconPath(id);
/* XXX: This appears to be an Android bug: files created with
* ParcelFileDescriptor.MODE_CREATE have mode 0, which is not
* readable. */
if (mode.equals("rw") == true)
{
FileOutputStream foo = getContext().openFileOutput(getIconFilename(id), 0);
try { foo.write(new byte[] { 't' }); foo.close(); }
catch (Exception e) { }
}
File file = new File(path);
int modeint;
if (mode.equals("rw") == true)
{
modeint = ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_TRUNCATE;
}
else
{
modeint = ParcelFileDescriptor.MODE_READ;
if (file.exists() == false)
{
try
{
/* TODO: Find a way around this. We should be able to
* simply return an InputStream. */
copyDefaultIc
androidRSS例子
需积分: 3 44 浏览量
2011-08-19
17:36:50
上传
评论
收藏 62KB ZIP 举报
hieify001
- 粉丝: 5
- 资源: 54
最新资源
- #P0015. 全排列 超级简单
- pta题库答案c语言之排序4统计工龄.zip
- pta题库答案c语言之树结构7堆中的路径.zip
- pta题库答案c语言之树结构3TreeTraversalsAgain.zip
- pta题库答案c语言之树结构2ListLeaves.zip
- pta题库答案c语言之树结构1树的同构.zip
- 基于C++实现民航飞行与地图简易管理系统可执行程序+说明+详细注释.zip
- pta题库答案c语言之复杂度1最大子列和问题.zip
- 三维装箱问题(Three-Dimensional Bin Packing Problem,3D-BPP)是一个经典的组合优化问题
- 以下是一些关于Linux线程同步的基本概念和方法.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈