Java tutorial
/*------------------------------------------------------------------------------ ** Ident: Sogeti Smart Mobile Solutions ** Author: rene ** Copyright: (c) Apr 24, 2011 Sogeti Nederland B.V. All Rights Reserved. **------------------------------------------------------------------------------ ** Sogeti Nederland B.V. | No part of this file may be reproduced ** Distributed Software Engineering | or transmitted in any form or by any ** Lange Dreef 17 | means, electronic or mechanical, for the ** 4131 NJ Vianen | purpose, without the express written ** The Netherlands | permission of the copyright holder. *------------------------------------------------------------------------------ * * This file is part of OpenGPSTracker. * * OpenGPSTracker 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. * * OpenGPSTracker 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 OpenGPSTracker. If not, see <http://www.gnu.org/licenses/>. * */ package nl.sogeti.android.gpstracker.actions; import android.app.Dialog; import android.content.ContentResolver; import android.content.Intent; import android.database.ContentObserver; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.NavUtils; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog.Builder; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.ContextMenu; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.Button; import android.widget.TextView; import android.widget.ViewFlipper; import nl.sogeti.android.gpstracker.R; import nl.sogeti.android.gpstracker.actions.utils.GraphCanvas; import nl.sogeti.android.gpstracker.actions.utils.StatisticsCalulator; import nl.sogeti.android.gpstracker.actions.utils.StatisticsDelegate; import nl.sogeti.android.gpstracker.service.db.GPStracking.Tracks; import nl.sogeti.android.gpstracker.util.UnitsI18n; import nl.sogeti.android.gpstracker.viewer.TrackList; import nl.sogeti.android.log.Log; /** * Display some calulations based on a track * * @author rene (c) Oct 19, 2009, Sogeti B.V. * @version $Id$ */ public class Statistics extends AppCompatActivity implements StatisticsDelegate { private static final int DIALOG_GRAPHTYPE = 3; private static final int MENU_GRAPHTYPE = 11; private static final int MENU_TRACKLIST = 12; private static final int MENU_SHARE = 41; private static final String TRACKURI = "TRACKURI"; private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private Uri mTrackUri = null; private boolean calculating; private TextView overallavgSpeedView; private TextView avgSpeedView; private TextView distanceView; private TextView endtimeView; private TextView starttimeView; private TextView maxSpeedView; private TextView waypointsView; private TextView mAscensionView; private TextView mElapsedTimeView; private UnitsI18n mUnits; private final ContentObserver mTrackObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfUpdate) { if (!calculating) { Statistics.this.drawTrackingStatistics(); } } }; private GraphCanvas mGraphTimeSpeed; private ViewFlipper mViewFlipper; private Animation mSlideLeftIn; private Animation mSlideLeftOut; private Animation mSlideRightIn; private Animation mSlideRightOut; private GestureDetector mGestureDetector; private GraphCanvas mGraphDistanceSpeed; private GraphCanvas mGraphTimeAltitude; private GraphCanvas mGraphDistanceAltitude; private OnClickListener mGraphControlListener = new View.OnClickListener() { @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.graphtype_timespeed: mViewFlipper.setDisplayedChild(0); break; case R.id.graphtype_distancespeed: mViewFlipper.setDisplayedChild(1); break; case R.id.graphtype_timealtitude: mViewFlipper.setDisplayedChild(2); break; case R.id.graphtype_distancealtitude: mViewFlipper.setDisplayedChild(3); break; default: break; } dismissDialog(DIALOG_GRAPHTYPE); } }; /** * Called when the activity is first created. */ @Override protected void onCreate(Bundle load) { super.onCreate(load); mUnits = new UnitsI18n(this, new UnitsI18n.UnitsChangeListener() { @Override public void onUnitsChange() { drawTrackingStatistics(); } }); setContentView(R.layout.statistics); Toolbar toolbar = (Toolbar) findViewById(R.id.support_actionbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mViewFlipper = (ViewFlipper) findViewById(R.id.flipper); mViewFlipper.setDrawingCacheEnabled(true); mSlideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in); mSlideLeftOut = AnimationUtils.loadAnimation(this, R.anim.slide_left_out); mSlideRightIn = AnimationUtils.loadAnimation(this, R.anim.slide_right_in); mSlideRightOut = AnimationUtils.loadAnimation(this, R.anim.slide_right_out); mGraphTimeSpeed = (GraphCanvas) mViewFlipper.getChildAt(0); mGraphDistanceSpeed = (GraphCanvas) mViewFlipper.getChildAt(1); mGraphTimeAltitude = (GraphCanvas) mViewFlipper.getChildAt(2); mGraphDistanceAltitude = (GraphCanvas) mViewFlipper.getChildAt(3); mGraphTimeSpeed.setType(GraphCanvas.TIMESPEEDGRAPH); mGraphDistanceSpeed.setType(GraphCanvas.DISTANCESPEEDGRAPH); mGraphTimeAltitude.setType(GraphCanvas.TIMEALTITUDEGRAPH); mGraphDistanceAltitude.setType(GraphCanvas.DISTANCEALTITUDEGRAPH); mGestureDetector = new GestureDetector(new MyGestureDetector()); maxSpeedView = (TextView) findViewById(R.id.stat_maximumspeed); mAscensionView = (TextView) findViewById(R.id.stat_ascension); mElapsedTimeView = (TextView) findViewById(R.id.stat_elapsedtime); overallavgSpeedView = (TextView) findViewById(R.id.stat_overallaveragespeed); avgSpeedView = (TextView) findViewById(R.id.stat_averagespeed); distanceView = (TextView) findViewById(R.id.stat_distance); starttimeView = (TextView) findViewById(R.id.stat_starttime); endtimeView = (TextView) findViewById(R.id.stat_endtime); waypointsView = (TextView) findViewById(R.id.stat_waypoints); if (load != null && load.containsKey(TRACKURI)) { mTrackUri = Uri.withAppendedPath(Tracks.CONTENT_URI, load.getString(TRACKURI)); } else { mTrackUri = this.getIntent().getData(); } } @Override protected void onRestoreInstanceState(Bundle load) { if (load != null) { super.onRestoreInstanceState(load); } if (load != null && load.containsKey(TRACKURI)) { mTrackUri = Uri.withAppendedPath(Tracks.CONTENT_URI, load.getString(TRACKURI)); } if (load != null && load.containsKey("FLIP")) { mViewFlipper.setDisplayedChild(load.getInt("FLIP")); } } /* * (non-Javadoc) * @see android.app.Activity#onResume() */ @Override protected void onResume() { super.onResume(); drawTrackingStatistics(); ContentResolver resolver = this.getContentResolver(); resolver.registerContentObserver(mTrackUri, true, this.mTrackObserver); } @Override protected void onSaveInstanceState(Bundle save) { super.onSaveInstanceState(save); save.putString(TRACKURI, mTrackUri.getLastPathSegment()); save.putInt("FLIP", mViewFlipper.getDisplayedChild()); } /* * (non-Javadoc) * @see android.app.Activity#onPause() */ @Override protected void onPause() { super.onPause(); mViewFlipper.stopFlipping(); mGraphTimeSpeed.clearData(); mGraphDistanceSpeed.clearData(); mGraphTimeAltitude.clearData(); mGraphDistanceAltitude.clearData(); ContentResolver resolver = this.getContentResolver(); resolver.unregisterContentObserver(this.mTrackObserver); } @Override public boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } else { return false; } } @Override public boolean onCreateOptionsMenu(Menu menu) { boolean result = super.onCreateOptionsMenu(menu); MenuItem item; item = menu.add(ContextMenu.NONE, MENU_SHARE, ContextMenu.NONE, R.string.menu_shareTrack) .setIcon(R.drawable.ic_share_24dp).setAlphabeticShortcut('s'); MenuItemCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_ALWAYS); item = menu.add(ContextMenu.NONE, MENU_TRACKLIST, ContextMenu.NONE, R.string.menu_tracklist) .setIcon(R.drawable.ic_list_24dp).setAlphabeticShortcut('l'); MenuItemCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_ALWAYS); item = menu.add(ContextMenu.NONE, MENU_GRAPHTYPE, ContextMenu.NONE, R.string.menu_graphtype) .setIcon(R.drawable.ic_graph_24dp).setAlphabeticShortcut('t'); MenuItemCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_NEVER); return result; } @Override public boolean onOptionsItemSelected(MenuItem item) { boolean handled = false; Intent intent; switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpFromSameTask(this); handled = true; break; case MENU_GRAPHTYPE: showDialog(DIALOG_GRAPHTYPE); handled = true; break; case MENU_TRACKLIST: intent = new Intent(this, TrackList.class); intent.putExtra(Tracks._ID, mTrackUri.getLastPathSegment()); startActivityForResult(intent, MENU_TRACKLIST); break; case MENU_SHARE: intent = new Intent(Intent.ACTION_RUN); intent.setDataAndType(mTrackUri, Tracks.CONTENT_ITEM_TYPE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Bitmap bm = mViewFlipper.getDrawingCache(); Uri screenStreamUri = ShareTrack.storeScreenBitmap(bm); intent.putExtra(Intent.EXTRA_STREAM, screenStreamUri); startActivityForResult(Intent.createChooser(intent, getString(R.string.share_track)), MENU_SHARE); handled = true; break; default: handled = super.onOptionsItemSelected(item); } return handled; } /* * (non-Javadoc) * @see android.app.Activity#onCreateDialog(int) */ @Override protected Dialog onCreateDialog(int id) { Dialog dialog = null; LayoutInflater factory = null; View view = null; Builder builder = null; switch (id) { case DIALOG_GRAPHTYPE: builder = new AlertDialog.Builder(this); factory = LayoutInflater.from(this); view = factory.inflate(R.layout.graphtype, (ViewGroup) findViewById(android.R.id.content), false); builder.setTitle(R.string.dialog_graphtype_title).setIcon(android.R.drawable.ic_dialog_alert) .setNegativeButton(R.string.btn_cancel, null).setView(view); dialog = builder.create(); return dialog; default: return super.onCreateDialog(id); } } /* * (non-Javadoc) * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog) */ @Override protected void onPrepareDialog(int id, Dialog dialog) { switch (id) { case DIALOG_GRAPHTYPE: Button speedtime = (Button) dialog.findViewById(R.id.graphtype_timespeed); Button speeddistance = (Button) dialog.findViewById(R.id.graphtype_distancespeed); Button altitudetime = (Button) dialog.findViewById(R.id.graphtype_timealtitude); Button altitudedistance = (Button) dialog.findViewById(R.id.graphtype_distancealtitude); speedtime.setOnClickListener(mGraphControlListener); speeddistance.setOnClickListener(mGraphControlListener); altitudetime.setOnClickListener(mGraphControlListener); altitudedistance.setOnClickListener(mGraphControlListener); default: break; } super.onPrepareDialog(id, dialog); } /* * (non-Javadoc) * @see android.app.Activity#onActivityResult(int, int, android.content.Intent) */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); switch (requestCode) { case MENU_TRACKLIST: if (resultCode == RESULT_OK) { mTrackUri = intent.getData(); drawTrackingStatistics(); } break; case MENU_SHARE: ShareTrack.clearScreenBitmap(); break; default: Log.w(this, "Unknown activity result request code"); } } private void drawTrackingStatistics() { calculating = true; StatisticsCalulator calculator = new StatisticsCalulator(this, mUnits, this); calculator.execute(mTrackUri); } @Override public void finishedCalculations(StatisticsCalulator calculated) { mGraphTimeSpeed.setData(mTrackUri, calculated); mGraphDistanceSpeed.setData(mTrackUri, calculated); mGraphTimeAltitude.setData(mTrackUri, calculated); mGraphDistanceAltitude.setData(mTrackUri, calculated); mViewFlipper.postInvalidate(); maxSpeedView.setText(calculated.getMaxSpeedText()); mElapsedTimeView.setText(calculated.getDurationText()); mAscensionView.setText(calculated.getAscensionText()); overallavgSpeedView.setText(calculated.getOverallavgSpeedText()); avgSpeedView.setText(calculated.getAvgSpeedText()); distanceView.setText(calculated.getDistanceText()); starttimeView.setText(Long.toString(calculated.getStarttime())); endtimeView.setText(Long.toString(calculated.getEndtime())); setTitle(calculated.getTracknameText()); waypointsView.setText(calculated.getWaypointsText()); calculating = false; } class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) { return false; } // right to left swipe if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { mViewFlipper.setInAnimation(mSlideLeftIn); mViewFlipper.setOutAnimation(mSlideLeftOut); mViewFlipper.showNext(); } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { mViewFlipper.setInAnimation(mSlideRightIn); mViewFlipper.setOutAnimation(mSlideRightOut); mViewFlipper.showPrevious(); } return false; } } }