Java tutorial
/* * Copyright 2012 Feedlr * * 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.chalmers.feedlr.activity; import java.util.ArrayList; import com.chalmers.feedlr.R; import com.chalmers.feedlr.adapter.PageAdapter; import com.chalmers.feedlr.adapter.UserAdapter; import com.chalmers.feedlr.client.Clients; import com.chalmers.feedlr.client.ClientHandler; import com.chalmers.feedlr.database.DatabaseHelper; import com.chalmers.feedlr.service.DataServiceHelper; import com.chalmers.feedlr.listener.AuthListener; import com.chalmers.feedlr.listener.FeedListener; import com.chalmers.feedlr.model.Feed; import com.viewpagerindicator.CirclePageIndicator; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Typeface; import android.support.v4.app.FragmentActivity; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.ViewPager; import android.support.v4.widget.CursorAdapter; import android.util.Log; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.ViewAnimator; import android.widget.ViewFlipper; /** * FeedActivity is the activity in which almost all parts of the application is * run. This is the default activity. */ public class FeedActivity extends FragmentActivity implements FeedListener { private DataServiceHelper feedService; private ClientHandler clientHandler; private DatabaseHelper db; // Twitter strings public static final String TWITTER_USERS_UPDATED = "com.chalmers.feedlr.TWITTER_USERS_UPDATED"; public static final String TWITTER_USERS_PROBLEM_UPDATING = "com.chalmers.feedlr.TWITTER_USERS_PROBLEM_UPDATING"; // Facebook strings public static final String FACEBOOK_TIMELINE_UPDATED = "com.chalmers.feedlr.FACEBOOK_TIMELINE_UPDATED"; public static final String FACEBOOK_USERS_UPDATED = "com.chalmers.feedlr.FACEBOOK_USERS_UPDATED"; public static final String FACEBOOK_USERS_PROBLEM_UPDATING = "com.chalmers.feedlr.FACEBOOK_USERS_PROBLEM_UPDATING"; public static final String FACEBOOK_USER_NEWS_UPDATED = "com.chalmers.feedlr.FACEBOOK_USER_NEWS_UPDATED"; public static final String FEED_UPDATED = "com.chalmers.feedlr.FEED_UPDATED"; public static final String FEED_PROBLEM_UPDATING = "com.chalmers.feedlr.FEED_PROBLEM_UPDATING"; public static final String NO_CONNECTION = "com.chalmers.feedlr.NO_CONNECTION"; // Android system helpers private Resources res; private LocalBroadcastManager lbm; private LayoutInflater inflater; private IntentFilter intentFilter; // Adapters private PageAdapter feedAdapter; private UserAdapter userAdapter; // Views private ViewFlipper mainViewFlipper; private ViewPager feedViewSwiper; private ViewAnimator settingsViewFlipper; private ListView userListView; private LinearLayout userListLayout; private Button facebookAuthButton; private Button twitterAuthButton; private TextView feedTitleTextView; // Animations private Animation slideOutLeft; private Animation slideOutRight; private Animation slideInLeft; private Animation slideInRight; private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String broadcast = intent.getAction(); if (broadcast.equals(TWITTER_USERS_UPDATED)) { userAdapter.swapCursor(db.getAllUsers()); } else if (broadcast.equals(FACEBOOK_USERS_UPDATED)) { userAdapter.swapCursor(db.getAllUsers()); } else if (broadcast.equals(TWITTER_USERS_PROBLEM_UPDATING)) { Toast.makeText(context, "The was a problem refreshing your twitter friends. Please check your connection and try again.", Toast.LENGTH_SHORT).show(); } else if (broadcast.equals(FACEBOOK_USERS_PROBLEM_UPDATING)) { Toast.makeText(context, "The was a problem refreshing your facebook friends. Please check your connection and try again.", Toast.LENGTH_SHORT).show(); } else if (broadcast.equals(FEED_PROBLEM_UPDATING)) { Toast.makeText(context, "The was a problem refreshing the feed. Please check your connection and try again.", Toast.LENGTH_SHORT).show(); } else { Log.wtf(getClass().getName(), "broadcast from unknown intent recieved!"); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_view_flipper); // get helpers from android system res = getResources(); lbm = LocalBroadcastManager.getInstance(this); inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); // add intent filter to be used by broadcast reciever intentFilter = new IntentFilter(); intentFilter.addAction(TWITTER_USERS_UPDATED); intentFilter.addAction(TWITTER_USERS_PROBLEM_UPDATING); intentFilter.addAction(FACEBOOK_TIMELINE_UPDATED); intentFilter.addAction(FACEBOOK_USERS_UPDATED); intentFilter.addAction(FACEBOOK_USERS_PROBLEM_UPDATING); intentFilter.addAction(FACEBOOK_USER_NEWS_UPDATED); intentFilter.addAction(FEED_PROBLEM_UPDATING); // instanciate database helper db = new DatabaseHelper(this); // load typefaces from assets Typeface robotoMedium = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Medium.ttf"); // find views inflated from xml mainViewFlipper = (ViewFlipper) findViewById(R.id.main_view_flipper); feedViewSwiper = (ViewPager) findViewById(R.id.feed_view_pager); settingsViewFlipper = (ViewAnimator) findViewById(R.id.settings_view_flipper); facebookAuthButton = (Button) findViewById(R.id.button_facebook); twitterAuthButton = (Button) findViewById(R.id.button_twitter); Button cfb = (Button) findViewById(R.id.button_create_feed); Button s = (Button) findViewById(R.id.button_settings); settingsViewFlipper.getBackground().setDither(true); feedTitleTextView = (TextView) findViewById(R.id.feed_action_bar_title); // Set typefaces manually since Android can't handle custom typefaces in // xml in any way whatsoever. Shame on them. twitterAuthButton.setTypeface(robotoMedium); facebookAuthButton.setTypeface(robotoMedium); feedTitleTextView = (TextView) findViewById(R.id.feed_action_bar_title); cfb.setTypeface(robotoMedium); s.setTypeface(robotoMedium); feedTitleTextView.setTypeface(robotoMedium); // set adapters feedAdapter = new PageAdapter(getSupportFragmentManager(), db, this); feedViewSwiper.setAdapter(feedAdapter); // lets 3 feedsviews to each side of the current one be retained in an // idle state. feedViewSwiper.setOffscreenPageLimit(3); CirclePageIndicator circleIndicator = (CirclePageIndicator) findViewById(R.id.indicator); circleIndicator.setViewPager(feedViewSwiper); circleIndicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int feedIndex) { String feedTitle = feedAdapter.getFeedTitle(feedIndex); feedTitleTextView.setText(feedTitle); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub' } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } }); // instanciate client and service helpers clientHandler = new ClientHandler(this); feedService = new DataServiceHelper(this); feedService.startService(); // load animations from res/anim slideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left); slideOutRight = AnimationUtils.loadAnimation(this, R.anim.slide_out_right); slideInLeft = AnimationUtils.loadAnimation(this, R.anim.slide_in_left); slideInRight = AnimationUtils.loadAnimation(this, R.anim.slide_in_right); // Display name correct if (feedAdapter.getCount() > 0) { String feedTitle = feedAdapter.getFeedTitle(0); feedTitleTextView.setText(feedTitle); } // misc settingsViewFlipper.setInAnimation(slideInRight); settingsViewFlipper.setOutAnimation(slideOutLeft); updateOverlay(); } @Override protected void onDestroy() { feedService.stopService(); super.onDestroy(); } @Override protected void onStart() { super.onStart(); feedService.bindService(); } @Override protected void onStop() { feedService.unbindService(); super.onStop(); } @Override protected void onResume() { super.onResume(); boolean isFacebookAuthorized = Clients.isAuthorized(Clients.FACEBOOK, this); facebookAuthButton.setText(isFacebookAuthorized ? res.getString(R.string.facebook_authorized) : res.getString(R.string.authorize_facebook)); facebookAuthButton.setEnabled(!isFacebookAuthorized); if (isFacebookAuthorized) { facebookAuthButton.setTextColor(Color.parseColor("#919191")); facebookAuthButton.setBackgroundResource(R.drawable.facebook_logo_disabled); } boolean isTwitterAuthorized = Clients.isAuthorized(Clients.TWITTER, this); twitterAuthButton.setText(isTwitterAuthorized ? res.getString(R.string.twitter_authorized) : res.getString(R.string.authorize_twitter)); twitterAuthButton.setEnabled(!isTwitterAuthorized); if (isTwitterAuthorized) { twitterAuthButton.setTextColor(Color.parseColor("#919191")); twitterAuthButton.setBackgroundResource(R.drawable.twitter_logo_disabled); } lbm.registerReceiver(receiver, intentFilter); // facebook kittens will die if this isn't called onResume clientHandler.extendFacebookAccessTokenIfNeeded(); } @Override protected void onPause() { lbm.unregisterReceiver(receiver); super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.feed_layout, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_settings: toggleSettingsView(null); break; case R.id.menu_exit: finish(); break; } return true; } @Override public void onBackPressed() { // TODO: Toggle animation for the create feed view. Currently sliding // away in the wring direction. if (mainViewFlipper.getCurrentView().getId() == R.id.settings_layout) { if (settingsViewFlipper.getCurrentView().getId() == R.id.user_list_layout) { settingsViewFlipper.showPrevious(); } else { toggleSettingsView(null); } } else { super.onBackPressed(); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { switch (requestCode) { case Clients.TWITTER: clientHandler.onTwitterAuthCallback(data); break; case Clients.FACEBOOK: clientHandler.onFacebookAuthCallback(requestCode, resultCode, data); break; default: Log.wtf(getClass().getName(), "Result callback from unknown intent"); } } } @Override public void onFeedUpdateRequest(String feedTitle) { if (isOnline()) { feedService.updateFeed(new Feed(feedTitle)); } else { Intent intent = new Intent(); intent.setAction(NO_CONNECTION); lbm.sendBroadcast(intent); } } public boolean isOnline() { ConnectivityManager cm; NetworkInfo info = null; try { cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); info = cm.getActiveNetworkInfo(); } catch (Exception e) { Log.e("Check connection", e.getMessage()); } if (info != null) { return info.isConnected(); } else { return false; } } // Methods called on button press below. See xml files. public void toggleSettingsView(View v) { int currentView = mainViewFlipper.getCurrentView().getId(); if (currentView == R.id.main_layout) { mainViewFlipper.setInAnimation(slideInLeft); mainViewFlipper.setOutAnimation(slideOutRight); mainViewFlipper.showNext(); } else { mainViewFlipper.setInAnimation(slideInRight); mainViewFlipper.setOutAnimation(slideOutLeft); mainViewFlipper.showPrevious(); } } public void initCreateFeedView(View v) { userListLayout = (LinearLayout) inflater.inflate(R.layout.user_list_layout, null); userListView = (ListView) userListLayout.findViewById(R.id.user_list_view); if (isOnline()) { feedService.updateUsers(); } else { Intent intent = new Intent(); intent.setAction(NO_CONNECTION); lbm.sendBroadcast(intent); } Cursor cursor = db.getAllUsers(); String[] columns = new String[] { DatabaseHelper.USER_COLUMN_USERNAME, DatabaseHelper.USER_COLUMN_USERID, DatabaseHelper.USER_COLUMN_SOURCE }; int[] to = new int[] { R.id.user_item_text_view }; userAdapter = new UserAdapter(this, R.layout.user_list_item, cursor, columns, to, CursorAdapter.NO_SELECTION); userListView.setAdapter(userAdapter); settingsViewFlipper.addView(userListLayout); settingsViewFlipper.showNext(); } public void createFeed(View button) { // Animate switch to main view toggleSettingsView(null); // Extract new feed title EditText titleEditText = (EditText) userListLayout.findViewById(R.id.create_feed_action_bar_title); String feedTitle = titleEditText.getText().toString(); Feed feed = new Feed(feedTitle); // Extract new feed users SparseBooleanArray checked = userListView.getCheckedItemPositions(); ArrayList<Integer> userIDs = new ArrayList<Integer>(); UserAdapter adapter = (UserAdapter) userListView.getAdapter(); Cursor c; for (int i = 0; i < adapter.getCount(); i++) { if (checked.get(i)) { c = (Cursor) adapter.getItem(i); userIDs.add(c.getInt(c.getColumnIndex(DatabaseHelper.USER_COLUMN_USERID))); } } // Save user list as a feed in database db.addFeed(feed); long feed_id = db.getFeed_id(feed); for (Integer i : userIDs) db.addFeedUserBridge(feed_id, i); Log.i(getClass().getName(), "Added feed \"" + feed.getTitle() + "\" with " + userIDs.size() + " users."); // Hide keyboard InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(titleEditText.getWindowToken(), 0); // Animate switch to new feed view this.feedAdapter.addFeed(feed); feedViewSwiper.setCurrentItem(adapter.getCount()); feedTitleTextView.setText(feed.getTitle()); // Remove the createFeedView View v = settingsViewFlipper.getCurrentView(); settingsViewFlipper.showPrevious(); settingsViewFlipper.removeView(v); userListLayout = null; userListView = null; // Check overlay updateOverlay(); } private void updateOverlay() { if (feedAdapter.getCount() > 0) { LinearLayout overlayLayout = (LinearLayout) mainViewFlipper.findViewById(R.id.main_layout); ImageView overlay = (ImageView) overlayLayout.findViewById(R.id.no_feed_image); overlay.setVisibility(View.INVISIBLE); } } public void authorizeTwitter(View v) { if (!isOnline()) { return; } clientHandler.authorize(Clients.TWITTER, new AuthListener() { @Override public void onAuthorizationComplete() { twitterAuthButton.setText(res.getString(R.string.twitter_authorized)); twitterAuthButton.setEnabled(false); twitterAuthButton.setTextColor(Color.parseColor("#919191")); twitterAuthButton.setBackgroundResource(R.drawable.twitter_logo_disabled); } @Override public void onAuthorizationFail() { Toast.makeText(FeedActivity.this, "Twitter authorization failed", Toast.LENGTH_SHORT).show(); } }); } public void authorizeFacebook(View v) { if (!isOnline()) { return; } clientHandler.authorize(Clients.FACEBOOK, new AuthListener() { @Override public void onAuthorizationComplete() { facebookAuthButton.setText(res.getString(R.string.facebook_authorized)); facebookAuthButton.setEnabled(false); facebookAuthButton.setTextColor(Color.parseColor("#919191")); facebookAuthButton.setBackgroundResource(R.drawable.facebook_logo_disabled); } @Override public void onAuthorizationFail() { Toast.makeText(FeedActivity.this, "Facebook authorization failed", Toast.LENGTH_SHORT).show(); } }); } public void testSomething(View v) { // This button is for testing only. Use it for all your testing needs <3 db.clearItemTable(); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); Window window = getWindow(); window.setFormat(PixelFormat.RGBA_8888); } }