Java tutorial
/* * Copyright (C) 2012-2013 Daniel Medina <http://danielme.com> * * This file is part of "Muspy for Android". * * "Muspy for Android" 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, version 3. * * "Muspy for Android" 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 version 3 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html/> */ package com.danielme.muspyforandroid.activities.base; import java.net.UnknownHostException; import org.apache.http.conn.ConnectTimeoutException; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.res.Configuration; import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.LayoutInflater.Factory; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.danielme.muspyforandroid.Constants; import com.danielme.muspyforandroid.MuspyApplication; import com.danielme.muspyforandroid.R; import com.danielme.muspyforandroid.activities.AboutActivity; import com.danielme.muspyforandroid.activities.AppSettingsActivity; import com.danielme.muspyforandroid.activities.ArtistBioActivity; import com.danielme.muspyforandroid.activities.MyArtistsActivity; import com.danielme.muspyforandroid.activities.ReleasesActivity; import com.danielme.muspyforandroid.activities.ResetPasswordActivity; import com.danielme.muspyforandroid.activities.SearchArtistsActivity; import com.danielme.muspyforandroid.activities.SettingsActivity; import com.danielme.muspyforandroid.activities.SignInActivity; import com.danielme.muspyforandroid.activities.SignUpActivity; import com.danielme.muspyforandroid.cache.CoverMemoryCache; import com.danielme.muspyforandroid.exc.AuthorizationException; import com.danielme.muspyforandroid.exc.MBGatewayTimeOutException; import com.danielme.muspyforandroid.services.MuspyClient; /** * All activities should extend this class. * * @author Daniel Medina (danielme.com) * @since 1.0 */ public abstract class AbstractActivity extends Activity { /* ************************************************************ */ /* FIELDS */ /* ************************************************************ */ private ProgressDialog progressDialog; private AlertDialog noConnectionDialog; private AlertDialog errorDialog; /* ************************************************************ */ /* STANDARD OPTIONS MENU */ /* ************************************************************ */ /** * Unfortunately font-style must be set programmatically // * http://stackoverflow * .com/questions/10521416/option-menu-default-gray-border-removal <item * name="android:panelFullBackground">@color/barbackground</item> * */ public boolean onCreateOptionsMenu(android.view.Menu menu) { if (this instanceof AboutActivity) { return false; } MenuInflater inflater = getMenuInflater(); if (this instanceof SignInActivity || this instanceof SignUpActivity || this instanceof ResetPasswordActivity) { inflater.inflate(R.menu.menusimple, menu); } else { inflater.inflate(R.menu.menu, menu); } getLayoutInflater().setFactory(new Factory() { public View onCreateView(String name, Context context, AttributeSet attrs) { if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) { try { LayoutInflater layoutInflater = LayoutInflater.from(context); final View view = layoutInflater.createView(name, null, attrs); new Handler().post(new Runnable() { public void run() { ((TextView) view).setTextColor(Color.WHITE); view.setBackgroundResource(R.drawable.menu_selector); } }); return view; } catch (Exception e) { Log.w("onCreateOptionsMenu", e.getMessage(), e); } } return null; } }); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.appsettings: defaultTransition(new Intent(this, AppSettingsActivity.class)); return true; case R.id.about: defaultTransition(new Intent(this, AboutActivity.class)); return true; case R.id.search: defaultTransition(new Intent(this, SearchArtistsActivity.class)); return true; default: return false; } } /** * Set animation. * @since 1.2 */ @Override public void onBackPressed() { super.onBackPressed(); //alpha doesn't seem to work fine on low spec devices if (Build.VERSION.SDK_INT >= Constants.API_40) { overridePendingTransition(R.anim.zoom_back_in, R.anim.zoom_back_out); } } /* ************************************************************ */ /* TOP BAR BUTTONS */ /* ************************************************************ */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (findViewById(R.id.commonbar) != null) { changeButtonRotation((Button) findViewById(R.id.releases), newConfig, R.drawable.releases_button); changeButtonRotation((Button) findViewById(R.id.artists), newConfig, R.drawable.artists_button); changeButtonRotation((Button) findViewById(R.id.settings), newConfig, R.drawable.settings_button); changeButtonRotation((Button) findViewById(R.id.signout), newConfig, R.drawable.signout_button); } } private void changeButtonRotation(Button button, Configuration newConfig, int icon) { if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { button.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); button.setTextSize(18); } else { button.setCompoundDrawablesWithIntrinsicBounds(0, icon, 0, 0); button.setTextSize(11); } } public void signout(View view) { MuspyApplication muspyApplication = (MuspyApplication) getApplication(); muspyApplication.setCredentials(null, null, null); CoverMemoryCache.clearAll(); MuspyClient.getInstance().clearArtists(); Intent intent = new Intent(this, SignInActivity.class); defaultTransition(intent); } public void showArtistInfo(View imageButtonInfo) { String mbid = (String) imageButtonInfo.getTag(); Intent intent = new Intent(this, ArtistBioActivity.class); intent.putExtra(Constants.PARAM_ARTIST, mbid); defaultTransition(intent); } public void releases(View view) { Intent intent = new Intent(this, ReleasesActivity.class); startActivity(intent); defaultTransition(intent); } public void artists(View view) { Intent intent = new Intent(this, MyArtistsActivity.class); defaultTransition(intent); } public void settings(View view) { Intent intent = new Intent(this, SettingsActivity.class); defaultTransition(intent); } public void markButtonPressed(int buttonint, boolean clickable) { Button button = (Button) findViewById(buttonint); button.setSelected(true); button.setClickable(clickable); // it didn't work with xml selector button.setTypeface(null, Typeface.BOLD); button.setFocusable(clickable); } /* ************************************************************ */ /* OTHER METHODS */ /* ************************************************************ */ /** * Default transiction between activities, very similar to Jelly Bean's defaut * @since 1.2 */ public void defaultTransition(Intent intent) { startActivity(intent); //alpha doesn't seem to work fine on low spec devices if (Build.VERSION.SDK_INT >= Constants.API_40) { overridePendingTransition(R.anim.zoom_forward_in, R.anim.zoom_forward_out); } } protected void showToast(int msgID) { showToast(msgID, null, Constants.TOAST_DURATION); } protected void showToast(int msgID, int duration) { showToast(msgID, null, duration); } private void showToast(int msgID, String msg, int duration) { Toast toast = new Toast(this); LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_success, (ViewGroup) findViewById(R.id.lytLayout)); TextView txtMsg = (TextView) layout.findViewById(R.id.toastMessage); if (msg == null) { txtMsg.setText(getString(msgID)); } else { txtMsg.setText(msg); } toast.setDuration(duration); toast.setView(layout); toast.show(); } protected void showToastSuccess(String msg) { showToast(0, msg, Constants.TOAST_DURATION); } /** * remember: this must be called inside UI Thread, be careful with * exceptions in AsyncTask and Runnables * * @param ex */ public void showError(Exception exc) { Builder builder = new Builder(this); String msg = getString(R.string.exception); builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setCancelable(false); builder.setNeutralButton(R.string.ok, null); if (exc != null) { if (exc instanceof UnknownHostException) { msg += getString(R.string.checkconn); } else if (exc instanceof ConnectTimeoutException) { msg += getString(R.string.timeout); } else if (exc instanceof MBGatewayTimeOutException) { msg += getString(R.string.gatewaytimeout); } else if (exc instanceof AuthorizationException) { msg += getString(R.string.badcredentials); builder.setNeutralButton(R.string.ok, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { signout(null); } }); } } builder.setMessage(msg); builder.setTitle(getString(R.string.error)); errorDialog = builder.create(); errorDialog.show(); errorDialog.setCancelable(false); dialogStyle(errorDialog); } /** * Checks internet connection. Shows a dialog if it ain't available. */ public boolean checkConnection() { ConnectivityManager connectivityManager = (ConnectivityManager) this .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = connectivityManager.getActiveNetworkInfo(); if ((noConnectionDialog == null || !noConnectionDialog.isShowing()) && (info == null || !info.isConnected() || !info.isAvailable())) { Builder builder = new Builder(this); builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setMessage(getString(R.string.noconnection)); builder.setCancelable(false); builder.setNeutralButton(R.string.ok, null); builder.setTitle(getString(R.string.error)); noConnectionDialog = builder.create(); noConnectionDialog.show(); dialogStyle(noConnectionDialog); return false; } else { return true; } } /** * <b>Call always after dialog.show!!!!!!!!!</b> * * @param alertDialog */ public void dialogStyle(AlertDialog alertDialog) { TextView textView = (TextView) alertDialog.findViewById(android.R.id.message); if (textView != null) { textView.setBackgroundDrawable(null); textView.setTextAppearance(this, R.style.muspydialogmessage); } Button button = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); if (button != null) { button.setBackgroundDrawable(getResources().getDrawable(R.drawable.textbuttonselector)); } button = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setBackgroundDrawable(getResources().getDrawable(R.drawable.textbuttonselector)); } button = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL); if (button != null) { button.setBackgroundDrawable(getResources().getDrawable(R.drawable.textbuttonselector)); } } /** * Muspy logo */ public void goToMuspy(View view) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.URL)); defaultTransition(intent); ; } /** * ProgressDialog should be cancelable (useful for slow connections). * @param message (loading by default) */ public void showProgressDialog(String s) { if (s == null) { s = getString(R.string.loading); } progressDialog = ProgressDialog.show(this, "", s, true); progressDialog.setCancelable(true); dialogStyle(progressDialog); } public ProgressDialog getProgressDialog() { return progressDialog; } public Builder createInfoDialog(String message) { Builder builder = new Builder(this); builder.setTitle(R.string.infotitle); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setMessage(message); return builder; } public boolean isShowingNoConnection() { return noConnectionDialog != null && noConnectionDialog.isShowing(); } public boolean isShowingError() { return errorDialog != null && errorDialog.isShowing(); } public AlertDialog getNoConnectionDialog() { return noConnectionDialog; } }