package com.athena.asm;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewPager;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.athena.asm.Adapter.TabsAdapter;
import com.athena.asm.data.Board;
import com.athena.asm.data.Preferences;
import com.athena.asm.fragment.CategoryFragment;
import com.athena.asm.fragment.FavoriteListFragment;
import com.athena.asm.fragment.GuidanceListFragment;
import com.athena.asm.fragment.MailFragment;
import com.athena.asm.fragment.ProfileFragment;
import com.athena.asm.listener.OnKeyDownListener;
import com.athena.asm.service.CheckMessageService;
import com.athena.asm.util.StringUtility;
import com.athena.asm.util.task.CheckUpdateAsyncTask;
import com.athena.asm.util.task.LoginTask;
import com.athena.asm.viewmodel.BaseViewModel;
import com.athena.asm.viewmodel.HomeViewModel;
import com.google.analytics.tracking.android.EasyTracker;
import com.koushikdutta.urlimageviewhelper.UrlImageViewHelper;
public class HomeActivity extends SherlockFragmentActivity implements OnOpenActivityFragmentListener,
BaseViewModel.OnViewModelChangObserver {
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
// stop EasyTracker methods
EasyTracker.getInstance().activityStop(this);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
// Adding EasyTracker methods
EasyTracker.getInstance().activityStart(this);
}
private HomeViewModel m_viewModel;
public LayoutInflater m_inflater;
private Handler m_handler = new Handler();
// public static aSMApplication m_application;
// public static int THEME = R.style.Theme_Sherlock;
ViewPager m_viewPager;
TabsAdapter m_tabsAdapter;
private ProgressDialog m_pdialog;
private boolean mDoubleBackToExit;
private Handler mHandler = null;
class PendingDoubleBackToExit implements Runnable {
public void run() {
mDoubleBackToExit = false;
}
}
Boolean getBoolean(Object key){
if(key == null)
return false;
return (Boolean)(key);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
aSMApplication application = aSMApplication.getCurrentApplication();
setTheme(aSMApplication.THEME);
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
// setContentView(R.layout.home);
m_viewPager = new ViewPager(this);
m_viewPager.setId(R.id.homePager);
setContentView(m_viewPager);
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
boolean isLight = aSMApplication.THEME == R.style.Theme_Sherlock_Light;
m_tabsAdapter = new TabsAdapter(this, m_viewPager);
m_tabsAdapter.addTab(actionBar.newTab().setIcon(isLight ? R.drawable.home_inverse : R.drawable.home),
GuidanceListFragment.class, null);
m_tabsAdapter.addTab(actionBar.newTab().setIcon(isLight ? R.drawable.favorite_inverse : R.drawable.favorite),
FavoriteListFragment.class, null);
m_tabsAdapter.addTab(actionBar.newTab().setIcon(isLight ? R.drawable.category_inverse : R.drawable.category),
CategoryFragment.class, null);
m_tabsAdapter.addTab(actionBar.newTab().setIcon(isLight ? R.drawable.mail_inverse : R.drawable.mail),
MailFragment.class, null);
m_tabsAdapter.addTab(actionBar.newTab().setIcon(isLight ? R.drawable.profile_inverse : R.drawable.profile),
ProfileFragment.class, null);
m_tabsAdapter.finishInit();
m_inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
m_viewModel = application.getHomeViewModel();
m_viewModel.registerViewModelChangeObserver(this);
m_viewModel.setCurrentTab(null); // since m_tabsAdapter.addTab will set
// current tab
boolean isAutoLogin = application.isAutoLogin();
m_viewModel.updateLoginStatus();
if (this.getIntent().getExtras() != null) {
m_viewModel.setLoggedin(getBoolean(this.getIntent().getExtras().get(StringUtility.LOGINED)));
m_viewModel.setGuestLogined(getBoolean(this.getIntent().getExtras().get(StringUtility.GUEST_LOGINED)));
}
// 如果已从login页面登录过来
if (m_viewModel.isLogined()) {
init();
}
// 如果是从login页面用guest登录过来
else if (m_viewModel.isGuestLogined()) {
init();
}
// 如果是第一次启动且保存了自动登录
else if (isAutoLogin) {
m_viewModel.restorSmthSupport();
String userName = application.getAutoUserName();
String password = application.getAutoPassword();
showProgressDialog("自动登录中...");
// LoginTask.doInBackground --> HomeViewModel.login -->
// SmthSupport.login
// loginTask.onPostExecute --> HomeViewModel.notifyLoginChanged
// --> HomeViewModel.notifyViewModelChange
// --> HomeActivity.onViewModelChange --> HomeActivity.loginTaskDone
LoginTask loginTask = new LoginTask(m_viewModel, userName, password);
loginTask.execute();
}
// 如果是第一次启动且没有自动登录
else {
Intent intent = new Intent();
intent.setClassName("com.athena.asm", "com.athena.asm.LoginActivity");
startActivity(intent);
finish();
}
setRequestedOrientation(aSMApplication.ORIENTATION);
}
@Override
protected void onResume() {
super.onResume();
}
// @Override
// public void onConfigurationChanged(Configuration newConfig) {
// // do nothing to stop onCreated
// super.onConfigurationChanged(newConfig);
// }
@Override
public void onDestroy() {
m_viewModel.unregisterViewModelChangeObserver(this);
super.onDestroy();
}
public void showAuthenticationFailedToast() {
m_handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "用户名或密码错.", Toast.LENGTH_SHORT).show();
}
});
}
public void showConnectionFailedToast() {
m_handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "连接错误,请检查网络.", Toast.LENGTH_SHORT).show();
}
});
}
public void loginTaskDone(int iLoginResult) {
if (iLoginResult != 1) {
if (iLoginResult == 0)
showAuthenticationFailedToast();
else if (iLoginResult == -1)
showConnectionFailedToast();
Intent intent = new Intent();
intent.setClassName("com.athena.asm", "com.athena.asm.LoginActivity");
startActivity(intent);
finish();
} else {
m_viewModel.updateLoginStatus();
init();
if (m_viewModel.getCurrentTab().equals(StringUtility.TAB_GUIDANCE)) {
m_viewModel.notifyGuidanceChanged();
}
}
}
// show information dialog, called by first run and about icon
private void showInfoDialog() {
// read version info from androidmanifest.xml
String version = "unknown";
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(getPackageName(), 0);
version = pi.versionName;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
Log.d("HomeActivity: can't get version name", e.toString());
}
// generate about_content with version from manifest
String content = getText(R.string.about_content).toString();
String content_with_version = String.format(content, version);
// linkify
final SpannableString msg = new SpannableString(content_with_version);
Linkify.addLinks(msg, Linkify.WEB_URLS);
final AlertDialog dlg = new AlertDialog.Builder(this).setIcon(R.drawable.icon).setTitle(R.string.about_title)
.setMessage(msg).create();
dlg.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.about_close),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing here
}
});
dlg.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.about_upgrade),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CheckUpdateAsyncTask task = new CheckUpdateAsyncTask(HomeActivity.this);
task.execute();
dlg.dismiss();
}
});
dlg.show();
// Make the textview clickable. Must be called after show()
((TextView) dlg.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
}
private void init() {
// initTasks();
aSMApplication application = aSMApplication.getCurrentApplication();
if (application.isFirstLaunchApp() || application.isFirstLaunchAfterUpdate()) {
application.markFirstLaunchApp();
showInfoDialog();
}
// if external sdcard is not available, we can't show images
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, "存储卡故障!附件图片将无法显示!", Toast.LENGTH_LONG).show();
}
m_viewModel.setChangeNotificationEnabled(false);
String tab = m_viewModel.getCurrentTab() == null ? application.getDefaultTab() : m_viewModel.getCurrentTab();
m_viewModel.setCurrentTab(tab);
m_viewModel.setChangeNotificationEnabled(true);
int item = 0;
if (tab.equals(StringUtility.TAB_GUIDANCE)) {
item = 0;
} else if (tab.equals(StringUtility.TAB_FAVORITE)) {
item = 1;
} else if (tab.equals(StringUtility.TAB_CATEGORY)) {
item = 2;
} else if (tab.equals(StringUtility.TAB_MAIL)) {
item = 3;
} else {
item = 4;
}
m_viewPager.setCurrentItem(item);
CheckMessageService.schedule(this);
}
private void exit() {
aSMApplication application = aSMApplication.getCurrentApplication();
Boolean rememberUser = application.isRememberUser();
if (!rememberUser) {
application.updateAutoUserNameAndPassword("", "");
}
application.syncPreferences();
finishAndClean();
}
private void finishAndClean() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(CheckMessageService.MESSAGE_NOTIFICATION_ID);
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
private void logout(final boolean isToExit) {
final ProgressDialog pdialog = new ProgressDialog(this);
pdialog.setMessage("正在注销...");
pdialog.show();
CheckMessageService.unschedule(this);
m_viewModel.clear();
// final Context context = this;
Thread th = new Thread() {
@Override
public void run() {
m_viewModel.logout();
pdialog.cancel();
if (!isToExit) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(StringUtility.LOGOUT, true);
intent.setClassName("com.athena.asm", "com.athena.asm.LoginActivity");
startActivity(intent);
finish();
} else {
// Intent intent = new Intent(context, LogoutService.class);
// PendingIntent pending = PendingIntent.getService(context,
// 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Calendar c = new GregorianCalendar();
// c.add(Calendar.SECOND, 2);
//
// AlarmManager alarm = (AlarmManager) context
// .getSystemService(Context.ALARM_SERVICE);
// alarm.cancel(pending);
// alarm.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),
// pending);
exit();
}
}
};
th.start();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (m_viewModel.isLogined()) {
// check preference for logout_confirm
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
boolean b_logout_confirm = settings.getBoolean(Preferences.LOGOUT_CONFIRM, false);
if (b_logout_confirm) {
// logout is required
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("确认要注销退出吗?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
logout(true);
}
});
builder.setNegativeButton("取消", null);
builder.create().show();
} else {
if (mDoubleBackToExit) {
// if mDoubleBackToExit is true, exit now
logout(true);
} else {
// set mDoubleBackToExit = true, and set delayed task to
// reset it to false
mDoubleBackToExit = true;
if (mHandler == null) {
mHandler = new Handler();
}
// reset will be run after 2000 ms
mHandler.postDelayed(new PendingDoubleBackToExit(), 2000);
Toast.makeText(this, "再按一次退出aSM", Toast.LENGTH_SHORT).show();
}
}
} else {
finishAndClean();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
int index = m_viewPager.getCurrentItem();
// get OnKeyDownListener by this position;
// if the fragment has implement the interface and not recycled, we
// will get valid listener
OnKeyDownListener listener = m_tabsAdapter.getOnKeyDownListener(index);
if (listener != null) {
return listener.onKeyDown(keyCode);
}
}
return super.onKeyDown(keyCode, event);
}
// http://stackoverflow.com/questions/4500354/control-volume-keys
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
// disable the beep sound when volume up/down is pressed
int index = m_viewPager.getCurrentItem();
OnKeyDownListener listener = m_tabsAdapter.getOnKeyDownListener(index);
if (listener != null) {
// only if we have valid listener
return true;
}
}
return super.onKeyUp(keyCode, event);
}
public static final int SETTING = Menu.FIRST;
public static final int REFRESH = Menu.FIRST + 1;
public static final int CLEAN = Menu.FIRST + 2;
public static final int ABOUT = Menu.FIRST + 3;
public static final int LOGOUT = Menu.FIRST + 4;
public static final int EXIT = Menu.FIRST + 5;
public static final int NIGHT_THEME = Menu.FIRST + 6;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// super.onCreateOptionsMenu(menu);
boolean isLight = aSMApplication.THEME == R.style.Theme_Sherlock_Light;
menu.add(0, CLEAN, Menu.NONE, "清除缓存").setIcon(isLight ? R.drawable.clean_inverse : R.drawable.clean)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, SETTING, Menu.NONE, "设置").setIcon(isLight ? R.drawable.setting_inverse : R.drawable.setting)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, REFRESH, Menu.NONE, "刷新").setIcon(isLight ? R.drawable.refresh_inverse : R.drawable.refresh)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, NIGHT_THEME, Menu.NONE, "光线模式")
.setIcon(isLight ? R.drawable.light_mode_inverse : R.drawable.light_mode)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, ABOUT, Menu.NONE, "关于").setIcon(isLight ? R.drawable.about_inverse : R.drawable.about)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, LOGOUT, Menu.NONE, "注销").setShowAsAction(
MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(0, EXIT, Menu.NONE, "退出").setShowAsAction(
MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case SETTING:
Intent intent = new Intent();
intent.setClassName("com.athena.asm", "com.athena.asm.SettingActivity");
startActivity(intent);
break;
case REFRESH:
int index = m_viewPager.getCurrentItem();
switch (index) {
case 0:
m_viewModel.setGuidanceSectionNames(null);
m_viewModel.setGuidanceSectionDetails(null);
m_viewModel.notifyGuidanceChanged();
break;
case 1:
boolean isDeleted = deleteFile("FavList");
if (isDeleted) {
m_viewModel.setFavList(null);
m_viewModel.notifyFavListChanged();
}
break;
case 2:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("耗时较长,确定吗?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean isDeleted = deleteFile("CategoryList");
if (isDeleted) {
m_viewModel.setCategoryList(null);
// tigger CategoryFragment: onViewModelChange ->
// reloadCategory
m_viewModel.notifyCategoryChanged();
}
}
});
builder.setNegativeButton("取消", null);
builder.create().show();
break;
case 3:
m_viewModel.setMailbox(null);
m_viewModel.notifyMailboxChanged();
break;
case 4:
m_viewModel.setCurrentProfile(null);
m_viewModel.notifyProfileChanged(null);
break;
default:
break;
}
break;
case NIGHT_THEME:
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
boolean b_night_theme = settings.getBoolean(Preferences.NIGHT_THEME, true);
SharedPreferences.Editor editor = settings.edit();
// change night_theme settings
if (b_night_theme) {
// switch to day mode
editor.putBoolean(Preferences.NIGHT_THEME, false);
editor.commit();
} else {
// switch to night mode
editor.putBoolean(Preferences.NIGHT_THEME, true);
editor.commit();
}
aSMApplication.getCurrentApplication().initPreferences();
// we destroy current activity, and create a new one
// it's a very heavy process and should be improved later
Intent tempIntent = getIntent();
// finish();
tempIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(tempIntent);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// actionbar might disappear in old system, sleep to solve this
// issue
SystemClock.sleep(500);
}
// show toast for the switch
if (b_night_theme) {
Toast.makeText(getApplicationContext(), "已切换至日光模式", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "已切换至夜间模式", Toast.LENGTH_SHORT).show();
}
break;
case CLEAN:
UrlImageViewHelper.cleanup(this, 0);
Toast.makeText(getApplicationContext(), "已清空图片缓存", Toast.LENGTH_SHORT).show();
break;
case ABOUT:
showInfoDialog();
break;
case LOGOUT:
logout(false);
break;
case EXIT:
if (m_viewModel.isLogined()) {
logout(true);
} else {
m_viewModel.logout();
exit();
}
break;
default:
break;
}
return true;
}
private static final int REQUESTCODE_POST_LIST = 1;
@Override
public void onOpenActivityOrFragment(String target, Bundle bundle) {
if (target.equals(ActivityFragmentTargets.POST_LIST)) {
Intent intent = new Intent();
intent.putExtras(bundle);
intent.setClassName("com.athena.asm", PostListActivity.class.getName());
startActivityForResult(intent, REQUESTCODE_POST_LIST);
} else if (target.equals(ActivityFragmentTargets.SUBJECT_LIST)) {
Intent intent = new Intent();
intent.putExtras(bundle);
intent.setClassName("com.athena.asm", SubjectListActivity.class.getName());
startActivity(intent);
} else if (target.equals(ActivityFragmentTargets.MAIL_LIST)) {
Intent intent = new Intent();
intent.putExtras(bundle);
intent.setClassName("com.athena.asm", MailListActivity.class.getName());
startActivity(intent);
} else if (target.equals(ActivityFragmentTargets.WRITE_POST)) {
Intent intent = new Intent();
intent.putExtras(bundle);
intent.setClassName("com.athena.asm", WritePostActivity.class.getName());
startActivity(intent);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == REQUESTCODE_POST_LIST) {
if (resultCode == RESULT_OK) {
String boardEngName = intent.getStringExtra("board_eng_name");
String boardChsName = intent.getStringExtra("board_chs_name");
if (boardEngName != null) {
Board board = new Board();
board.setEngName(boardEngName);
board.setChsName(boardChsName);
board.setCurrentPageNo(0);
// this will cause issue when
// 导读页面->帖子详情->回到版面->搜索->搜索结果->点击帖子 的内容无法显示
board.setBoardID("fake");
Intent newIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putSerializable(StringUtility.BOARD, board);
newIntent.putExtras(bundle);
newIntent.setClass(this, SubjectListActivity.class);
startActivity(newIntent);
}
}
}
}
@Override
public void onViewModelChange(BaseViewModel viewModel, String changedPropertyName, Object... params) {
if (changedPropertyName.equals(HomeViewModel.LOGIN_PROPERTY_NAME)) {
dismissProgressDialog();
int iLoginResult = (Integer) params[0];
loginTaskDone(iLoginResult);
}
}
private void showProgressDialog(String message) {
if (m_pdialog == null) {
m_pdialog = new ProgressDialog(this);
m_pdialog.setMessage(message);
m_pdialog.show();
}
}
private void dismissProgressDialog() {
if (m_pdialog != null) {
m_pdialog.cancel();
m_pdialog = null;
}
}
}