package org.droidcon.droidconapp.news;
/*
* This file is part of OI Newsreader.
* Copyright (C) 2007-2009 OpenIntents.org
* OI Newsreader 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 3 of the License, or
* (at your option) any later version.
*
* OI Newsreader 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.
*
* You should have received a copy of the GNU General Public License
* along with OI Newsreader. If not, see <http://www.gnu.org/licenses/>.
*/
import java.io.InputStream;
import java.util.HashMap;
import org.droidcon.droidconapp.R;
import org.droidcon.droidconapp.news.News.Channel;
import org.droidcon.droidconapp.news.News.Contents;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.NotificationManager;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
public class NewsActivity extends ListActivity {
private static final int MENU_CHANNELITEM = 1001;
private static final int MENU_CHANNELSETTINGS = 1002;
private static final int MENU_TAGS = 1003;
private static final int MENU_SCAN = 1004;
private static final int MENU_SEARCH = 1005;
private static final int MENU_MARK_ALL_AS_READ = 1006;
private static final int SUBMENU_CHANNELITEM_TAG = 2001;
private static final int SUBMENU_CHANNELITEM_DELETE = 2002;
private static final int SUBMENU_CHANNELITEM_FOLLOW = 2003;
private static final int SUBMENU_CHANNELITEM_MAGNOLIA = 2004;
private static final int SUBMENU_CHANNELITEM_URL = 2005;
private static final int SUBMENU_CHANNELITEM_SHOW_CONTENT = 2006;
private static final int SUBMENU_DEBUG_1 = 6006;
private static final int SUBMENU_CHANNELITEM_TOGGLE = 2007;
private static final int SUBMENU_CHANNELSETTINGS_TAG = 3001;
private static final int SUBMENU_CHANNELSETTINGS_EDITSETTINGS = 3002;
private static final int SUBMENU_CHANNELSETTINGS_DELETEALL = 3003;
private static final String _TAG = "AFeedMessages";
protected static final int CONNECTIVITY_EVENT = 10000;
private Cursor mCursor;
private String feedID = "";
private String feedName = "";
private String channelType = "0";
private News mNews;
private String feedLink;
private boolean offlineMode;
private AlertDialog mCurrentMsgDialog;
private String feedUpdateMsgs;
private ConnectivityManager mConnectionManager;
private int mCurrentPosition;
private boolean notConnected;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
mNews = new News(getContentResolver());
// Add footer
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout footer = (LinearLayout) inflater.inflate(
R.layout.messages_footer, null);
Button bt = (Button) footer.findViewById(R.id.button);
bt.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
scan();
}
});
getListView().setItemsCanFocus(true);
getListView().addFooterView(footer);
mConnectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
}
private void checkOfflineMode() {
// Default is off:
offlineMode = true;
notConnected = false; // assume always online
if (mConnectionManager != null) {
NetworkInfo ni = mConnectionManager.getActiveNetworkInfo();
if (ni != null) {
Log.v(_TAG, ni.getTypeName());
NetworkInfo.State nis = ni.getState();
if (nis.equals(android.net.NetworkInfo.State.CONNECTED)
|| nis.equals(android.net.NetworkInfo.State.CONNECTING)) {
notConnected = false;
} else {
notConnected = true;
}
}
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Log.d(_TAG, "Clicked at >>" + position);
if (offlineMode) {
showOfflineItem(position);
} else {
followItemLink(position);
}
}
@Override
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
if (mCurrentMsgDialog != null && mCurrentMsgDialog.isShowing()) {
icicle.putInt(this.getClass().getName(), mCurrentPosition);
}
stopManagingCursor(mCursor);
Log.d("AFEEDLIST", "onFreeze: entering");
}
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
int position = state.getInt(this.getClass().getName(), -1);
if (position >= 0) {
showOfflineItem(position);
}
}
@Override
protected void onResume() {
super.onResume();
Log.d(_TAG, "onResume: entering");
checkOfflineMode();
init();
}
@Override
protected void onPause() {
super.onPause();
}
private void init() {
initFieldsFromIntent();
mCursor = managedQuery(News.Contents.CONTENT_URI,
News.Contents.PROJECTION_MAP, News.Contents.CHANNEL_ID + "="
+ "=" + feedID, null, null);
mCursor.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
NewsActivity.this.setTitle(feedName + "(" + mCursor.getCount()
+ ")");
}
});
this.setTitle(feedName + "(" + mCursor.getCount() + ")");
// always scan if no entries yet or
// if feed is viewed directly (e.g. from browser)
if (mCursor.getCount() == 0
|| Intent.ACTION_VIEW.equals(getIntent().getAction())) {
scan();
}
// Use our own list adapter
setListAdapter(new MessageListAdapter(mCursor, this, channelType));
// Add context menu
getListView().setOnCreateContextMenuListener(
new View.OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu contextmenu,
View view, ContextMenu.ContextMenuInfo obj) {
contextmenu.add(0,
NewsActivity.SUBMENU_CHANNELITEM_SHOW_CONTENT,
0, R.string.showoffline).setIcon(
android.R.drawable.ic_menu_info_details);
contextmenu.add(0,
NewsActivity.SUBMENU_CHANNELITEM_DELETE, 0,
R.string.delete).setIcon(
android.R.drawable.ic_menu_delete);
// contextmenu.add(0,AFeedMessages.SUBMENU_CHANNELITEM_TAG
// ,"Tag
// Local",R.drawable.tagging_application001a);
// contextmenu.add(0,
// AFeedMessages.SUBMENU_CHANNELITEM_MAGNOLIA, 0,
// R.string.magnolia_tagging);
// contextmenu.add(0, AFeedMessages.SUBMENU_DEBUG_1, 0,
// "show debug info").setIcon(
// android.R.drawable.ic_menu_info_details);
/*
* android.view.SubMenu submenu;
* submenu=contextmenu.addSubMenu
* (0,AFeedMessages.MENU_TAGS,
* "Tags",R.drawable.tagging_application001a);
* //submenu.
* add(0,AFeedMessages.SUBMENU_CHANNELITEM_TAG,"Tag
* Local",R.drawable.tagging_application001a);
* submenu.add
* (0,AFeedMessages.SUBMENU_CHANNELITEM_MAGNOLIA
* ,"Magnolia"
* ,R.drawable.tagging_magnolia_application001a);
*/
}
});
/*
* // Add click action getListView().setOnItemClickListener( new
* AdapterView.OnItemClickListener() {
*
* @Override public void onItemClick(AdapterView parent, View v, int
* position, long id) { // Clicking an item starts editing it
* followItemLink(position); }
*
* });
*/
}
private void initFieldsFromIntent() {
String channelUri = "http://droidcon.de/de?format=feed&type=rss";
feedID = mNews.findChannel(Channel.CONTENT_URI, channelUri);
feedLink = channelUri;
channelType = String.valueOf(News.CHANNEL_TYPE_RSS);
Log.v(_TAG, "view: " + channelType + " " + " " + feedID + " "
+ feedName + " " + feedLink);
if (feedID == null) {
HashMap map = new HashMap();
map.put(News.Channel.CHANNEL_LINK, feedLink);
AbstractFeedFetcherThread thread = new RSSSaxFetcherThread(map,
mNews, this);
InputStream is = thread.fetch();
feedName = thread.parseTitle(is);
ContentValues cv = new ContentValues();
cv.put(Channel.CHANNEL_LINK, feedLink);
cv.put(Channel.CHANNEL_TYPE, channelType);
cv.put(Channel.CHANNEL_NAME, feedName);
// default is 0 (= insertOnly)
feedUpdateMsgs = String.valueOf(0);
cv.put(News.Channel.UPDATE_MSGS, feedUpdateMsgs);
// default is 0 (= no notification)
cv.put(News.Channel.NOTIFY_NEW, String.valueOf(0));
Uri newUri = mNews.insert(Channel.CONTENT_URI, cv);
feedID = newUri.getLastPathSegment();
Log.v(_TAG, "new id: " + channelType + " " + " " + feedID + " "
+ feedName + " " + feedLink);
} else {
Cursor cursor = getContentResolver().query(
Uri.withAppendedPath(Channel.CONTENT_URI, feedID),
new String[] { Channel._ID, Channel.CHANNEL_TYPE,
Channel.UPDATE_MSGS }, null, null, null);
cursor.moveToFirst();
channelType = cursor.getString(1);
feedUpdateMsgs = cursor.getString(2);
cursor.close();
Log.v(_TAG, "old id: " + channelType + " " + " " + feedID + " "
+ feedName + " " + feedLink);
}
}
private int getChannelType(String type) {
int result = News.CHANNEL_TYPE_RSS;
return result;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.v("AFeedMessages", "onCreateOptionsMenu:entering");
boolean result = super.onCreateOptionsMenu(menu);
menu.add(0, NewsActivity.MENU_SCAN, 0, R.string.update).setIcon(
android.R.drawable.ic_menu_search);
menu.add(0, NewsActivity.MENU_MARK_ALL_AS_READ, 0,
R.string.markallasread);
// .setIcon(android.R.drawable.ic_menu_search);
return result;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.v(_TAG, "onOptionsItemSelected: item.id>>" + item.getItemId()
+ "<<");
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case MENU_SCAN:
scan();
break;
case MENU_MARK_ALL_AS_READ:
markAllAsRead();
break;
}
return true;
}
/**
* requires feedId, feedLink and channelType
*/
private void scan() {
setProgressBarIndeterminateVisibility(true);
// mProgressDialog = ProgressDialog.show(this,
// getString(R.string.update),
// getString(R.string.update));
new Thread() {
@Override
public void run() {
HashMap<String, String> data = new HashMap();
data.put(News.Channel._ID, feedID);
data.put(News.Channel.CHANNEL_LINK, feedLink);
data.put(News.Channel.UPDATE_MSGS, feedUpdateMsgs);
AbstractFeedFetcherThread rt = new RSSSaxFetcherThread(data,
mNews, NewsActivity.this);
InputStream is = rt.fetch();
if (is != null) {
rt.parse(is);
} else {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(NewsActivity.this,
getString(R.string.urlfailed),
Toast.LENGTH_LONG).show();
}
});
}
runOnUiThread(new Runnable() {
public void run() {
setProgressBarIndeterminateVisibility(true);
// mProgressDialog
// .setMessage(getString(R.string.checkicon));
}
});
data = new HashMap();
data.put(News.Channel._ID, feedID);
data.put(News.Channel.CHANNEL_NAME, feedName);
data.put(News.Channel.CHANNEL_LINK, feedLink);
data.put(News.Channel.CHANNEL_TYPE, channelType);
IconRetrieverThread iconThread = new IconRetrieverThread(
NewsActivity.this, data);
String iconUri = iconThread.getUri();
iconThread.downloadIcon(iconUri);
runOnUiThread(new Runnable() {
public void run() {
setProgressBarIndeterminateVisibility(false);
// mProgressDialog.dismiss();
}
});
}
}.start();
}
private void markAllAsRead() {
mNews.markFeedAsRead(Long.parseLong(feedID));
}
@Override
public boolean onContextItemSelected(MenuItem item) {
super.onContextItemSelected(item);
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item
.getMenuInfo();
switch (item.getItemId()) {
case SUBMENU_CHANNELITEM_FOLLOW:
followItemLink(menuInfo.position);
break;
case SUBMENU_CHANNELITEM_SHOW_CONTENT:
showOfflineItem(menuInfo.position);
break;
case SUBMENU_CHANNELITEM_TOGGLE:
((MessageListAdapter) getListAdapter()).toggle(menuInfo.position);
break;
case SUBMENU_CHANNELITEM_DELETE:
menuDelete(menuInfo.id);
break;
case SUBMENU_DEBUG_1:
showDebugInfo(menuInfo.position);
break;
}
return true;
}
private void showDebugInfo(int position) {
Cursor cursor = (Cursor) getListAdapter().getItem(position);
String pubDate = cursor.getString(cursor
.getColumnIndexOrThrow(Contents.ITEM_PUB_DATE));
String created = cursor.getString(cursor
.getColumnIndexOrThrow(Contents.CREATED_ON));
String id = cursor
.getString(cursor.getColumnIndexOrThrow(Contents._ID));
Toast.makeText(
this,
"Pub date: " + pubDate + "\n created: " + created + " id: "
+ id, Toast.LENGTH_LONG).show();
}
private void showOfflineItem(int position) {
Log.v(_TAG, "show offline " + position);
mCursor.moveToPosition(position);
SingleMessageWebView view = new SingleMessageWebView(this);
CharSequence titel = setWebViewMessage(view, mCursor);
Builder b = new AlertDialog.Builder(this).setView(view).setTitle(titel);
setCurrentMessageToRead(mCursor);
// get icon uri
Cursor channelC = getContentResolver().query(
Uri.withAppendedPath(Channel.CONTENT_URI, feedID),
new String[] { Channel._ID, Channel.CHANNEL_ICON_URI }, null,
null, null);
String iconUri = null;
if (channelC.moveToFirst()) {
iconUri = channelC.getString(1);
}
// set dialog icon
channelC.close();
setIcon(b, iconUri, Integer.parseInt(channelType));
// show dialog
mCurrentMsgDialog = b.show();
mCurrentPosition = position;
}
private void setCurrentMessageToRead(Cursor cursor) {
ContentValues cv = new ContentValues();
cv.put(News.Contents.READ_STATUS, News.STATUS_READ);
mNews.update(Uri.withAppendedPath(Contents.CONTENT_URI, cursor
.getString(mCursor.getColumnIndexOrThrow(News.Contents._ID))),
cv, null, null);
}
private CharSequence setWebViewMessage(final SingleMessageWebView view,
Cursor cursor) {
CharSequence content = cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents.ITEM_CONTENT));
CharSequence contentType = cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents.ITEM_CONTENT_TYPE));
CharSequence titel = cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents.ITEM_TITLE));
Log.v(_TAG, "show offline " + content + " " + titel);
if (News.CONTENT_TYPE_G.equals(contentType) && !notConnected) {
String link = cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents.ITEM_LINK));
view.loadUrl(link);
} else {
view.loadUrl(Uri.withAppendedPath(
Contents.CONTENT_URI,
cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents._ID)))
.toString());
}
view.setMessageLink(cursor.getString(cursor
.getColumnIndexOrThrow(News.Contents.ITEM_LINK)));
view.disableButtons(cursor.isFirst(), cursor.isLast());
return titel;
}
private void setIcon(Builder b, String iconUri, int type) {
if (iconUri == null || iconUri.equals("")) {
b.setIcon(R.drawable.rss_icon_small);
} else {
try {
b.setIcon(Drawable.createFromPath(iconUri));
} catch (Exception e) {
Log.e(_TAG, "error reading icon," + e.getMessage());
b.setIcon(R.drawable.rss_icon_small);
}
}
}
private void followItemLink(int position) {
int pos = position;
Log.d(_TAG, "followItemLink: pos>>" + pos + "<<");
if (pos > -1) {
mCursor.moveToPosition(pos);
Uri uri = null;
String strUri = mCursor.getString(mCursor
.getColumnIndexOrThrow(News.Contents.ITEM_LINK));
uri = Uri.parse(strUri);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
private void menuDelete(long l) {
int result = getContentResolver().delete(
Uri.withAppendedPath(Contents.CONTENT_URI, String.valueOf(l)),
null, null);
Log.d(_TAG, " deletet row " + l + " >" + result);
}
public void showPrevious(SingleMessageWebView view) {
mCursor.moveToPosition(mCurrentPosition);
if (!mCursor.isFirst()) {
mCursor.moveToPrevious();
CharSequence title = setWebViewMessage(view, mCursor);
mCurrentMsgDialog.setTitle(title);
setCurrentMessageToRead(mCursor);
mCurrentPosition--;
}
}
public void showNext(SingleMessageWebView view) {
mCursor.moveToPosition(mCurrentPosition);
if (!mCursor.isLast()) {
mCursor.moveToNext();
CharSequence title = setWebViewMessage(view, mCursor);
mCurrentMsgDialog.setTitle(title);
setCurrentMessageToRead(mCursor);
mCurrentPosition++;
}
}
}/* eoc */
|