Java tutorial
/* * This file is part of LoLin1. * * LoLin1 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. * * LoLin1 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 LoLin1. If not, see <http://www.gnu.org/licenses/>. * * Created by Jorge Antonio Diaz-Benito Soriano. */ package org.jorge.cmp.ui.activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.net.ConnectivityManager; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.sothree.slidinguppanel.SlidingUpPanelLayout; import org.jorge.cmp.LoLin1Application; import org.jorge.cmp.R; import org.jorge.cmp.auth.LoLin1AccountAuthenticator; import org.jorge.cmp.chat.FriendManager; import org.jorge.cmp.datamodel.FeedArticle; import org.jorge.cmp.datamodel.LoLin1Account; import org.jorge.cmp.datamodel.Realm; import org.jorge.cmp.io.database.SQLiteDAO; import org.jorge.cmp.io.prefs.PreferenceAssistant; import org.jorge.cmp.service.ChatIntentService; import org.jorge.cmp.ui.adapter.ChatAdapter; import org.jorge.cmp.ui.adapter.NavigationDrawerAdapter; import org.jorge.cmp.ui.fragment.ArticleReaderFragment; import org.jorge.cmp.ui.fragment.CommunityListFragment; import org.jorge.cmp.ui.fragment.NavigationDrawerFragment; import org.jorge.cmp.ui.fragment.NewsListFragment; import org.jorge.cmp.ui.fragment.SchoolListFragment; import org.jorge.cmp.util.Interface; import org.jorge.cmp.util.PicassoUtils; import org.jorge.cmp.util.Utils; import java.util.Arrays; import java.util.Stack; import java.util.concurrent.Executors; public class MainActivity extends ActionBarActivity implements Interface.IOnFeedArticleClickedListener, NavigationDrawerAdapter.NavigationDrawerCallbacks { public static final String KEY_LOLIN1_ACCOUNT = "KEY_LOLIN1_ACCOUNT"; public static final String KEY_OPEN_CHAT = "KEY_OPEN_CHAT"; private Context mContext; private Fragment[] mContentFragments; private NavigationDrawerFragment mNavigationDrawerFragment; private Stack<Integer> mNavigatedIndexesStack; private LoLin1Account mAccount; private BroadcastReceiver mChatBroadcastReceiver; private Boolean mAlreadyInited = Boolean.FALSE; private View mLoginProgress; private ImageView mLoginStatus; private ChatAdapter mChatAdapter; private TextView mEmptyView; private String mTag = getClass().getName(); private SlidingUpPanelLayout mSlidingLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mNavigatedIndexesStack = new Stack<>(); mNavigatedIndexesStack.push(0); setContentView(R.layout.activity_main); final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); setSupportActionBar(toolbar); getSupportActionBar().setHomeButtonEnabled(Boolean.TRUE); mContext = LoLin1Application.getInstance().getContext(); mAccount = getIntent().getParcelableExtra(KEY_LOLIN1_ACCOUNT); final Boolean comesFromNotification; if (comesFromNotification = mAccount == null) mAccount = LoLin1AccountAuthenticator.loadAccount(mContext); mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager() .findFragmentById(R.id.navigation_drawer_fragment); setupNavigationDrawer(toolbar, mAccount); mSlidingLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout); mLoginProgress = findViewById(R.id.progress_bar); mLoginStatus = (ImageView) findViewById(R.id.login_status_image); final TextView chatActionView = (TextView) findViewById(R.id.chat_view_action); mSlidingLayout.setDragView(chatActionView); mSlidingLayout.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { @Override public void onPanelSlide(View view, float v) { //Unused } @Override public void onPanelCollapsed(View view) { MainActivity.this.mNavigationDrawerFragment.unlockDrawer(); chatActionView.setText(R.string.chat_view_action_expand); } @Override public void onPanelExpanded(View view) { MainActivity.this.mNavigationDrawerFragment.lockDrawerClosed(); chatActionView.setText(R.string.chat_view_action_collapse); } @Override public void onPanelAnchored(View view) { MainActivity.this.mNavigationDrawerFragment.lockDrawerClosed(); chatActionView.setText(R.string.chat_view_action_collapse); } @Override public void onPanelHidden(View view) { MainActivity.this.mNavigationDrawerFragment.unlockDrawer(); chatActionView.setText(R.string.chat_view_action_expand); } }); setupChatView(); if (!comesFromNotification) initChat(); else { mNavigationDrawerFragment.asyncLoadUserImage(mAccount); requestChatListRefresh(); showChatViewConnected(); } if (mContentFragments == null) showInitialFragment(); } private void setupChatView() { final RecyclerView chatRecyclerView = (RecyclerView) findViewById(R.id.chat_recycler_view); chatRecyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); chatRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); mEmptyView = (TextView) findViewById(android.R.id.empty); mChatAdapter = new ChatAdapter(mContext, mEmptyView, mTag); chatRecyclerView.setHasFixedSize(Boolean.FALSE); chatRecyclerView.setAdapter(mChatAdapter); chatRecyclerView.setItemAnimator(new DefaultItemAnimator()); } @Override public void onDestroy() { super.onDestroy(); PicassoUtils.cancel(mContext, mTag); } private void initChat() { final View thisView = findViewById(android.R.id.content); registerLocalBroadcastReceiver(); if (mAlreadyInited) { if (!Utils.isInternetReachable()) { thisView.post(new Runnable() { @Override public void run() { showChatViewNoConnection(); } }); } else { if (!ChatIntentService.isLoggedIn()) { thisView.post(new Runnable() { @Override public void run() { showChatViewLoading(); } }); runChat(); } else { thisView.post(new Runnable() { @Override public void run() { showChatViewConnected(); } }); } } return; } final Runnable viewRunnable; if (!Utils.isInternetReachable()) { viewRunnable = new Runnable() { @Override public void run() { showChatViewNoConnection(); } }; } else { viewRunnable = new Runnable() { @Override public void run() { showChatViewLoading(); } }; if (!ChatIntentService.isLoggedIn()) { runChat(); } } thisView.post(viewRunnable); if (getIntent().getBooleanExtra(KEY_OPEN_CHAT, Boolean.FALSE) && !mSlidingLayout.isPanelExpanded()) { mSlidingLayout.expandPanel(); } } private void showChatViewLoading() { mLoginStatus.setVisibility(View.GONE); mLoginStatus.setContentDescription(getString(R.string.chat_status_loading_content_description)); mLoginProgress.setVisibility(View.VISIBLE); mEmptyView.setText(getString(R.string.chat_friend_list_empty_loading)); } private void showChatViewConnected() { mLoginProgress.setVisibility(View.GONE); mLoginStatus.setVisibility(View.VISIBLE); mLoginStatus.setContentDescription(getString(R.string.chat_status_logged_in_content_description)); mLoginStatus.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_logged_in)); mEmptyView.setOnClickListener(null); mEmptyView.setText(getString(R.string.chat_friend_list_empty_no_online_friends)); } private void showChatViewNoConnection() { mLoginProgress.setVisibility(View.GONE); mLoginStatus.setVisibility(View.VISIBLE); mLoginStatus.setContentDescription(getString(R.string.chat_status_no_connection_content_description)); mLoginStatus.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_error)); mEmptyView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Utils.isInternetReachable() && !ChatIntentService.isLoggedIn()) { showChatViewLoading(); MainActivity.this.runChat(); } } }); mEmptyView.setText(getString(R.string.chat_friend_list_empty_no_connection)); } private void showChatViewWrongCredentials() { mLoginProgress.setVisibility(View.GONE); mLoginStatus.setVisibility(View.VISIBLE); mLoginStatus.setContentDescription(getString(R.string.chat_status_wrong_credentials_content_description)); mLoginStatus.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_warning)); mEmptyView.setOnClickListener(null); mEmptyView.setText(getString(R.string.chat_friend_list_empty_wrong_credentials)); } private void showInitialFragment() { if (mContentFragments == null) { mContentFragments = new Fragment[4]; } getSupportFragmentManager().beginTransaction() .replace(R.id.content_fragment_container, findNewsListFragment()).commitAllowingStateLoss(); } private Fragment findNewsListFragment() { if (mContentFragments[0] == null) mContentFragments[0] = NewsListFragment.newInstance(mContext, Realm.getInstanceByRealmId(mAccount.getRealmEnum())); return mContentFragments[0]; } private Fragment findCommunityListFragment() { if (mContentFragments[1] == null) mContentFragments[1] = CommunityListFragment.newInstance(mContext); return mContentFragments[1]; } private Fragment findSchoolListFragment() { if (mContentFragments[2] == null) mContentFragments[2] = SchoolListFragment.newInstance(mContext); return mContentFragments[2]; } private Fragment findChatFragment() { throw new UnsupportedOperationException("Not yet implemented."); } @Override public void onConfigurationChanged(Configuration newConfig) { if (getResources().getConfiguration().orientation != newConfig.orientation) { mNavigationDrawerFragment.selectItem(mNavigatedIndexesStack.peek()); mNavigatedIndexesStack.pop(); //Remove the element that was added because of the // call to selectItem } super.onConfigurationChanged(newConfig); } /** * Launches an article reader. * * @param article The article information. * @param c The class of the article list, so that the errorResId can be deducted * in the ArticleReaderFragment constructor. */ private void launchArticleReader(FeedArticle article, Class c) { //Link-type post auto-parsing if (article.getPreviewText().contentEquals("null")) { article.requestBrowseToAction(mContext); article.markAsRead(); final Class newsClass = NewsListFragment.class; final Class communityClass = CommunityListFragment.class; final Class schoolClass = SchoolListFragment.class; String tableName; final Realm r = Realm.getInstanceByRealmId(mAccount.getRealmEnum()); if (c == newsClass) { String l = PreferenceAssistant.readSharedString(mContext, PreferenceAssistant.PREF_LANG, null); if (l == null || !Arrays.asList(r.getLocales()).contains(l)) { l = r.getLocales()[0]; PreferenceAssistant.writeSharedString(mContext, PreferenceAssistant.PREF_LANG, l); } tableName = SQLiteDAO.getNewsTableName(r, l); } else if (c == communityClass) { tableName = SQLiteDAO.getCommunityTableName(); } else if (c == schoolClass) { tableName = SQLiteDAO.getSchoolTableName(); } else { throw new IllegalArgumentException( "Feed list fragment class " + c.getCanonicalName() + " not recognized."); } new AsyncTask<Object, Void, Void>() { @Override protected Void doInBackground(Object... params) { SQLiteDAO.getInstance().markArticleAsRead((FeedArticle) params[0], (String) params[1]); return null; } }.executeOnExecutor(Executors.newSingleThreadExecutor(), article, tableName); return; } Intent intent = new Intent(mContext, ArticleReaderActivity.class); intent.putExtra(ArticleReaderFragment.KEY_ARTICLE, article); intent.putExtra(ArticleReaderActivity.READER_LIST_FRAGMENT_CLASS, c); intent.putExtra(ArticleReaderFragment.KEY_ACCOUNT, mAccount); startActivity(intent); overridePendingTransition(R.anim.move_in_from_bottom, R.anim.move_out_to_bottom); } @Override public void onFeedArticleClicked(FeedArticle item, Class c) { launchArticleReader(item, c); } @Override public void onBackPressed() { Boolean handled = Boolean.FALSE; if (mNavigationDrawerFragment.isDrawerOpen()) { mNavigationDrawerFragment.closeDrawer(); handled = Boolean.TRUE; } if (!handled && mContentFragments != null && mContentFragments[mNavigatedIndexesStack.peek()] != null && mContentFragments[mNavigatedIndexesStack.peek()] instanceof Interface.IOnBackPressed) { handled = ((Interface.IOnBackPressed) mContentFragments[mNavigatedIndexesStack.peek()]).onBackPressed(); } if (!handled) { super.onBackPressed(); if (mNavigatedIndexesStack.size() > 1) { mNavigatedIndexesStack.pop(); mNavigationDrawerFragment.selectItem(mNavigatedIndexesStack.peek()); mNavigatedIndexesStack.pop(); //Remove the element that was added because of the // call to selectItem } else finish(); } } @Override public void onNavigationDrawerItemSelected(int position) { if (mNavigationDrawerFragment == null || mNavigationDrawerFragment.getPosition() == position) { return; } Fragment target; mNavigatedIndexesStack.push(position); switch (position) { case 0: target = findNewsListFragment(); break; case 1: target = findCommunityListFragment(); break; case 2: target = findSchoolListFragment(); break; case 3: target = findChatFragment(); break; default: throw new IllegalArgumentException("Menu with id " + position + " not found."); } final Fragment targetAsFinal = target; runOnUiThread(new Runnable() { @Override public void run() { getSupportFragmentManager().beginTransaction() .replace(R.id.content_fragment_container, targetAsFinal).addToBackStack(null) .commitAllowingStateLoss(); } }); } public void setupNavigationDrawer(Toolbar toolbar, LoLin1Account acc) { mNavigationDrawerFragment.setup(R.id.navigation_drawer_fragment, (DrawerLayout) findViewById(R.id.navigation_drawer), toolbar, acc); } private void runChat() { Intent intent = new Intent(mContext, ChatIntentService.class); if (ChatIntentService.isLoggedIn()) { stopService(intent); } Intent chatConnectIntent = new Intent(mContext, ChatIntentService.class); chatConnectIntent.setAction(ChatIntentService.ACTION_CONNECT); chatConnectIntent.putExtra(ChatIntentService.EXTRA_KEY_LOLIN1_ACCOUNT, mAccount); startService(chatConnectIntent); } private void registerLocalBroadcastReceiver() { if (mChatBroadcastReceiver != null) { return; } mChatBroadcastReceiver = new ChatOverviewBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(mContext.getString(R.string.event_login_failed)); intentFilter.addAction(mContext.getString(R.string.event_chat_overview)); intentFilter.addAction(mContext.getString(R.string.event_login_successful)); intentFilter.addAction(mContext.getString(R.string.event_message_received)); LocalBroadcastManager.getInstance(mContext).registerReceiver(mChatBroadcastReceiver, intentFilter); } private void stopChatService() { Intent chatDisconnectIntent = new Intent(mContext, ChatIntentService.class); chatDisconnectIntent.setAction(ChatIntentService.ACTION_DISCONNECT); startService(chatDisconnectIntent); mAlreadyInited = Boolean.FALSE; stopService(new Intent(mContext, ChatIntentService.class)); } private synchronized void requestChatListRefresh() { FriendManager.getInstance().updateOnlineFriends(); mChatAdapter.notifyFriendSetChanged(); } public class ChatOverviewBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, final Intent intent) { String action = intent.getAction(); if (action.contentEquals(context.getString(R.string.event_chat_overview))) { MainActivity.this.requestChatListRefresh(); } else { final View thisView = findViewById(android.R.id.content); if (action.contentEquals(ConnectivityManager.CONNECTIVITY_ACTION)) { if (!Utils.isInternetReachable()) { thisView.post(new Runnable() { @Override public void run() { MainActivity.this.requestChatListRefresh(); showChatViewNoConnection(); } }); if (ChatIntentService.isLoggedIn()) { stopChatService(); } } else { MainActivity.this.runChat(); } } else if (action.contentEquals(context.getString(R.string.event_login_failed))) { thisView.post(new Runnable() { @Override public void run() { showChatViewWrongCredentials(); } }); if (ChatIntentService.isLoggedIn()) { stopChatService(); } } else if (action.contentEquals(context.getString(R.string.event_login_successful))) { MainActivity.this.mAlreadyInited = Boolean.TRUE; thisView.post(new Runnable() { @Override public void run() { mNavigationDrawerFragment.asyncLoadUserImage(mAccount); requestChatListRefresh(); showChatViewConnected(); } }); } } } } }