Java tutorial
package au.com.infiniterecursion.hashqanda; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import twitter4j.Query; import twitter4j.QueryResult; import twitter4j.Tweet; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.conf.ConfigurationBuilder; import twitter4j.http.AccessToken; import android.app.AlertDialog; import android.app.Dialog; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; /* * Main HashQanda Activity * * AUTHORS: * * Andy Nicholson * * 2011 * Copyright Infinite Recursion Pty Ltd. * http://www.infiniterecursion.com.au */ public class MainActivity extends ListActivity { private static final String TAG = "hashqanda"; private HQApp app; boolean autoRefreshPreference; String str_numberTweets; int numberTweets; SharedPreferences prefs; // UI threaded updater infrastructure private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); ScheduledFuture<?> tweet_loader_handler; final Runnable tweet_loader = new Runnable() { public void run() { Log.d(TAG, " Auto loader starting "); tryToStartLoader(); } }; // Menu ids private static final int MENU_ITEM_1 = Menu.FIRST; private static final int MENU_ITEM_2 = MENU_ITEM_1 + 1; private static final int MENU_ITEM_3 = MENU_ITEM_2 + 1; private static final int MENU_ITEM_4 = MENU_ITEM_3 + 1; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); app = (HQApp) getApplication(); Log.d(TAG, "onCreate , launching asynch loading if thread not running ? " + app.isThread_running()); app.setShowing_tweet_dialog(false); } public void onResume() { super.onResume(); Log.d(TAG, " on Resume... running thread ? " + app.isThread_running()); prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); autoRefreshPreference = prefs.getBoolean("autoloadingPreference", true); str_numberTweets = prefs.getString("numberTweetsPreference", "30"); numberTweets = Integer.valueOf(str_numberTweets).intValue(); // set up adapter TweetAdapter adapter = new TweetAdapter(this, R.layout.tweet_row, app.getTweetList()); setListAdapter(adapter); app.setListAdapter(adapter); tryToStartLoader(); if (autoRefreshPreference) { Log.d(TAG, "Starting autorefresh scheduler"); tweet_loader_handler = scheduler.scheduleAtFixedRate(tweet_loader, 30, 60, TimeUnit.SECONDS); } else { tweet_loader_handler = null; } } private void tryToStartLoader() { //dont do it, if user in middle of tweeting. if (app.isShowing_tweet_dialog()) return; // If we are still running, show dialog again, or else launch threaded // loader if (app.isThread_running()) { ThreadedLoader loader = app.getLoader(); if (loader != null) { loader.showDialog(); } else { Log.e(TAG, "Loader is null, though thread is running ?!"); } } else { ThreadedLoader loader = new ThreadedLoader(); loader.start(); app.setLoader(loader); } } public void onDestroy() { super.onDestroy(); Log.d(TAG, " on Destroy"); } public void onPause() { super.onPause(); Log.d(TAG, " on Pause. running thread ? " + app.isThread_running()); if (app.isThread_running()) { ThreadedLoader loader = app.getLoader(); if (loader != null) { loader.dismissDialog(); } else { Log.e(TAG, "Loader is null, though thread is running ?!"); } } // cancel the periodic loader. if (tweet_loader_handler != null) tweet_loader_handler.cancel(true); } public int getVersionCode() { int v = 0; try { v = getPackageManager().getPackageInfo(getApplicationInfo().packageName, 0).versionCode; } catch (NameNotFoundException e) { // Huh? Really? } return v; } public String getVersionName() { String name = null; try { name = getPackageManager().getPackageInfo(getApplicationInfo().packageName, 0).versionName; } catch (NameNotFoundException e) { // Huh? Really? } return name; } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); Log.i(TAG, "OnPrepareOptionsMenu called"); menu.clear(); addConstantMenuItems(menu); return true; } private void addConstantMenuItems(Menu menu) { // ALWAYS ON menu items. MenuItem menu_about = menu.add(0, MENU_ITEM_1, 0, R.string.about); menu_about.setIcon(R.drawable.wizard48); MenuItem menu_tweet = menu.add(0, MENU_ITEM_4, 0, R.string.tweet); menu_tweet.setIcon(R.drawable.sun48); MenuItem menu_prefs = menu.add(0, MENU_ITEM_2, 0, R.string.preferences); menu_prefs.setIcon(R.drawable.options); MenuItem menu_refresh = menu.add(0, MENU_ITEM_3, 0, R.string.refresh); menu_refresh.setIcon(R.drawable.business48); } @Override public boolean onOptionsItemSelected(MenuItem menuitem) { int menuNum = menuitem.getItemId(); Log.d("MENU", "Option " + menuNum + " selected"); switch (menuitem.getItemId()) { case MENU_ITEM_1: // ABOUT String mesg = getString(R.string.about_this); // find&replace VERSION mesg = mesg.replace("VERSION", "version " + getVersionName()); final SpannableString s = new SpannableString(mesg); Linkify.addLinks(s, Linkify.ALL); // Licenses String mesg2 = getString(R.string.third_party_licenses); final SpannableString s2 = new SpannableString(mesg2); Linkify.addLinks(s2, Linkify.ALL); AlertDialog about = new AlertDialog.Builder(this).setMessage(s) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }).setNegativeButton(R.string.licenses, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { AlertDialog licenses = new AlertDialog.Builder(MainActivity.this).setMessage(s2) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }).show(); // makes links work ((TextView) licenses.findViewById(android.R.id.message)) .setMovementMethod(LinkMovementMethod.getInstance()); } }).show(); // makes links work ((TextView) about.findViewById(android.R.id.message)) .setMovementMethod(LinkMovementMethod.getInstance()); break; case MENU_ITEM_2: // Preferences Intent intent = new Intent().setClass(this, PreferencesActivity.class); this.startActivity(intent); break; case MENU_ITEM_3: // refresh tryToStartLoader(); break; case MENU_ITEM_4: // tweeting String twitterToken, twitterTokenSecret; String[] toks = twitterTokens(); twitterToken = toks[0]; twitterTokenSecret = toks[1]; if (twitterToken != null && twitterTokenSecret != null) { showTweetDialog(); } else { // Need to authorise. Toast.makeText(MainActivity.this, R.string.you_need_to_authorise_this_application_with_twitter_first_, Toast.LENGTH_LONG) .show(); // Launch Authorisation first. Intent intent2 = new Intent().setClass(this, TwitterOAuthActivity.class); this.startActivity(intent2); } break; default: return super.onOptionsItemSelected(menuitem); } return true; } public class ThreadedLoader extends Thread { ProgressDialog pdialog; public void dismissDialog() { MainActivity.this.runOnUiThread(new Runnable() { public void run() { if (pdialog != null && pdialog.isShowing()) { pdialog.dismiss(); } pdialog = null; } }); } public void showDialog() { // Show dialog on MainActivity UI thread MainActivity.this.runOnUiThread(new Runnable() { public void run() { if (pdialog == null) { pdialog = ProgressDialog.show(MainActivity.this, "HashQanda", "Loading conversation from twitter. Please wait...", true); } } }); } public void run() { // Tell app we are running app.setThread_running(true); showDialog(); // do long running network ops final boolean loaded_ok = loadTweets(); // Dismiss dialog on UI thread, and then either update adapter , or // show Toast dismissDialog(); MainActivity.this.runOnUiThread(new Runnable() { public void run() { Log.d(TAG, " load Tweets success ? " + loaded_ok); if (loaded_ok) { app.getListAdapter().notifyDataSetChanged(); } else { Toast.makeText(MainActivity.this, "Failed to connect to twitter. Sorry", Toast.LENGTH_LONG) .show(); } } }); // Finally tell app we arent running anymore. app.setThread_running(false); } } public class CachedBitmapAndTweet { Bitmap bm; Tweet twt; } public boolean loadTweets() { ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true).setOAuthConsumerKey("Q2DfeCNOxprbDp66fWlw") .setOAuthConsumerSecret("TgyJ26CKXz1SxGiEJx4HG9rytFsqiMZlEPeCO7S9g"); Twitter twitter = new TwitterFactory(cb.build()).getInstance(); // clear tweet list. MainActivity.this.runOnUiThread(new Runnable() { public void run() { // add to it , via the runOnUIThread app.getTweetList().clear(); } }); try { Log.d(TAG, " starting Tweets loading "); Query q = new Query("#qanda"); q.setRpp(numberTweets); QueryResult result = twitter.search(q); List<Tweet> tweets = result.getTweets(); for (Tweet tweet : tweets) { // Log.d(TAG, "@" + tweet.getFromUser() + " - " + // tweet.getText()); // Log.d(TAG, " img url " + tweet.getProfileImageUrl()); final CachedBitmapAndTweet cachedbmtwt = new CachedBitmapAndTweet(); cachedbmtwt.twt = tweet; try { URL url = new URL(tweet.getProfileImageUrl()); InputStream is = (InputStream) url.getContent(); if (is != null) { Bitmap bitmap = BitmapFactory.decodeStream(is); cachedbmtwt.bm = bitmap; } else { cachedbmtwt.bm = null; } } catch (MalformedURLException e) { e.printStackTrace(); cachedbmtwt.bm = null; } catch (IOException e) { e.printStackTrace(); cachedbmtwt.bm = null; } catch (NullPointerException npe) { npe.printStackTrace(); cachedbmtwt.bm = null; } MainActivity.this.runOnUiThread(new Runnable() { public void run() { // add to it , via the runOnUIThread app.getTweetList().add(cachedbmtwt); } }); } Log.d(TAG, " finished Tweets loading "); return true; } catch (TwitterException te) { te.printStackTrace(); Log.d(TAG, "Failed to search tweets: " + te.getMessage()); return false; } } public class TweetAdapter extends ArrayAdapter<CachedBitmapAndTweet> { private ArrayList<CachedBitmapAndTweet> items; private TweetViewHolder tweetHolder; private class TweetViewHolder { ImageView img; TextView msg; } public TweetAdapter(Context context, int tvResId, ArrayList<CachedBitmapAndTweet> items) { super(context, tvResId, items); this.items = items; } public View getView(int pos, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.tweet_row, null); tweetHolder = new TweetViewHolder(); tweetHolder.img = (ImageView) v.findViewById(R.id.imageView1); tweetHolder.msg = (TextView) v.findViewById(R.id.textView1); v.setTag(tweetHolder); } else { tweetHolder = (TweetViewHolder) v.getTag(); } // check items hasnt been reset if (items == null || items.size() == 0) { return v; } CachedBitmapAndTweet bmtwt = items.get(pos); if (bmtwt != null) { String raw = bmtwt.twt.getFromUser() + " : " + bmtwt.twt.getText(); final SpannableString text = new SpannableString(raw); Linkify.addLinks(text, Linkify.ALL); tweetHolder.msg.setText(text); tweetHolder.msg.setMovementMethod(LinkMovementMethod.getInstance()); if (bmtwt.bm != null) { tweetHolder.img.setImageBitmap(bmtwt.bm); } else { tweetHolder.img.setImageBitmap(null); } } return v; } } private void showTweetDialog() { app.setShowing_tweet_dialog(true); // Launch Tweet Edit View LayoutInflater inflater = (LayoutInflater) getApplicationContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View tweet_dialog_view = inflater.inflate(R.layout.tweet_dialog, null); final EditText tweet_edittext = (EditText) tweet_dialog_view.findViewById(R.id.EditTextTweet); final Dialog d = new Dialog(this); Window w = d.getWindow(); w.setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND); d.setTitle(R.string.tweet_dialog_title); // the edit layout defined in an xml file (in res/layout) d.setContentView(tweet_dialog_view); // Cancel Button cbutton = (Button) d.findViewById(R.id.button2Cancel); cbutton.setOnClickListener(new OnClickListener() { public void onClick(View v) { app.setShowing_tweet_dialog(false); d.dismiss(); } }); // Edit Button ebutton = (Button) d.findViewById(R.id.button1Edit); ebutton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // save title and description to DB. String tweet = tweet_edittext.getText().toString(); int end = (tweet.length() > 133) ? 133 : tweet.length(); String real_tweet = "#qanda " + tweet.substring(0, end); Log.d(TAG, "New tweet is " + tweet); Log.d(TAG, "real tweet is " + real_tweet); String twitterToken, twitterTokenSecret; String[] toks = twitterTokens(); twitterToken = toks[0]; twitterTokenSecret = toks[1]; if (twitterToken != null && twitterTokenSecret != null) { // Ok, now we can tweet this URL AccessToken a = new AccessToken(twitterToken, twitterTokenSecret); Twitter twitter = new TwitterFactory().getInstance(); twitter.setOAuthConsumer(TwitterOAuthActivity.consumerKey, TwitterOAuthActivity.consumerSecret); twitter.setOAuthAccessToken(a); try { twitter.updateStatus(real_tweet); runOnUiThread(new Runnable() { public void run() { Toast.makeText(MainActivity.this, R.string.tweet_posted, Toast.LENGTH_LONG).show(); } }); } catch (TwitterException e) { // e.printStackTrace(); Log.e(TAG, " twittering failed " + e.getMessage()); } } else { runOnUiThread(new Runnable() { public void run() { Toast.makeText(MainActivity.this, R.string.tweet_not_posted, Toast.LENGTH_LONG).show(); } }); } app.setShowing_tweet_dialog(false); d.dismiss(); } }); d.show(); } private String[] twitterTokens() { // Check there is a valid twitter OAuth tokens. String twitterToken = prefs.getString("twitterToken", null); String twitterTokenSecret = prefs.getString("twitterTokenSecret", null); return new String[] { twitterToken, twitterTokenSecret }; } }