/*******************************************************************************
* Copyright 2011, 2012, 2013 fanfou.com, Xiaoke, Zhang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.fanfou.app.opensource;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import com.fanfou.app.opensource.adapter.BaseCursorAdapter;
import com.fanfou.app.opensource.adapter.MessageCursorAdapter;
import com.fanfou.app.opensource.adapter.StatusCursorAdapter;
import com.fanfou.app.opensource.adapter.ViewsAdapter;
import com.fanfou.app.opensource.api.bean.Status;
import com.fanfou.app.opensource.db.Contents.BasicColumns;
import com.fanfou.app.opensource.db.Contents.DirectMessageInfo;
import com.fanfou.app.opensource.db.Contents.StatusInfo;
import com.fanfou.app.opensource.db.FanFouProvider;
import com.fanfou.app.opensource.dialog.ConfirmDialog;
import com.fanfou.app.opensource.service.Constants;
import com.fanfou.app.opensource.service.DownloadService;
import com.fanfou.app.opensource.service.FanfouServiceManager;
import com.fanfou.app.opensource.service.NotificationService;
import com.fanfou.app.opensource.ui.ActionBar;
import com.fanfou.app.opensource.ui.ActionManager;
import com.fanfou.app.opensource.ui.UIManager;
import com.fanfou.app.opensource.ui.viewpager.TitlePageIndicator;
import com.fanfou.app.opensource.ui.viewpager.TitleProvider;
import com.fanfou.app.opensource.util.CommonHelper;
import com.fanfou.app.opensource.util.IntentHelper;
import com.fanfou.app.opensource.util.OptionHelper;
import com.fanfou.app.opensource.util.SoundManager;
import com.fanfou.app.opensource.util.ToastHelper;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnLastItemVisibleListener;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
/**
* @author mcxiaoke
* @version 1.0 2011.05.31
*
*/
public class HomePage extends BaseActivity implements OnPageChangeListener,
OnItemLongClickListener, TitleProvider, OnRefreshListener2<ListView>,
OnLastItemVisibleListener, OnItemClickListener {
/**
* FetchService返回数据处理 根据resultData里面的type信息分别处理
*/
@SuppressLint("HandlerLeak")
@SuppressWarnings("deprecation")
private class ResultHandler extends Handler {
private final int requestPage;
private final boolean doGetMore;
public ResultHandler(final int page, final boolean getMore) {
this.requestPage = page;
this.doGetMore = getMore;
}
@Override
public void handleMessage(final Message msg) {
final Bundle bundle = msg.getData();
final int type = msg.arg1;
switch (msg.what) {
case Constants.RESULT_SUCCESS:
final int count = bundle.getInt(Constants.EXTRA_COUNT);
HomePage.this.views[this.requestPage].onRefreshComplete();
if (this.doGetMore) {
HomePage.this.cursors[this.requestPage].requery();
} else {
if (count > 0) {
String toastSuffix = null;
if (type == Constants.TYPE_STATUSES_HOME_TIMELINE) {
toastSuffix = "条好友消息";
} else if (type == Constants.TYPE_STATUSES_MENTIONS) {
toastSuffix = "条@你的消息";
} else if (type == Constants.TYPE_DIRECT_MESSAGES_CONVERSTATION_LIST) {
toastSuffix = "条私信";
} else if (type == Constants.TYPE_STATUSES_PUBLIC_TIMELINE) {
toastSuffix = "条随便看看消息";
}
if (AppContext.DEBUG) {
Log.i(HomePage.TAG, "ResultHandler page:"
+ this.requestPage + " message: " + count
+ toastSuffix);
}
showToast(count + toastSuffix);
if (HomePage.this.soundEffect) {
SoundManager.playSound(1, 0);
}
HomePage.this.cursors[this.requestPage].requery();
// listViews[requestPage].setSelection(0);
}
}
break;
case Constants.RESULT_ERROR:
HomePage.this.views[this.requestPage].onRefreshComplete();
final String errorMessage = bundle
.getString(Constants.EXTRA_ERROR);
final int errorCode = bundle.getInt(Constants.EXTRA_CODE);
if (AppContext.DEBUG) {
Log.i(HomePage.TAG, "ResultHandler page:"
+ this.requestPage + "errorCode:" + errorCode
+ " errorMessage: " + errorMessage);
}
CommonHelper.checkErrorCode(HomePage.this.mContext, errorCode,
errorMessage);
break;
default:
break;
}
}
}
public static final int NUMS_OF_PAGE = 4;
private ActionBar mActionBar;
private ViewPager mViewPager;
private Handler mUiHandler;
private ViewsAdapter mViewAdapter;
private TitlePageIndicator mPageIndicator;
private int mCurrentPage;
private int initPage;
private final PullToRefreshListView[] views = new PullToRefreshListView[HomePage.NUMS_OF_PAGE];
private final ListView[] listViews = new ListView[HomePage.NUMS_OF_PAGE];
private final Cursor[] cursors = new Cursor[HomePage.NUMS_OF_PAGE];
private final BaseCursorAdapter[] adapters = new BaseCursorAdapter[HomePage.NUMS_OF_PAGE];
private final Parcelable[] states = new Parcelable[HomePage.NUMS_OF_PAGE];
private static final String[] PAGE_TITLES = new String[] { "我的主页", "提到我的",
"我的私信", "随便看看" };
private boolean endlessScroll;
private boolean soundEffect;
public static final String TAG = "HomePage";
private long lastPressTime = 0;
private void checkRefresh() {
final boolean refresh = OptionHelper.readBoolean(this,
R.string.option_refresh_on_open, false);
if ((this.mCurrentPage == 0)
&& (refresh || (this.cursors[0].getCount() == 0))) {
this.mUiHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (HomePage.this.views[HomePage.this.mCurrentPage] != null) {
HomePage.this.views[HomePage.this.mCurrentPage]
.setRefreshing();
}
}
}, 300);
}
}
private void checkUpdate() {
final boolean autoUpdate = OptionHelper.readBoolean(this,
R.string.option_autoupdate, true);
if (autoUpdate) {
final long now = System.currentTimeMillis();
final long last = OptionHelper.readLong(this,
R.string.option_auto_update_last_time, 0L);
if (AppContext.DEBUG) {
log("checkUpdate() autoUpdate=" + autoUpdate
+ " lastUpdateTime=" + last);
}
if ((now - last) > DownloadService.AUTO_UPDATE_INTERVAL) {
OptionHelper.saveLong(this,
R.string.option_auto_update_last_time, now);
final Intent intent = new Intent(this, DownloadService.class);
intent.putExtra(Constants.EXTRA_TYPE,
DownloadService.TYPE_CHECK);
startService(intent);
}
}
}
@SuppressWarnings("unused")
private boolean doBackPress() {
if ((System.currentTimeMillis() - this.lastPressTime) < 2000) {
finish();
} else {
CommonHelper.notify(this, "再按一次退出");
this.lastPressTime = System.currentTimeMillis();
}
return true;
}
/**
* 载入更多,获取较旧的消息
*/
private void doGetMore() {
doRetrieve(this.mCurrentPage, true);
}
/**
* 刷新,载入更新的消息
*/
private void doRefresh() {
if (AppContext.DEBUG) {
log("doRefresh()");
}
doRetrieve(this.mCurrentPage, false);
}
/**
* 刷新,获取最新的消息
*
* @param type
* 类型参数:Home/Mention/Message/Public
*/
private void doRetrieve(final int page, final boolean doGetMore) {
if (AppContext.DEBUG) {
log("doRetrieve() page=" + page + " doGetMore=" + doGetMore);
}
final ResultHandler handler = new ResultHandler(page, doGetMore);
String sinceId = null;
String maxId = null;
final Cursor cursor = this.cursors[page];
switch (page) {
case 0:
if (doGetMore) {
maxId = CommonHelper.getMaxId(cursor);
} else {
sinceId = CommonHelper.getSinceId(cursor);
}
FanfouServiceManager.doFetchHomeTimeline(this, new Messenger(
handler), sinceId, maxId);
break;
case 1:
if (doGetMore) {
maxId = CommonHelper.getMaxId(cursor);
} else {
sinceId = CommonHelper.getSinceId(cursor);
}
FanfouServiceManager.doFetchMentions(this, new Messenger(handler),
sinceId, maxId);
break;
case 2:
FanfouServiceManager.doFetchDirectMessagesConversationList(this,
new Messenger(handler), doGetMore);
break;
case 3:
if (!doGetMore) {
FanfouServiceManager.doFetchPublicTimeline(this, new Messenger(
handler));
}
break;
default:
break;
}
}
@Override
protected IntentFilter getIntentFilter() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Constants.ACTION_STATUS_SENT);
filter.addAction(Constants.ACTION_DRAFTS_SENT);
filter.addAction(Constants.ACTION_NOTIFICATION);
return filter;
}
@Override
protected int getPageType() {
return BaseActivity.PAGE_HOME;
}
@Override
public String getTitle(final int position) {
return HomePage.PAGE_TITLES[position % HomePage.NUMS_OF_PAGE];
}
private void goTop() {
if (this.listViews[this.mCurrentPage] != null) {
this.listViews[this.mCurrentPage].setSelection(0);
}
}
private void initAdapters() {
this.adapters[0] = new StatusCursorAdapter(true, this, this.cursors[0]);
this.adapters[1] = new StatusCursorAdapter(true, this, this.cursors[1]);
this.adapters[2] = new MessageCursorAdapter(this, this.cursors[2]);
this.adapters[3] = new StatusCursorAdapter(true, this, this.cursors[3]);
}
private void initialize() {
this.initPage = getIntent().getIntExtra(Constants.EXTRA_PAGE, 0);
this.endlessScroll = OptionHelper.readBoolean(this,
R.string.option_page_scroll_endless, false);
this.soundEffect = OptionHelper.readBoolean(this,
R.string.option_play_sound_effect, true);
this.mUiHandler = new Handler();
initSoundManager();
}
@SuppressWarnings("deprecation")
private Cursor initMessageCursor() {
final Uri uri = Uri.withAppendedPath(DirectMessageInfo.CONTENT_URI,
"list");
return managedQuery(uri, DirectMessageInfo.COLUMNS, null, null, null);
}
private void initSoundManager() {
setVolumeControlStream(AudioManager.STREAM_MUSIC);
SoundManager.getInstance();
SoundManager.initSounds(this);
SoundManager.loadSounds();
}
@SuppressWarnings("deprecation")
private Cursor initStatusCursor(final int type) {
final String where = BasicColumns.TYPE + "=?";
final String[] whereArgs = new String[] { String.valueOf(type) };
final Uri uri = StatusInfo.CONTENT_URI;
return managedQuery(uri, StatusInfo.COLUMNS, where, whereArgs,
FanFouProvider.ORDERBY_DATE_DESC);
}
@Override
protected boolean isHomeScreen() {
return true;
}
private void log(final String message) {
Log.d(HomePage.TAG, message);
}
@Override
public void onBackPressed() {
final boolean needConfirm = OptionHelper.readBoolean(this,
R.string.option_confirm_on_exit, false);
if (needConfirm) {
final ConfirmDialog dialog = new ConfirmDialog(this, "提示",
"确认退出饭否吗?");
dialog.setClickListener(new ConfirmDialog.AbstractClickHandler() {
@Override
public void onButton1Click() {
HomePage.this.mContext.finish();
}
});
dialog.show();
} else {
super.onBackPressed();
}
}
@SuppressWarnings("deprecation")
@Override
protected boolean onBroadcastReceived(final Intent intent) {
final String action = intent.getAction();
if (action.equals(Constants.ACTION_STATUS_SENT)) {
if (AppContext.DEBUG) {
log("onBroadcastReceived ACTION_STATUS_SENT");
}
if (this.mCurrentPage == 0) {
final boolean needRefresh = OptionHelper.readBoolean(this,
R.string.option_refresh_after_send, false);
if (needRefresh) {
startRefresh();
}
}
} else if (action.equals(Constants.ACTION_DRAFTS_SENT)) {
if (AppContext.DEBUG) {
log("onBroadcastReceived ACTION_DRAFTS_SENT");
}
if (this.mCurrentPage == 0) {
final boolean needRefresh = OptionHelper.readBoolean(this,
R.string.option_refresh_after_send, false);
if (needRefresh) {
startRefresh();
}
}
} else if (action.equals(Constants.ACTION_NOTIFICATION)) {
if (AppContext.DEBUG) {
log("onBroadcastReceived ACTION_NOTIFICATION");
}
final int type = intent.getIntExtra(Constants.EXTRA_TYPE, -1);
final int count = intent.getIntExtra(Constants.EXTRA_COUNT, 0);
switch (type) {
case NotificationService.NOTIFICATION_TYPE_HOME:
if (count > 0) {
if (this.cursors[0] != null) {
this.cursors[0].requery();
}
this.listViews[0].setSelection(0);
CommonHelper.notify(this, count + "条新消息");
if (this.soundEffect) {
SoundManager.playSound(1, 0);
}
}
break;
case NotificationService.NOTIFICATION_TYPE_MENTION:
if (count > 0) {
if (this.cursors[1] != null) {
this.cursors[1].requery();
}
this.listViews[1].setSelection(0);
CommonHelper.notify(this, count + "条新@消息");
if (this.soundEffect) {
SoundManager.playSound(1, 0);
}
}
break;
case NotificationService.NOTIFICATION_TYPE_DM:
if (count > 0) {
if (this.cursors[2] != null) {
this.cursors[2].requery();
}
this.listViews[2].setSelection(0);
CommonHelper.notify(this, count + "条新私信");
if (this.soundEffect) {
SoundManager.playSound(1, 0);
}
}
break;
default:
break;
}
}
return true;
}
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.actionbar_title:
goTop();
break;
default:
break;
}
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (AppContext.DEBUG) {
log("onCreate()");
}
initialize();
setContentView(R.layout.home);
setActionBar();
setListViews();
setViewPager();
setCursors();
setAdapters();
checkRefresh();
checkUpdate();
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
// super.onCreateOptionsMenu(menu);
final MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.home_menu, menu);
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
AppContext.getImageLoader().shutdown();
SoundManager.cleanup();
if (AppContext.DEBUG) {
log("onDestroy()");
}
}
@Override
public void onItemClick(final AdapterView<?> parent, final View view,
final int position, final long id) {
final Cursor c = (Cursor) parent.getItemAtPosition(position);
if (c == null) {
return;
}
if (this.mCurrentPage == 2) {
CommonHelper.goMessageChatPage(this, c);
} else {
final Status s = Status.parse(c);
if ((s != null) && !s.isNull()) {
CommonHelper.goStatusPage(this, s);
}
}
}
@Override
public boolean onItemLongClick(final AdapterView<?> parent,
final View view, final int position, final long id) {
if (this.mCurrentPage == 2) {
return true;
}
final Cursor c = (Cursor) parent.getItemAtPosition(position);
showPopup(view, c);
return true;
}
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
@Override
public void onLastItemVisible() {
}
private void onMenuLogoutClick() {
final ConfirmDialog dialog = new ConfirmDialog(this, "注销",
"确定注销当前登录帐号吗?");
dialog.setClickListener(new ConfirmDialog.AbstractClickHandler() {
@Override
public void onButton1Click() {
AppContext.handleLogout(HomePage.this.mContext);
IntentHelper.goLoginPage(HomePage.this.mContext);
finish();
}
});
dialog.show();
}
private void onMenuOptionClick() {
final Intent intent = new Intent(this, SettingsPage.class);
startActivity(intent);
}
private void onMenuProfileClick() {
ActionManager.doMyProfile(this);
}
private void onMenuSearchClick() {
final Intent intent = new Intent(this, SearchPage.class);
startActivity(intent);
}
@Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
this.initPage = getIntent().getIntExtra(Constants.EXTRA_PAGE, 0);
if (AppContext.DEBUG) {
log("onNewIntent page=" + this.initPage);
}
if (this.initPage >= 0) {
this.mViewPager.setCurrentItem(this.initPage);
}
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
switch (id) {
case R.id.menu_option:
onMenuOptionClick();
return true;
case R.id.menu_profile:
onMenuProfileClick();
return true;
case R.id.menu_search:
onMenuSearchClick();
return true;
case R.id.menu_logout:
onMenuLogoutClick();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onPageScrolled(final int position, final float positionOffset,
final int positionOffsetPixels) {
this.mPageIndicator.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
@Override
public void onPageScrollStateChanged(final int state) {
}
@Override
public void onPageSelected(final int position) {
this.mCurrentPage = position % HomePage.NUMS_OF_PAGE;
this.mPageIndicator.onPageSelected(this.mCurrentPage);
if ((this.cursors[this.mCurrentPage] != null)
&& (this.cursors[this.mCurrentPage].getCount() == 0)) {
startRefresh();
}
}
@Override
protected void onPause() {
super.onPause();
if (AppContext.DEBUG) {
log("onPause");
}
}
@Override
public void onPullDownToRefresh(
final PullToRefreshBase<ListView> refreshView) {
doRefresh();
}
@Override
public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
doGetMore();
}
@Override
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
for (int i = 0; i < this.views.length; i++) {
if (this.views[i] != null) {
this.states[i] = savedInstanceState.getParcelable(this.views[i]
.toString());
}
}
}
@Override
protected void onResume() {
super.onResume();
if (AppContext.DEBUG) {
log("onResume");
}
for (int i = 0; i < this.views.length; i++) {
if ((this.views[i] != null) && (this.states[i] != null)) {
this.listViews[i].onRestoreInstanceState(this.states[i]);
this.states[i] = null;
}
}
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
for (int i = 0; i < this.views.length; i++) {
if (this.views[i] != null) {
this.states[i] = this.listViews[i].onSaveInstanceState();
outState.putParcelable(this.views[i].toString(), this.states[i]);
}
}
}
@Override
protected void onStop() {
super.onStop();
if (!AppContext.isWifi()) {
AppContext.getImageLoader().clearQueue();
}
}
/**
* 初始化和设置ActionBar
*/
private void setActionBar() {
this.mActionBar = (ActionBar) findViewById(R.id.actionbar);
this.mActionBar.setRightAction(new ActionBar.WriteAction(this, null));
this.mActionBar.setTitle(getString(R.string.app_name));
if (AppContext.DEBUG) {
this.mActionBar.setTitle("开发版 " + AppContext.appVersionName
+ " 用户:" + AppContext.getUserName());
}
}
private void setAdapters() {
initAdapters();
for (int i = 0; i < this.adapters.length; i++) {
this.views[i].setAdapter(this.adapters[i]);
}
}
private void setCursors() {
this.cursors[0] = initStatusCursor(Constants.TYPE_STATUSES_HOME_TIMELINE);
this.cursors[1] = initStatusCursor(Constants.TYPE_STATUSES_MENTIONS);
this.cursors[2] = initMessageCursor();
this.cursors[3] = initStatusCursor(Constants.TYPE_STATUSES_PUBLIC_TIMELINE);
}
/**
* 初始化并添加四个页面的ListView
*/
private void setListViews() {
final LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < this.views.length; i++) {
this.views[i] = (PullToRefreshListView) inflater.inflate(
R.layout.ptr_list, null);
this.views[i].setOnRefreshListener(this);
this.listViews[i] = this.views[i].getRefreshableView();
this.listViews[i].setOnItemClickListener(this);
if (i != 2) {
this.listViews[i].setOnItemLongClickListener(this);
}
if (i == 3) {
this.views[i].setMode(Mode.PULL_FROM_START);
}
}
}
private void setViewPager() {
if (AppContext.DEBUG) {
log("setViewPager initPage=" + this.initPage);
}
this.mViewAdapter = new ViewsAdapter(this.views, this.endlessScroll);
this.mViewPager = (ViewPager) findViewById(R.id.viewpager);
this.mViewPager.setOnPageChangeListener(this);
this.mViewPager.setAdapter(this.mViewAdapter);
this.mPageIndicator = (TitlePageIndicator) findViewById(R.id.viewindicator);
this.mPageIndicator.setTitleProvider(this);
if (this.initPage > 0) {
this.mPageIndicator.setViewPager(this.mViewPager, this.initPage);
this.mViewPager.setCurrentItem(this.initPage);
}
}
private void showPopup(final View view, final Cursor c) {
if (c != null) {
final Status s = Status.parse(c);
if (s == null) {
return;
}
UIManager.showPopup(this.mContext, c, view, s);
}
}
private void showToast(final String text) {
ToastHelper.showInfoToast(this.mContext, text);
}
private void startRefresh() {
if (this.views[this.mCurrentPage] != null) {
this.views[this.mCurrentPage].setRefreshing();
}
}
}