Java tutorial
/* * Tweetings - Twitter client for Android * * Copyright (C) 2012-2013 RBD Solutions Limited <apps@tweetings.net> * Copyright (C) 2012 Mariotaku Lee <mariotaku.lee@gmail.com> * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package com.dwdesign.tweetings.fragment; import static com.dwdesign.tweetings.util.Utils.findStatusInDatabases; import static com.dwdesign.tweetings.util.Utils.getAccountUsername; import static com.dwdesign.tweetings.util.Utils.getQuoteStatus; import static com.dwdesign.tweetings.util.Utils.getTwitterInstance; import static com.dwdesign.tweetings.util.Utils.showErrorToast; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.dwdesign.tweetings.Constants; import com.dwdesign.tweetings.HttpClientFactory; import com.dwdesign.tweetings.R; import com.dwdesign.tweetings.activity.ComposeActivity; import com.dwdesign.tweetings.adapter.ParcelableStatusesAdapter; import com.dwdesign.tweetings.loader.DummyParcelableStatusesLoader; import com.dwdesign.tweetings.loader.UserListTimelineLoader; import com.dwdesign.tweetings.model.ParcelableStatus; import com.dwdesign.tweetings.service.TweetingsService; import com.dwdesign.tweetings.util.NoDuplicatesArrayList; import com.dwdesign.tweetings.util.ServiceInterface; import com.dwdesign.tweetings.util.SynchronizedStateSavedList; import twitter4j.Twitter; import twitter4j.TwitterException; import android.app.Dialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.content.Loader; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; public class ConversationFragment extends ParcelableStatusesListFragment implements Constants { private static final int ADD_STATUS = 1; private static final long INVALID_ID = -1; private ShowConversationTask mShowConversationTask; private StatusHandler mStatusHandler; private ParcelableStatusesAdapter mAdapter; public long account_id; public String screen_name; public boolean isShare = false; @Override public boolean isLoaderUsed() { return false; } @Override public void scrollToStatusId(long statusId) { } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case MENU_SHARE: { isShare = true; shareConversation(false); break; } case MENU_TWEET_CONVERSATION: { isShare = false; shareConversation(true); break; } } return super.onOptionsItemSelected(item); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_conversation, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public Loader<SynchronizedStateSavedList<ParcelableStatus, Long>> newLoaderInstance(final Bundle args) { final long account_id = args != null ? args.getLong(INTENT_KEY_ACCOUNT_ID, -1) : -1; return new DummyParcelableStatusesLoader(getActivity(), account_id, getData()); } @Override public void onActivityCreated(final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setPullToRefreshEnabled(false); mAdapter = getListAdapter(); mAdapter.setGapDisallowed(true); Bundle bundle = getArguments(); if (bundle == null) { bundle = new Bundle(); } account_id = bundle.getLong(INTENT_KEY_ACCOUNT_ID, INVALID_ID); final long status_id = bundle.getLong(INTENT_KEY_STATUS_ID, INVALID_ID); if (mShowConversationTask != null && !mShowConversationTask.isCancelled()) { mShowConversationTask.cancel(true); } mStatusHandler = new StatusHandler(mAdapter, account_id); mShowConversationTask = new ShowConversationTask(mStatusHandler, account_id, status_id); if (account_id != INVALID_ID && status_id != INVALID_ID) { mShowConversationTask.execute(); } } @Override public void onDataLoaded(final Loader<SynchronizedStateSavedList<ParcelableStatus, Long>> loader, final ParcelableStatusesAdapter adapter) { } @Override public void onDestroyView() { setProgressBarIndeterminateVisibility(false); super.onDestroyView(); } class ShowConversationTask extends AsyncTask<Void, Void, TwitterException> { private final long mAccountId, mStatusId; private final StatusHandler mHandler; public ShowConversationTask(final StatusHandler handler, final long account_id, final long status_id) { mHandler = handler; mAccountId = account_id; mStatusId = status_id; } @Override protected TwitterException doInBackground(final Void... params) { final Twitter twitter = getTwitterInstance(getActivity(), mAccountId, true); if (twitter == null) return null; try { ParcelableStatus p_status = findStatusInDatabases(getActivity(), mAccountId, mStatusId); twitter4j.Status status = null; if (p_status == null) { status = twitter.showStatus(mStatusId); if (status == null) return null; p_status = new ParcelableStatus(status, mAccountId, false); } mHandler.sendMessage(mHandler.obtainMessage(ADD_STATUS, p_status)); long in_reply_to_id = p_status.in_reply_to_status_id; while (in_reply_to_id != -1) { p_status = findStatusInDatabases(getActivity(), mAccountId, in_reply_to_id); if (p_status == null) { status = twitter.showStatus(in_reply_to_id); if (status == null) { break; } p_status = new ParcelableStatus(status, mAccountId, false); } if (p_status.status_id <= 0) { break; } mHandler.sendMessage(mHandler.obtainMessage(ADD_STATUS, p_status)); in_reply_to_id = p_status.in_reply_to_status_id; } } catch (final TwitterException e) { return e; } return null; } @Override protected void onPostExecute(final TwitterException result) { if (result != null) { showErrorToast(getActivity(), null, result, true); } setProgressBarIndeterminateVisibility(false); super.onPostExecute(result); } @Override protected void onPreExecute() { setProgressBarIndeterminateVisibility(true); super.onPreExecute(); } } static class StatusHandler extends Handler { private final ParcelableStatusesAdapter mAdapter; public StatusHandler(final ParcelableStatusesAdapter adapter, long account_id) { mAdapter = adapter; } @Override public void handleMessage(final Message msg) { switch (msg.what) { case ADD_STATUS: final Object obj = msg.obj; if (obj instanceof ParcelableStatus) { mAdapter.add((ParcelableStatus) obj); } break; } super.handleMessage(msg); } } protected void shareConversation(boolean isCompose) { GenerateConversationLinkTask mTask = new GenerateConversationLinkTask(); mTask.execute(); } private class GenerateConversationLinkTask extends AsyncTask<String, Void, String> { private ProgressDialog dialog; // can use UI thread here protected void onPreExecute() { dialog = new ProgressDialog(ConversationFragment.this.getActivity()); dialog.setMessage(getString(R.string.storify_generate)); dialog.setIndeterminate(true); dialog.setCancelable(false); dialog.show(); } // automatically done on worker thread (separate from UI thread) protected String doInBackground(final String... args) { HttpClient client = HttpClientFactory.getThreadSafeClient(); final String screen_name = getAccountUsername(ConversationFragment.this.getActivity(), account_id); String title = "Conversation with"; String slug = "conversation-with"; String thumbnail = null; String statusId = null; String signingUrl = TWITTER_VERIFY_CREDENTIALS_JSON; ServiceInterface mService = getServiceInterface(); String oAuthEchoHeader = mService.generateOAuthEchoHeader(account_id); NoDuplicatesArrayList<ParcelableStatus> statuses = mAdapter.getStatuses(); ArrayList<String> userArray = new ArrayList<String>(); ArrayList<String> elementArray = new ArrayList<String>(); for (ParcelableStatus status : statuses) { if (statusId == null) { statusId = String.valueOf(status.status_id); thumbnail = "http://api.twitter.com/1/users/profile_image?screen_name=" + screen_name + "&size=bigger"; } boolean inArray = false; for (String user : userArray) { if (user.equals(status.screen_name)) { inArray = true; } } if (inArray == false) { title = title + " " + status.screen_name; slug = slug + "-" + status.screen_name.toLowerCase(); userArray.add(status.screen_name); } elementArray.add("https://twitter.com/" + status.screen_name + "/status/" + String.valueOf(status.status_id)); } slug = slug + "-" + statusId; JSONObject jObject = new JSONObject(); try { jObject.put("title", title); jObject.put("slug", slug); jObject.put("elements", new JSONArray(elementArray)); } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String jsonString = jObject.toString(); try { HttpPost post = new HttpPost("http://api.storify.com/v1/stories/" + screen_name + "/create"); post.addHeader("X-Verify-Credentials-Authorization", oAuthEchoHeader); post.addHeader("X-Auth-Service-Provider", TWITTER_VERIFY_CREDENTIALS_JSON); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); nameValuePairs.add(new BasicNameValuePair("publish", "true")); nameValuePairs.add(new BasicNameValuePair("api_key", STORIFY_API_KEY)); nameValuePairs.add(new BasicNameValuePair("story", jsonString)); post.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = client.execute(post); BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String line = ""; String outputContent = ""; while ((line = rd.readLine()) != null) { outputContent += line; } if (!outputContent.equals("")) { JSONObject bufferResponse = new JSONObject(outputContent); JSONObject content = bufferResponse.getJSONObject("content"); if (content != null) { String url = content.getString("permalink"); if (url != null) { return url; } } } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } // can use UI thread here protected void onPostExecute(final String result) { if (dialog.isShowing()) { dialog.dismiss(); } if (result == null) { Toast.makeText(ConversationFragment.this.getActivity(), R.string.storify_failed, Toast.LENGTH_SHORT) .show(); } else { ConversationFragment.this.linkGenerationComplete(result); } } } public void linkGenerationComplete(String url) { if (isShare == false) { final Intent intent = new Intent(INTENT_ACTION_COMPOSE); final Bundle bundle = new Bundle(); bundle.putLong(INTENT_KEY_ACCOUNT_ID, account_id); bundle.putString(INTENT_KEY_TEXT, url); intent.putExtras(bundle); startActivity(intent); } else { final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, url); startActivity(Intent.createChooser(intent, getString(R.string.share))); } } }