Java tutorial
package de.electricdynamite.pasty; /* * Copyright 2012-2013 Philipp Geschke * * 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. */ import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONObject; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.text.ClipboardManager; import android.text.util.Linkify; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; import android.webkit.URLUtil; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; import com.actionbarsherlock.app.SherlockListFragment; import com.actionbarsherlock.view.Menu; import de.electricdynamite.pasty.PastyLoader.PastyResponse; @SuppressWarnings("deprecation") public class ClipboardFragment extends SherlockListFragment implements LoaderCallbacks<PastyLoader.PastyResponse> { private static final String TAG = ClipboardFragment.class.toString(); private boolean LOCAL_LOG = false; protected Drawable mBackground; protected TextView mHelpTextBig; protected TextView mHelpTextSmall; private LayoutInflater mInflater; private ClipboardItemListAdapter mAdapter; private ArrayList<ClipboardItem> mItems; private PastyClipboardFragmentListener activity; private PastyPreferencesProvider prefs; public interface PastyClipboardFragmentListener { void onPastyClipboardFragmentSignal(int signal); void onPastyClipboardFragmentSignal(int signal, int dialogId); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // this is really important in order to save the state across screen // configuration changes for example setRetainInstance(true); if (PastySharedStatics.LOCAL_LOG == true) this.LOCAL_LOG = true; //LoaderManager.enableDebugLogging(true); mInflater = LayoutInflater.from(getSherlockActivity()); activity = (PastyClipboardFragmentListener) getSherlockActivity(); mHelpTextBig = (TextView) getActivity().findViewById(R.id.tvHelpTextBig); mHelpTextSmall = (TextView) getActivity().findViewById(R.id.tvHelpTextSmall); mBackground = mHelpTextSmall.getBackground(); if (mAdapter == null) { // Set up our ArrayList and ListAdapter mItems = new ArrayList<ClipboardItem>(); mAdapter = new ClipboardItemListAdapter(getSherlockActivity(), mItems); } getListView().setAdapter(mAdapter); if (this.prefs == null) { this.prefs = new PastyPreferencesProvider(getSherlockActivity().getApplication()); } else { prefs.reload(); } // Try to reconnect with an existing loader if (getSherlockActivity().getSupportLoaderManager().getLoader(PastyLoader.TASK_CLIPBOARD_FETCH) != null) { if (LOCAL_LOG) Log.v(TAG, "onActivityCreated(): Loader already exists, reconnecting"); getSherlockActivity().getSupportLoaderManager().initLoader(PastyLoader.TASK_CLIPBOARD_FETCH, null, this); } else { if (LOCAL_LOG) Log.v(TAG, "onActivityCreated(): No PastyLoader found"); startLoading(); } // ----- end magic lines ----- } protected void startLoading() { //Log.d(TAG,"startLoading()"); getSherlockActivity().setSupportProgressBarIndeterminateVisibility(Boolean.TRUE); ProgressBar pbLoading = (ProgressBar) getSherlockActivity().findViewById(R.id.progressbar_downloading); mHelpTextBig.setText(R.string.helptext_PastyActivity_loading); pbLoading.setVisibility(View.VISIBLE); pbLoading = null; Bundle b = new Bundle(); // first time we call this loader, so we need to create a new one getSherlockActivity().getSupportLoaderManager().initLoader(PastyLoader.TASK_CLIPBOARD_FETCH, b, this); b = null; } protected void restartLoading() { Bundle args = new Bundle(); restartLoading(args); args = null; } protected void restartLoading(Boolean permitCache) { Bundle args = new Bundle(); args.putBoolean("permitCache", permitCache); restartLoading(args); args = null; } protected void restartLoading(Bundle args) { getSherlockActivity().setSupportProgressBarIndeterminateVisibility(Boolean.TRUE); // --------- the other magic lines ---------- // call restart because we want the background work to be executed // again if (LOCAL_LOG) Log.v(TAG, "restartLoading(): re-starting loader"); // TODO Make sure this does not get called before startLoading was called, or NULL PE getSherlockActivity().getSupportLoaderManager().restartLoader(PastyLoader.TASK_CLIPBOARD_FETCH, args, this); args = null; // --------- end the other magic lines -------- } @Override public Loader<PastyLoader.PastyResponse> onCreateLoader(int id, Bundle args) { if (LOCAL_LOG) Log.v(TAG, "onCreateLoader(): New PastyLoader created"); return new PastyLoader(getSherlockActivity().getApplicationContext(), id, args); } @Override public void onLoadFinished(Loader<PastyLoader.PastyResponse> loader, PastyLoader.PastyResponse response) { ProgressBar pbLoading = (ProgressBar) getSherlockActivity().findViewById(R.id.progressbar_downloading); pbLoading.setVisibility(View.GONE); pbLoading = null; mHelpTextBig.setTextColor(getResources().getColor(R.color.abs__primary_text_holo_light)); mHelpTextBig.setBackgroundDrawable(mBackground); if (response.isFinal) { getSherlockActivity().setSupportProgressBarIndeterminateVisibility(Boolean.FALSE); if (response.getResultSource() == PastyResponse.SOURCE_CACHE) { Toast.makeText(getSherlockActivity().getApplicationContext(), getString(R.string.warning_no_network_short), Toast.LENGTH_SHORT).show(); } } if (response.hasException) { if (LOCAL_LOG) Log.v(TAG, "onLoadFinished(): Loader delivered exception; calling handleException()"); // an error occured getSherlockActivity().setSupportProgressBarIndeterminateVisibility(Boolean.FALSE); PastyException mException = response.getException(); handleException(mException); } else { switch (loader.getId()) { case PastyLoader.TASK_CLIPBOARD_FETCH: JSONArray Clipboard = response.getClipboard(); mItems.clear(); mAdapter.notifyDataSetChanged(); getListView().invalidateViews(); try { if (Clipboard.length() == 0) { //Clipboard is empty mHelpTextBig.setText(R.string.helptext_PastyActivity_clipboard_empty); mHelpTextSmall.setText(R.string.helptext_PastyActivity_how_to_add); } else { for (int i = 0; i < Clipboard.length(); i++) { JSONObject Item = Clipboard.getJSONObject(i); ClipboardItem cbItem = new ClipboardItem(Item.getString("_id"), Item.getString("item")); this.mItems.add(cbItem); } mHelpTextBig.setText(R.string.helptext_PastyActivity_copy); mHelpTextSmall.setText(R.string.helptext_PastyActivity_options); //Assign adapter to ListView ListView listView = (ListView) getSherlockActivity().findViewById(R.id.listItems); listView.setAdapter(mAdapter); listView.setItemsCanFocus(false); listView.setOnItemClickListener(new OnItemClickListener() { @SuppressLint("NewApi") @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ClipboardItem Item = mItems.get(position); // get a ClipboardItem from the clicked position if (Item.isLinkified() && prefs.getClickableLinks()) { /* If the clicked item was originally linkified and prefs.getClickableLinks() is true, we manually * fire an ACTION_VIEW intent to simulate Linkify() behavior */ String url = Item.getText(); if (!URLUtil.isValidUrl(url)) url = "http://" + url; Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); } else { /* Else we copy the item to the systems clipboard, * show a Toast and finish() the activity */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { android.content.ClipboardManager sysClipboard = (android.content.ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(sysClipboard); sysClipboard = null; } else { ClipboardManager sysClipboard = (ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(sysClipboard); sysClipboard = null; } Toast.makeText(getSherlockActivity().getApplicationContext(), getString(R.string.item_copied), Toast.LENGTH_LONG).show(); getSherlockActivity().finish(); } } }); registerForContextMenu(listView); } } catch (Exception e) { e.printStackTrace(); } break; default: break; } } } @Override public void onLoaderReset(Loader<PastyResponse> arg0) { // TODO Auto-generated method stub } public class ClipboardItemListAdapter extends BaseAdapter { // List of stored ClipboardItems private List<ClipboardItem> itemList; public ClipboardItemListAdapter(Context context, List<ClipboardItem> itemList) { this.itemList = itemList; } public int getCount() { return itemList.size(); } public ClipboardItem getItem(int position) { return itemList.get(position); } public long getItemId(int position) { return position; } public String getClipboardItemId(int position) { return itemList.get(position).getId(); } public void linkified(int position) { this.itemList.get(position).setLinkfied(Boolean.TRUE); } public Boolean isLinkified(int position) { return this.itemList.get(position).isLinkified(); } public void remove(int position) { this.itemList.remove(position); this.notifyDataSetChanged(); } public void removeAll() { this.itemList.clear(); } public void delete(int position) { ClipboardItem mItem = getItem(position); new ItemDeleteTask().execute(mItem); remove(position); // TODO Implement some kind of callback to remove only upon successful deletion. } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = mInflater.inflate(R.layout.listitem, parent, false); } // get the item associated with this position ClipboardItem Item = itemList.get(position); // Select our text view from our view row TextView tvListItem = (TextView) view.findViewById(R.id.listItemText); tvListItem.setText(Item.getText()); //view.setOnClickListener(new clipboardOnClickListener(position)); if (prefs.getClickableLinks()) { /* Linkify/ListView / JB problem work around: * 1. Linkify the item * 2. If the item was linkified, write it into the ClipboardItem * 3. Delete the MovementMethod * 4. (in the onClick callback) check if the clicked ClipboardItem was linkified * 5. (in the onClick callback) if it was, fire a manual ACTIEN_VIEW intent * 6. ???? * 7. PROFIT!!!11 (and dirty, dirty code!) * (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) */ Boolean linkified = Linkify.addLinks(tvListItem, Linkify.WEB_URLS); if (linkified) { linkified(position); // Tell the ClipboardItem that it was linkified. } /* Delete the MovementMethod to prevent linkified items from firing an intent * at onItemClick() or onItemLongClick() */ tvListItem.setMovementMethod(null); linkified = null; } else { if (URLUtil.isValidUrl(Item.getText())) { linkified(position); } } View mSpinner = (View) view.findViewById(R.id.listItemSpinnerLayout); mSpinner.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { v.showContextMenu(); } }); return view; } } public class ClipboardOnClickListener implements OnClickListener { private int position; public ClipboardOnClickListener(int position) { this.position = position; } @Override public void onClick(View view) { ClipboardItem Item = mItems.get(position); // get a ClipboardItem from the clicked position if (Item.isLinkified() && prefs.getClickableLinks()) { /* If the clicked item was originally linkified and prefs.getClickableLinks() is true, we manually * fire an ACTION_VIEW intent to simulate Linkify() behavior */ String url = Item.getText(); if (!URLUtil.isValidUrl(url)) url = "http://" + url; Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); } else { /* Else we copy the item to the systems clipboard, * show a Toast and finish() the activity */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { android.content.ClipboardManager sysClipboard = (android.content.ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(sysClipboard); sysClipboard = null; } else { ClipboardManager sysClipboard = (ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(sysClipboard); sysClipboard = null; } Toast.makeText(getSherlockActivity().getApplicationContext(), getString(R.string.item_copied), Toast.LENGTH_LONG).show(); getSherlockActivity().finish(); } } } private class ItemDeleteTask extends AsyncTask<ClipboardItem, Void, PastyResponse> { private Context context; /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ @Override protected PastyResponse doInBackground(ClipboardItem... item) { if (context == null) { context = getSherlockActivity().getApplicationContext(); } PastyPreferencesProvider prefs = new PastyPreferencesProvider(context); PastyClient client = new PastyClient(prefs.getRESTBaseURL(), true); client.setUsername(prefs.getUsername()); client.setPassword(prefs.getPassword()); PastyResponse result; try { client.deleteItem(item[0]); result = new PastyResponse(); } catch (PastyException e) { result = new PastyResponse(e); } return result; } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(PastyResponse result) { if (result.hasException) { handleException(result.getException()); } else { Toast.makeText(context, getString(R.string.item_deleted), Toast.LENGTH_LONG).show(); restartLoading(PastyLoader.CACHE_DENIED); } } } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; if (v.getId() == R.id.listItems || v.getId() == R.id.listItemText) { menu.setHeaderTitle(getString(R.string.itemContextMenuTitle)); String[] menuItems = getResources().getStringArray(R.array.itemContextMenu); ClipboardItem mItem = mAdapter.getItem(info.position); if (mItem.isLinkified()) { /* Item was Linkified. * Let's add a "open in browser" menuItem */ menu.add(Menu.NONE, PastySharedStatics.ITEM_CONTEXTMENU_OPEN_ID, 0, R.string.itemContextMenu_open); } for (int i = 0; i < menuItems.length; i++) { menu.add(Menu.NONE, i, i, menuItems[i]); } } } @SuppressLint("NewApi") public boolean onContextItemSelected(android.view.MenuItem item) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); int menuItemIndex = item.getItemId(); ClipboardItem Item = mItems.get(info.position); switch (menuItemIndex) { case PastySharedStatics.ITEM_CONTEXTMENU_COPY_ID: // Copy without exit selected if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(clipboard); clipboard = null; } else { ClipboardManager clipboard = (ClipboardManager) getSherlockActivity() .getSystemService(Context.CLIPBOARD_SERVICE); Item.copyToClipboard(clipboard); clipboard = null; } Toast.makeText(getSherlockActivity().getApplicationContext(), getString(R.string.item_copied), Toast.LENGTH_LONG).show(); break; case PastySharedStatics.ITEM_CONTEXTMENU_SHARE_ID: // Share to another app Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, Item.getText()); startActivity(Intent.createChooser(shareIntent, getString(R.string.app_share_from_pasty))); break; case PastySharedStatics.ITEM_CONTEXTMENU_DELETE_ID: // Delete selected mAdapter.delete(info.position); break; case PastySharedStatics.ITEM_CONTEXTMENU_OPEN_ID: /* If the clicked item was originally linkified, we * fire an ACTION_VIEW intent. */ String url = Item.getText(); if (!URLUtil.isValidUrl(url)) url = "http://" + url; Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); break; } return true; } /** handles PastyExceptions within this Fragment */ protected void handleException(PastyException mException) { if (mHelpTextBig == null || mHelpTextSmall == null) return; switch (mException.errorId) { case PastyException.ERROR_AUTHORIZATION_FAILED: mHelpTextBig.setTextColor(getResources().getColor(R.color.white)); mHelpTextBig.setBackgroundColor(getResources().getColor(R.color.red)); mHelpTextBig.setText(R.string.error_login_failed_title); mHelpTextSmall.setText(R.string.error_login_failed); return; case PastyException.ERROR_IO_EXCEPTION: mHelpTextBig.setTextColor(getResources().getColor(R.color.white)); mHelpTextBig.setBackgroundColor(getResources().getColor(R.color.red)); mHelpTextBig.setText(R.string.error_io_title); mHelpTextSmall.setText(R.string.error_io); case PastyException.ERROR_ILLEGAL_RESPONSE: mHelpTextBig.setTextColor(getResources().getColor(R.color.white)); mHelpTextBig.setBackgroundColor(getResources().getColor(R.color.red)); mHelpTextBig.setText(R.string.error_badanswer_title); mHelpTextSmall.setText(R.string.error_badanswer); return; case PastyException.ERROR_NO_CACHE_EXCEPTION: mHelpTextBig.setTextColor(getResources().getColor(R.color.white)); mHelpTextBig.setBackgroundColor(getResources().getColor(R.color.red)); mHelpTextBig.setText(R.string.error_no_network_title); mHelpTextSmall.setText(R.string.error_no_network); return; case PastyException.ERROR_UNKNOWN: mHelpTextBig.setTextColor(getResources().getColor(R.color.white)); mHelpTextBig.setBackgroundColor(getResources().getColor(R.color.red)); mHelpTextBig.setText(R.string.error_unknown_title); mHelpTextSmall.setText(R.string.error_unknown); Log.e(TAG, mException.getMessage()); return; default: break; } } }