package com.masterofcode.android.magreader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.kroz.activerecord.ActiveRecordBase;
import org.kroz.activerecord.ActiveRecordException;
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SearchView;
import com.masterofcode.android.magreader.adapters.ListOfCategoriesAdapter;
import com.masterofcode.android.magreader.application.JtjApplication;
import com.masterofcode.android.magreader.db.entity.FeedItem;
import com.masterofcode.android.magreader.db.entity.FeedType;
import com.masterofcode.android.magreader.fragments.FeedsCategoriesFragment;
import com.masterofcode.android.magreader.fragments.FeedsListFragment;
import com.masterofcode.android.magreader.library.LibraryManager;
import com.masterofcode.android.magreader.service.GetFeedsService;
import com.masterofcode.android.magreader.utils.ActionBarView;
import com.masterofcode.android.magreader.utils.ApplicationUtils;
import com.masterofcode.android.magreader.utils.FeedsListProvider;
import com.masterofcode.android.magreader.utils.RestClient;
import com.masterofcode.android.magreader.utils.SaveToDbQueue;
import com.masterofcode.android.magreader.utils.constants.Constants;
import com.sandsmedia.apps.mobile.android.epub.lib.R;
public class MainActivity extends Activity {
/**
* Called when the activity is first created.
*/
private static Context mContext;
private ActionBar actionBar;
private int mCurrentPosition = 0;
private PopulateFeedsAsyncTask feedTask = new PopulateFeedsAsyncTask();
private List<FeedType> feedTypes = null;
private boolean isFirstRun = false;
private ActiveRecordBase database;
private RelativeLayout feedsHintLayout;
protected boolean feedsAddHintIsShowed = false;
protected boolean feedsHintDisabled = false;
private static MainActivity instance;
static class Self {
public Self() {
}
public GetFeedsService mBoundService;
public ServiceConnection updateConnection;
}
Self _self = new Self();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("noInetException", "in onCreate, MainActivity");
setContentView(R.layout.main);
instance = this;
// feeds hint hide
feedsHintLayout = (RelativeLayout) findViewById(R.id.included_feeds_hint);
feedsHintLayout.setVisibility(View.GONE);
isFirstRun = true;
feedsHintDisabled = ApplicationUtils.getPrefPropertyBoolean(this, Constants.PREFERENCES_PROPERTY_SHOW_FEEDS_HINT_DISABLED, false);
if (savedInstanceState != null) {
setCurrentPosition(savedInstanceState.getInt("currentPosition"));
}
this.mContext = this;
database = ((JtjApplication) ((MainActivity) mContext).getApplication()).getDatabase();
ApplicationUtils.setPrefProperty(mContext, Constants.DATE_FEEDS_UPDATE, new SimpleDateFormat("dd MMMMMMMMMMMMM yyyy, HH:mm").format(new Date()));
this.actionBar = getActionBar();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
actionBar.setListNavigationCallbacks(ArrayAdapter.createFromResource(this, R.array.menu_categories,
android.R.layout.simple_dropdown_item_1line), navigationListener);
ActionBarView.setActionBarListView(actionBar, mContext);
actionBar.setSelectedNavigationItem(0);
} else {
actionBar.addTab(actionBar.newTab().setText(R.string.action_bar_feeds).setTabListener(feedsTabListener), true);
actionBar.addTab(actionBar.newTab().setText(R.string.action_bar_library).setTabListener(libraryTabListener), false);
actionBar.addTab(actionBar.newTab().setText(R.string.action_bar_shop).setTabListener(shopTabListener), false);
actionBar.addTab(actionBar.newTab().setText(R.string.action_bar_bookmarks).setTabListener(bookmarkTabListener), false);
ActionBarView.setActionBarTabView(actionBar, mContext);
}
Log.i("feed_prov", getActionBar().toString());
if(ApplicationUtils.isOnline(MainActivity.this)){
new Thread(new Runnable() {
public void run() {
if (ApplicationUtils.checkIssueIsAvail()){
feedTask.execute(mCurrentPosition);
// set up service
doInitUpdateConnection();
} else {
MainActivity.this.runOnUiThread(new Runnable() {
public void run()
{
noInternetShowDialog();
}
});
}
}
}).start();
} else{
noInternetShowDialog();
}
LibraryManager.GetInstance().copyCoversFromRes(mContext);
}
@Override
protected void onResume() {
super.onResume();
Log.d("noInetException", "in onResume, MainActivity... isFirstRun = " + isFirstRun);
if (!isFirstRun) {
Log.d("noInetException", "in onResume, before call updateAdapter ");
updateAdapters();
}
Log.d("noInetException", "in onResume, after call updateAdapter ");
isFirstRun = false;
}
@Override
protected void onPause() {
super.onPause();
Log.d("noInetException", "in onPause");
}
@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
public int getCurrentPosition() {
return mCurrentPosition;
}
public void setCurrentPosition(int mCurrentPosition) {
this.mCurrentPosition = mCurrentPosition;
}
OnNavigationListener navigationListener = new OnNavigationListener() {
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
switch (itemPosition) {
case 1:
Intent libraryIntent = new Intent();
libraryIntent.setClass(mContext, MainLibraryActivity.class);
startActivity(libraryIntent);
finish();
break;
case 2:
Intent shopIntent = new Intent();
shopIntent.setClass(mContext, MainShopActivity.class);
startActivity(shopIntent);
finish();
break;
case 3:
Intent bookmarkIntent = new Intent();
bookmarkIntent.setClass(mContext, MainBookmarkActivity.class);
startActivity(bookmarkIntent);
finish();
break;
}
return false;
}
};
TabListener feedsTabListener = new TabListener() { //for this tab we have empty tabListener
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
TabListener libraryTabListener = new TabListener() {
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Intent libraryIntent = new Intent();
libraryIntent.setClass(mContext, MainLibraryActivity.class);
startActivity(libraryIntent);
finish();
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
TabListener shopTabListener = new TabListener() {
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Intent shopIntent = new Intent();
shopIntent.setClass(mContext, MainShopActivity.class);
startActivity(shopIntent);
finish();
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
TabListener bookmarkTabListener = new TabListener() {
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Intent bookmarkIntent = new Intent();
bookmarkIntent.setClass(mContext, MainBookmarkActivity.class);
startActivity(bookmarkIntent);
finish();
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
};
private class PopulateFeedsAsyncTask extends AsyncTask<Integer, Void, JSONArray> {
private int mCurrentPosition = 0;
List<FeedType> feedTypes;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected JSONArray doInBackground(Integer... params) {
this.mCurrentPosition = params[0];
JSONArray remoteFeeds = RestClient.connect(Constants.FEEDS_LIST_URL);
return remoteFeeds;
}
@Override
protected void onPostExecute(JSONArray remoteFeeds) {
int length = 0;
try {
if (!database.isOpen()) database.open();
feedTypes = database.findAll(FeedType.class);//database.find(FeedType.class, "ISHIDE=?", new String [] { String.valueOf(false) });
length = feedTypes.size();
} catch (ActiveRecordException e) {
e.printStackTrace();
}
if(remoteFeeds!=null) // prevent crashing if no inet
{
if (remoteFeeds.length() != length) {
try {
String[] args = new String[1];
args[0]="0";
length = database.delete(FeedType.class,"_id>?",args);
} catch (ActiveRecordException e) {
e.printStackTrace();
}
for (int i = 0; i < remoteFeeds.length(); i++) {
JSONObject currentObject = remoteFeeds.optJSONObject(i);
try {
FeedType ft = new FeedType(currentObject.getString("name"), currentObject.getString("url"), "en_EN", i + 1, 0);
if (currentObject.has(Constants.FEEDS_JSON_ATTRIBUTES_DEFAULT)) {
boolean isDefaultFromJSON = currentObject.getBoolean(Constants.FEEDS_JSON_ATTRIBUTES_DEFAULT);
Log.i("feed_prov -> is default: ", new Boolean(isDefaultFromJSON).toString());
ft.is_default = isDefaultFromJSON;
ft.is_hide = !ft.is_default;
}
FeedsListProvider.getInstance(database).addFeedType(ft);
feedTypes.add(ft);
Log.i("feed_prov", "URL is added");
} catch (JSONException e) {
Log.e("feed_prov", "Invalid JSON");
}
}
try {
if (!database.isOpen()) database.open();
if (database.isOpen()) feedTypes = database.findAll(FeedType.class);
length = feedTypes.size();
} catch (ActiveRecordException e) {
e.printStackTrace();
}
}
}
try {
feedTypes = updateUnreadCount(feedTypes);
MainActivity.this.setFeedTypes(MainActivity.this.feedTypes);
FeedsCategoriesFragment categoriesFragment = (FeedsCategoriesFragment) getFragmentManager().findFragmentById(R.id.feed_categories_fragment);
categoriesFragment.setListAdapter(new ListOfCategoriesAdapter(mContext, R.layout.list_categories, feedTypes));
ListView lv = categoriesFragment.getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setCacheColorHint(Color.WHITE);
showAddFeedsHint(feedTypes);
//startService(new Intent(GetFeedsService.class.getName()));
//doBindService();
if (GetFeedsService.getInstance() != null) {
doBindService();
} else {
startService(new Intent(mContext, GetFeedsService.class));
doBindService();
}
if(remoteFeeds!=null) // prevent crashing if no inet
categoriesFragment.setPosition(mCurrentPosition);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public List<FeedType> updateUnreadCount(List<FeedType> feedTypes) {
for (FeedType feedType:feedTypes) {
try {
if (!database.isOpen()) database.open();
List<FeedItem> fil = database.find(FeedItem.class, "CHANNELID=? AND IS_READ=?", new String[] {String.valueOf(feedType.order_id), String.valueOf(false)});
feedType.unread_count = fil.size();
SaveToDbQueue.saveToDbAsyncQueue(null, feedType);//feedType.update();
if (!feedType.title.equals(Constants.FEED_ALL_NAME) && !feedType.title.equals(Constants.FEED_NEWS_NAME) && !feedType.title.equals(Constants.FEED_VIDEOS_NAME)) {
((JtjApplication) ((MainActivity) mContext).getApplication()).addFeedsToManageArray(feedType);
}
} catch (ActiveRecordException e) {
e.printStackTrace();
}
}
try {
feedTypes = database.find(FeedType.class, "ISHIDE=?", new String [] { String.valueOf(false) });
} catch (ActiveRecordException e) {
e.printStackTrace();
}
return feedTypes;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentPosition", mCurrentPosition);
}
public static class FeedsBroadcastListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
try {
if (action.equals(Constants.UPDATE_FEEDS)) {
ActiveRecordBase database = ((JtjApplication) ((MainActivity) mContext).getApplication()).getDatabase();
List<FeedType> feedTypes = null;
try {
database.open();
feedTypes = database.find(FeedType.class, "ISHIDE=?", new String [] { String.valueOf(false) });
} catch (ActiveRecordException e) {
e.printStackTrace();
}
feedTypes = ((MainActivity) mContext).updateUnreadCount(feedTypes);
FeedsCategoriesFragment categoriesFragment = (FeedsCategoriesFragment) ((MainActivity) mContext).getFragmentManager().findFragmentById(R.id.feed_categories_fragment);
categoriesFragment.setListAdapter(new ListOfCategoriesAdapter(mContext, R.layout.list_categories, feedTypes));
ListView lv = categoriesFragment.getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setCacheColorHint(Color.WHITE);
categoriesFragment.setPosition(((MainActivity) mContext).getmCurrentPosition());
ApplicationUtils.setPrefProperty(mContext, Constants.DATE_FEEDS_UPDATE, new SimpleDateFormat("dd MMMMMMMMMMMMM yyyy, HH:mm").format(new Date()));
((MainActivity) mContext).getActionBar().setSubtitle("Last Update: " + ApplicationUtils.getPreferences(context).getString(Constants.DATE_FEEDS_UPDATE, null));
}
} catch(Exception e){
e.printStackTrace();
}
}
}
public void updateAdapters() {
Log.d("noInetException", "in updateAdapters");
List<FeedType> feedTypes = null;
try {
if (!database.isOpen()) database.open();
feedTypes = database.find(FeedType.class, "ISHIDE=?", new String [] { String.valueOf(false) });//database.findAll(FeedType.class);
} catch (ActiveRecordException e) {
e.printStackTrace();
}
feedTypes = updateUnreadCount(feedTypes);
if (feedTypes.size() <= mCurrentPosition) {
mCurrentPosition = 0;
}
FeedsCategoriesFragment categoriesFragment = (FeedsCategoriesFragment) getFragmentManager().findFragmentById(R.id.feed_categories_fragment);
categoriesFragment.setListAdapter(new ListOfCategoriesAdapter(mContext, R.layout.list_categories, feedTypes));
ListView lv = categoriesFragment.getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setCacheColorHint(Color.WHITE);
categoriesFragment.setPosition(mCurrentPosition);
showAddFeedsHint(feedTypes);
Log.d("noInetException", "in updateAdapters, end");
}
private void showAddFeedsHint(List<FeedType> feedTypes)
{
if(feedsHintDisabled) return;
if(feedTypes.size() > Constants.CONSTANT_FEEDS_COUNT)
{
if(feedsAddHintIsShowed)return; // no need to show again
// animation
Animation anim_in = AnimationUtils.loadAnimation(this, R.anim.feeds_hint_in);
anim_in.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
feedsAddHintIsShowed = true;
feedsHintLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Log.i("-----", "click");
Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
intent.putExtra(Constants.BUNDLE_KEY_SETTINGS_SELECT_FEEDS, true);
startActivityForResult(intent, Constants.SETTINGS_ACTIVITY);
}
});
}
});
feedsHintLayout.startAnimation(anim_in);
feedsHintLayout.setVisibility(View.VISIBLE);
} else {
if(feedsAddHintIsShowed) // no need to hide if is already hided
{
/* // animation
Animation anim_out = AnimationUtils.loadAnimation(this, R.anim.feeds_hint_out);
anim_out.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
feedsAddHintIsShowed = false;
}
});
feedsHintLayout.startAnimation(anim_out);
*/
feedsHintLayout.setOnClickListener(null);
feedsHintLayout.setVisibility(View.GONE);
feedsAddHintIsShowed = false;
feedsHintDisabled = true;
ApplicationUtils.setPrefProperty(mContext, Constants.PREFERENCES_PROPERTY_SHOW_FEEDS_HINT_DISABLED, feedsHintDisabled);
}
}
}
void doInitUpdateConnection(){
if (_self.updateConnection == null)
_self.updateConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has
// been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a
// explicit
// service that we know is running in our own process, we
// can
// cast its IBinder to a concrete class and directly access
// it.
_self.mBoundService = ((GetFeedsService.Controller) service)
.getService();
// Refresh UI
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has
// been
// unexpectedly disconnected -- that is, its process
// crashed.
// Because it is running in our same process, we should
// never
// see this happen.
_self.mBoundService = null;
}
};
}
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
if (_self.updateConnection == null)
doInitUpdateConnection();
bindService(new Intent(MainActivity.this, GetFeedsService.class),
_self.updateConnection, Context.BIND_AUTO_CREATE);
}
void doUnbindService() {
if (_self.mBoundService != null) {
// Detach our existing connection.
try {
if(_self.updateConnection != null)
unbindService(_self.updateConnection);
} catch (IllegalArgumentException e) {
Log.e(Constants.LOG_BS, "unbindService failed!", e);
}
_self.mBoundService = null;
}
}
public List<FeedType> getFeedTypes() {
return feedTypes;
}
public void setFeedTypes(List<FeedType> feedTypes) {
this.feedTypes = feedTypes;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (MainActivity.this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
getMenuInflater().inflate(R.menu.feed_main_menu, menu);
} else {
getMenuInflater().inflate(R.menu.feed_main_menu_vertical, menu);
}
//search
final SearchView searchView = (SearchView) menu.findItem(R.id.menu_feed_search).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
searchView.setIconified(true);
Intent intent = new Intent(MainActivity.this, SearchActivity.class);
intent.putExtra(Constants.BUNDLE_KEY_SEARCH_KEYWORD, query);
intent.putExtra(Constants.BUNDLE_KEY_SEARCH_TYPE, Constants.SEARCH_TYPE_FEEDS);
startActivity(intent);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_mark_as_read) {
new UpdateUnreadCountAsyncTask().execute();
return true;
}
else if (itemId == R.id.menu_feed_settings) {
startActivityForResult(new Intent(MainActivity.this, SettingsActivity.class), Constants.SETTINGS_ACTIVITY);
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Constants.SETTINGS_ACTIVITY:
if (resultCode == RESULT_OK) {
//_self.mBoundService.onRebind(data);//sendBroadcast(data);//onStart(data, resultCode);
doUnbindService();
stopService(new Intent(mContext, GetFeedsService.class));
doBindService();
startService(new Intent(mContext, GetFeedsService.class).putExtra(Constants.FEEDS_TO_UPDATE, data.getIntegerArrayListExtra(Constants.FEEDS_TO_UPDATE)));
}
}
}
public void reloadService(Intent data){
doUnbindService();
stopService(new Intent(mContext, GetFeedsService.class));
doBindService();
startService(new Intent(mContext, GetFeedsService.class).putExtra(Constants.FEEDS_TO_UPDATE, data.getIntegerArrayListExtra(Constants.FEEDS_TO_UPDATE)));
}
public static MainActivity getInstance() {
return instance;
}
private void noInternetShowDialog(){
ApplicationUtils.createNoInternetDialog(MainActivity.this).show();
updateAdapters();
((FeedsCategoriesFragment) getFragmentManager().findFragmentById(R.id.feed_categories_fragment)).setListShown(true);
((FeedsListFragment) getFragmentManager().findFragmentById(R.id.feed_list_fragment)).setItemsForCategories(1);
}
private class UpdateUnreadCountAsyncTask extends AsyncTask<Void, Void, Void> {
List<FeedType> lft;
FeedType ft;
FeedsCategoriesFragment categoriesFragment;
FeedsListFragment listFragment;
public UpdateUnreadCountAsyncTask() {
this.categoriesFragment = (FeedsCategoriesFragment) getFragmentManager().findFragmentById(R.id.feed_categories_fragment);
this.listFragment = (FeedsListFragment) getFragmentManager().findFragmentById(R.id.feed_list_fragment);
try {
this.lft = database.find(FeedType.class, "ISHIDE=?", new String [] { String.valueOf(false) });//findAll(FeedType.class);
ft = lft.get(mCurrentPosition);
} catch (ActiveRecordException e) {
e.printStackTrace();
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
this.categoriesFragment.setListShown(false);
this.listFragment.setListShown(false);
}
@Override
protected Void doInBackground(Void... params) {
try {
if (!database.isOpen()) database.open();
List<FeedItem> lfi = database.find(FeedItem.class, "CHANNELID=?", new String[] {String.valueOf(ft.order_id)});
for (FeedItem fi:lfi) {
List<FeedItem> lfiToUpdateWithGuid = database.find(FeedItem.class, "GUID=?", new String[] {fi.guid});
for (FeedItem item:lfiToUpdateWithGuid) {
if (!item.isRead) {
item.isRead = true;
SaveToDbQueue.saveToDbAsyncQueue(item, null);//item.update();
}
}
}
} catch (ActiveRecordException e) {
e.printStackTrace();
}
lft = updateUnreadCount(lft);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
this.categoriesFragment.setListAdapter(new ListOfCategoriesAdapter(mContext, R.layout.list_categories, lft));
ListView lv = this.categoriesFragment.getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setCacheColorHint(Color.WHITE);
this.categoriesFragment.setPosition(mCurrentPosition);
this.categoriesFragment.setListShown(true);
}
}
public int getmCurrentPosition() {
return mCurrentPosition;
}
}