/* * Copyright (C) 2010- Peer internet solutions * * This file is part of mixare. * * 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 org.mixare; /** * This class is the main application which uses the other classes for different * functionalities. * It sets up the camera screen and the augmented screen which is in front of the * camera screen. * It also handles the main sensor events, touch events and location events. */ import static android.hardware.SensorManager.SENSOR_DELAY_GAME; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.mixare.R.drawable; import org.mixare.data.DataHandler; import org.mixare.data.DataSourceList; import org.mixare.data.DataSourceStorage; import org.mixare.lib.gui.PaintScreen; import org.mixare.lib.marker.Marker; import org.mixare.lib.render.Matrix; import android.app.Activity; import android.app.AlertDialog; import android.app.SearchManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.hardware.Camera; import android.hardware.GeomagneticField; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.location.Location; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.provider.Settings; import android.util.FloatMath; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.widget.FrameLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; public class MixView extends Activity implements SensorEventListener, OnTouchListener { private CameraSurface camScreen; private AugmentedView augScreen; private boolean isInited; private static PaintScreen dWindow; private static DataView dataView; private boolean fError; //---------- private MixViewDataHolder mixViewData ; // TAG for logging public static final String TAG = "Mixare"; // why use Memory to save a state? MixContext? activity lifecycle? //private static MixView CONTEXT; /* string to name & access the preference file in the internal storage */ public static final String PREFS_NAME = "MyPrefsFileForMenuItems"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //MixView.CONTEXT = this; try { handleIntent(getIntent()); final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); getMixViewData().setmWakeLock(pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My Tag")); killOnError(); requestWindowFeature(Window.FEATURE_NO_TITLE); maintainCamera(); maintainAugmentR(); maintainZoomBar(); if (!isInited) { //getMixViewData().setMixContext(new MixContext(this)); //getMixViewData().getMixContext().setDownloadManager(new DownloadManager(mixViewData.getMixContext())); setdWindow(new PaintScreen()); setDataView(new DataView(getMixViewData().getMixContext())); /* set the radius in data view to the last selected by the user */ setZoomLevel(); isInited = true; } /*Get the preference file PREFS_NAME stored in the internal memory of the phone*/ SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); /*check if the application is launched for the first time*/ if(settings.getBoolean("firstAccess",false)==false){ firstAccess(settings); } } catch (Exception ex) { doError(ex); } } public MixViewDataHolder getMixViewData() { if (mixViewData==null){ // TODO: VERY inportant, only one! mixViewData = new MixViewDataHolder(new MixContext(this)); } return mixViewData; } @Override protected void onPause() { super.onPause(); try { this.getMixViewData().getmWakeLock().release(); try { getMixViewData().getSensorMgr().unregisterListener(this, getMixViewData().getSensorGrav()); getMixViewData().getSensorMgr().unregisterListener(this, getMixViewData().getSensorMag()); getMixViewData().setSensorMgr(null); getMixViewData().getMixContext().getLocationFinder().switchOff(); getMixViewData().getMixContext().getDownloadManager().switchOff(); if (getDataView() != null) { getDataView().cancelRefreshTimer(); } } catch (Exception ignore) { } if (fError) { finish(); } } catch (Exception ex) { doError(ex); } } /** * {@inheritDoc} * Mixare - Receives results from other launched activities * Base on the result returned, it either refreshes screen or not. * Default value for refreshing is false */ protected void onActivityResult(final int requestCode, final int resultCode, Intent data) { Log.d(TAG + " WorkFlow", "MixView - onActivityResult Called"); // check if the returned is request to refresh screen (setting might be // changed) try { if (data.getBooleanExtra("RefreshScreen", false)) { Log.d(TAG + " WorkFlow", "MixView - Received Refresh Screen Request .. about to refresh"); repaint(); refreshDownload(); } } catch (Exception ex) { // do nothing do to mix of return results. } } @Override protected void onResume() { super.onResume(); try { this.getMixViewData().getmWakeLock().acquire(); killOnError(); getMixViewData().getMixContext().doResume(this); repaint(); getDataView().doStart(); getDataView().clearEvents(); getMixViewData().getMixContext().getDataSourceManager().refreshDataSources(); float angleX, angleY; int marker_orientation = -90; int rotation = Compatibility.getRotation(this); // display text from left to right and keep it horizontal angleX = (float) Math.toRadians(marker_orientation); getMixViewData().getM1().set(1f, 0f, 0f, 0f, (float) FloatMath.cos(angleX), (float) -FloatMath.sin(angleX), 0f, (float) FloatMath.sin(angleX), (float) FloatMath.cos(angleX)); angleX = (float) Math.toRadians(marker_orientation); angleY = (float) Math.toRadians(marker_orientation); if (rotation == 1) { getMixViewData().getM2().set(1f, 0f, 0f, 0f, (float) FloatMath.cos(angleX), (float) -FloatMath.sin(angleX), 0f, (float) FloatMath.sin(angleX), (float) FloatMath.cos(angleX)); getMixViewData().getM3().set((float) FloatMath.cos(angleY), 0f, (float) FloatMath.sin(angleY), 0f, 1f, 0f, (float) -FloatMath.sin(angleY), 0f, (float) FloatMath.cos(angleY)); } else { getMixViewData().getM2().set((float) FloatMath.cos(angleX), 0f, (float) FloatMath.sin(angleX), 0f, 1f, 0f, (float) -FloatMath.sin(angleX), 0f, (float) FloatMath.cos(angleX)); getMixViewData().getM3().set(1f, 0f, 0f, 0f, (float) FloatMath.cos(angleY), (float) -FloatMath.sin(angleY), 0f, (float) FloatMath.sin(angleY), (float) FloatMath.cos(angleY)); } getMixViewData().getM4().toIdentity(); for (int i = 0; i < getMixViewData().getHistR().length; i++) { getMixViewData().getHistR()[i] = new Matrix(); } getMixViewData() .setSensorMgr((SensorManager) getSystemService(SENSOR_SERVICE)); getMixViewData().setSensors(getMixViewData().getSensorMgr().getSensorList( Sensor.TYPE_ACCELEROMETER)); if (getMixViewData().getSensors().size() > 0) { getMixViewData().setSensorGrav(getMixViewData().getSensors().get(0)); } getMixViewData().setSensors(getMixViewData().getSensorMgr().getSensorList( Sensor.TYPE_MAGNETIC_FIELD)); if (getMixViewData().getSensors().size() > 0) { getMixViewData().setSensorMag(getMixViewData().getSensors().get(0)); } getMixViewData().getSensorMgr().registerListener(this, getMixViewData().getSensorGrav(), SENSOR_DELAY_GAME); getMixViewData().getSensorMgr().registerListener(this, getMixViewData().getSensorMag(), SENSOR_DELAY_GAME); try { GeomagneticField gmf = getMixViewData().getMixContext().getLocationFinder().getGeomagneticField(); angleY = (float) Math.toRadians(-gmf.getDeclination()); getMixViewData().getM4().set((float) FloatMath.cos(angleY), 0f, (float) FloatMath.sin(angleY), 0f, 1f, 0f, (float) -FloatMath.sin(angleY), 0f, (float) FloatMath.cos(angleY)); } catch (Exception ex) { Log.d("mixare", "GPS Initialize Error", ex); } getMixViewData().getMixContext().getDownloadManager().switchOn(); getMixViewData().getMixContext().getLocationFinder().switchOn(); } catch (Exception ex) { doError(ex); try { if (getMixViewData().getSensorMgr() != null) { getMixViewData().getSensorMgr().unregisterListener(this, getMixViewData().getSensorGrav()); getMixViewData().getSensorMgr().unregisterListener(this, getMixViewData().getSensorMag()); getMixViewData().setSensorMgr(null); } if (getMixViewData().getMixContext() != null) { getMixViewData().getMixContext().getLocationFinder().switchOff(); getMixViewData().getMixContext().getDownloadManager().switchOff(); } } catch (Exception ignore) { } } Log.d("-------------------------------------------", "resume"); if (getDataView().isFrozen() && getMixViewData().getSearchNotificationTxt() == null) { getMixViewData().setSearchNotificationTxt(new TextView(this)); getMixViewData().getSearchNotificationTxt().setWidth( getdWindow().getWidth()); getMixViewData().getSearchNotificationTxt().setPadding(10, 2, 0, 0); getMixViewData().getSearchNotificationTxt().setText( getString(R.string.search_active_1) + " " + DataSourceList.getDataSourcesStringList() + getString(R.string.search_active_2)); ; getMixViewData().getSearchNotificationTxt().setBackgroundColor( Color.DKGRAY); getMixViewData().getSearchNotificationTxt().setTextColor(Color.WHITE); getMixViewData().getSearchNotificationTxt().setOnTouchListener(this); addContentView(getMixViewData().getSearchNotificationTxt(), new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); } else if (!getDataView().isFrozen() && getMixViewData().getSearchNotificationTxt() != null) { getMixViewData().getSearchNotificationTxt().setVisibility(View.GONE); getMixViewData().setSearchNotificationTxt(null); } } /** * {@inheritDoc} * Customize Activity after switching back to it. * Currently it maintain and ensures view creation. */ protected void onRestart (){ super.onRestart(); maintainCamera(); maintainAugmentR(); maintainZoomBar(); } /* ********* Operators ***********/ public void repaint() { //clear stored data getDataView().clearEvents(); setDataView(null); //It's smelly code, but enforce garbage collector //to release data. setDataView(new DataView(mixViewData.getMixContext())); setdWindow(new PaintScreen()); //setZoomLevel(); //@TODO Caller has to set the zoom. This function repaints only. } /** * Checks camScreen, if it does not exist, it creates one. */ private void maintainCamera() { if (camScreen == null){ camScreen = new CameraSurface(this); } setContentView(camScreen); } /** * Checks augScreen, if it does not exist, it creates one. */ private void maintainAugmentR() { if (augScreen == null ){ augScreen = new AugmentedView(this); } addContentView(augScreen, new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } /** * Creates a zoom bar and adds it to view. */ private void maintainZoomBar() { SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); FrameLayout frameLayout = createZoomBar(settings); addContentView(frameLayout, new FrameLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM)); } /** * Refreshes Download * TODO refresh downloads */ private void refreshDownload(){ // try { // if (getMixViewData().getDownloadThread() != null){ // if (!getMixViewData().getDownloadThread().isInterrupted()){ // getMixViewData().getDownloadThread().interrupt(); // getMixViewData().getMixContext().getDownloadManager().restart(); // } // }else { //if no download thread found // getMixViewData().setDownloadThread(new Thread(getMixViewData() // .getMixContext().getDownloadManager())); // //@TODO Syncronize DownloadManager, call Start instead of run. // mixViewData.getMixContext().getDownloadManager().run(); // } // }catch (Exception ex){ // } } public void refresh(){ dataView.refresh(); } public void setErrorDialog(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getString(R.string.connection_error_dialog)); builder.setCancelable(false); /*Retry*/ builder.setPositiveButton(R.string.connection_error_dialog_button1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { fError=false; //TODO improve try { maintainCamera(); maintainAugmentR(); repaint(); setZoomLevel(); } catch(Exception ex){ //Don't call doError, it will be a recursive call. //doError(ex); } } }); /*Open settings*/ builder.setNeutralButton(R.string.connection_error_dialog_button2, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent intent1 = new Intent(Settings.ACTION_WIRELESS_SETTINGS); startActivityForResult(intent1, 42); } }); /*Close application*/ builder.setNegativeButton(R.string.connection_error_dialog_button3, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { System.exit(0); //wouldn't be better to use finish (to stop the app normally?) } }); AlertDialog alert = builder.create(); alert.show(); } public float calcZoomLevel(){ int myZoomLevel = getMixViewData().getMyZoomBar().getProgress(); float myout = 5; if (myZoomLevel <= 26) { myout = myZoomLevel / 25f; } else if (25 < myZoomLevel && myZoomLevel < 50) { myout = (1 + (myZoomLevel - 25)) * 0.38f; } else if (25 == myZoomLevel) { myout = 1; } else if (50 == myZoomLevel) { myout = 10; } else if (50 < myZoomLevel && myZoomLevel < 75) { myout = (10 + (myZoomLevel - 50)) * 0.83f; } else { myout = (30 + (myZoomLevel - 75) * 2f); } return myout; } /** * Handle First time users. It display license agreement and store user's * acceptance. * * @param settings */ private void firstAccess(SharedPreferences settings) { SharedPreferences.Editor editor = settings.edit(); AlertDialog.Builder builder1 = new AlertDialog.Builder(this); builder1.setMessage(getString(R.string.license)); builder1.setNegativeButton(getString(R.string.close_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert1 = builder1.create(); alert1.setTitle(getString(R.string.license_title)); alert1.show(); editor.putBoolean("firstAccess", true); // value for maximum POI for each selected OSM URL to be active by // default is 5 editor.putInt("osmMaxObject", 5); editor.commit(); // add the default datasources to the preferences file DataSourceStorage.getInstance().fillDefaultDataSources(); } /** * Create zoom bar and returns FrameLayout. FrameLayout is created to be * hidden and not added to view, Caller needs to add the frameLayout to * view, and enable visibility when needed. * * @param SharedOreference settings where setting is stored * @return FrameLayout Hidden Zoom Bar */ private FrameLayout createZoomBar(SharedPreferences settings) { getMixViewData().setMyZoomBar(new SeekBar(this)); getMixViewData().getMyZoomBar().setMax(100); getMixViewData().getMyZoomBar() .setProgress(settings.getInt("zoomLevel", 65)); getMixViewData().getMyZoomBar().setOnSeekBarChangeListener(myZoomBarOnSeekBarChangeListener); getMixViewData().getMyZoomBar().setVisibility(View.INVISIBLE); FrameLayout frameLayout = new FrameLayout(this); frameLayout.setMinimumWidth(3000); frameLayout.addView(getMixViewData().getMyZoomBar()); frameLayout.setPadding(10, 0, 10, 10); return frameLayout; } /* ********* Operator - Menu ******/ @Override public boolean onCreateOptionsMenu(Menu menu) { int base = Menu.FIRST; /* define the first */ MenuItem item1 = menu.add(base, base, base, getString(R.string.menu_item_1)); MenuItem item2 = menu.add(base, base + 1, base + 1, getString(R.string.menu_item_2)); MenuItem item3 = menu.add(base, base + 2, base + 2, getString(R.string.menu_item_3)); MenuItem item4 = menu.add(base, base + 3, base + 3, getString(R.string.menu_item_4)); MenuItem item5 = menu.add(base, base + 4, base + 4, getString(R.string.menu_item_5)); MenuItem item6 = menu.add(base, base + 5, base + 5, getString(R.string.menu_item_6)); MenuItem item7 = menu.add(base, base + 6, base + 6, getString(R.string.menu_item_7)); /* assign icons to the menu items */ item1.setIcon(drawable.icon_datasource); item2.setIcon(android.R.drawable.ic_menu_view); item3.setIcon(android.R.drawable.ic_menu_mapmode); item4.setIcon(android.R.drawable.ic_menu_zoom); item5.setIcon(android.R.drawable.ic_menu_search); item6.setIcon(android.R.drawable.ic_menu_info_details); item7.setIcon(android.R.drawable.ic_menu_share); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { /* Data sources */ case 1: if (!getDataView().isLauncherStarted()) { Intent intent = new Intent(MixView.this, DataSourceList.class); startActivityForResult(intent, 40); } else { Toast.makeText(this, getString(R.string.no_website_available), Toast.LENGTH_LONG).show(); } break; /* List view */ case 2: /* * if the list of titles to show in alternative list view is not * empty */ if (getDataView().getDataHandler().getMarkerCount() > 0) { Intent intent1 = new Intent(MixView.this, MixListView.class); startActivityForResult(intent1, 42); } /* if the list is empty */ else { Toast.makeText(this, R.string.empty_list, Toast.LENGTH_LONG) .show(); } break; /* Map View */ case 3: Intent intent2 = new Intent(MixView.this, MixMap.class); startActivityForResult(intent2, 20); break; /* zoom level */ case 4: getMixViewData().getMyZoomBar().setVisibility(View.VISIBLE); getMixViewData().setZoomProgress(getMixViewData().getMyZoomBar() .getProgress()); break; /* Search */ case 5: onSearchRequested(); break; /* GPS Information */ case 6: Location currentGPSInfo = getMixViewData().getMixContext().getLocationFinder().getCurrentLocation(); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getString(R.string.general_info_text) + "\n\n" + getString(R.string.longitude) + currentGPSInfo.getLongitude() + "\n" + getString(R.string.latitude) + currentGPSInfo.getLatitude() + "\n" + getString(R.string.altitude) + currentGPSInfo.getAltitude() + "m\n" + getString(R.string.speed) + currentGPSInfo.getSpeed() + "km/h\n" + getString(R.string.accuracy) + currentGPSInfo.getAccuracy() + "m\n" + getString(R.string.gps_last_fix) + new Date(currentGPSInfo.getTime()).toString() + "\n"); builder.setNegativeButton(getString(R.string.close_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.setTitle(getString(R.string.general_info_title)); alert.show(); break; /* Case 6: license agreements */ case 7: AlertDialog.Builder builder1 = new AlertDialog.Builder(this); builder1.setMessage(getString(R.string.license)); /* Retry */ builder1.setNegativeButton(getString(R.string.close_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert1 = builder1.create(); alert1.setTitle(getString(R.string.license_title)); alert1.show(); break; } return true; } /* ******** Operators - Sensors ****** */ private SeekBar.OnSeekBarChangeListener myZoomBarOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { Toast t; public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float myout = calcZoomLevel(); getMixViewData().setZoomLevel(String.valueOf(myout)); getMixViewData().setZoomProgress(getMixViewData().getMyZoomBar() .getProgress()); t.setText("Radius: " + String.valueOf(myout)); t.show(); } public void onStartTrackingTouch(SeekBar seekBar) { Context ctx = seekBar.getContext(); t = Toast.makeText(ctx, "Radius: ", Toast.LENGTH_LONG); // zoomChanging= true; } public void onStopTrackingTouch(SeekBar seekBar) { SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); /* store the zoom range of the zoom bar selected by the user */ editor.putInt("zoomLevel", getMixViewData().getMyZoomBar().getProgress()); editor.commit(); getMixViewData().getMyZoomBar().setVisibility(View.INVISIBLE); // zoomChanging= false; getMixViewData().getMyZoomBar().getProgress(); t.cancel(); //repaint after zoom level changed. repaint(); setZoomLevel(); } }; public void onSensorChanged(SensorEvent evt) { try { if (evt.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { getMixViewData().getGrav()[0] = evt.values[0]; getMixViewData().getGrav()[1] = evt.values[1]; getMixViewData().getGrav()[2] = evt.values[2]; augScreen.postInvalidate(); } else if (evt.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { getMixViewData().getMag()[0] = evt.values[0]; getMixViewData().getMag()[1] = evt.values[1]; getMixViewData().getMag()[2] = evt.values[2]; augScreen.postInvalidate(); } SensorManager.getRotationMatrix(getMixViewData().getRTmp(), getMixViewData().getI(), getMixViewData().getGrav(), getMixViewData().getMag()); int rotation = Compatibility.getRotation(this); if (rotation == 1) { SensorManager.remapCoordinateSystem(getMixViewData().getRTmp(), SensorManager.AXIS_X, SensorManager.AXIS_MINUS_Z, getMixViewData().getRot()); } else { SensorManager.remapCoordinateSystem(getMixViewData().getRTmp(), SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_Z, getMixViewData().getRot()); } getMixViewData().getTempR().set(getMixViewData().getRot()[0], getMixViewData().getRot()[1], getMixViewData().getRot()[2], getMixViewData().getRot()[3], getMixViewData().getRot()[4], getMixViewData().getRot()[5], getMixViewData().getRot()[6], getMixViewData().getRot()[7], getMixViewData().getRot()[8]); getMixViewData().getFinalR().toIdentity(); getMixViewData().getFinalR().prod(getMixViewData().getM4()); getMixViewData().getFinalR().prod(getMixViewData().getM1()); getMixViewData().getFinalR().prod(getMixViewData().getTempR()); getMixViewData().getFinalR().prod(getMixViewData().getM3()); getMixViewData().getFinalR().prod(getMixViewData().getM2()); getMixViewData().getFinalR().invert(); getMixViewData().getHistR()[getMixViewData().getrHistIdx()].set(getMixViewData() .getFinalR()); getMixViewData().setrHistIdx(getMixViewData().getrHistIdx() + 1); if (getMixViewData().getrHistIdx() >= getMixViewData().getHistR().length) getMixViewData().setrHistIdx(0); getMixViewData().getSmoothR().set(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f); for (int i = 0; i < getMixViewData().getHistR().length; i++) { getMixViewData().getSmoothR().add(getMixViewData().getHistR()[i]); } getMixViewData().getSmoothR().mult( 1 / (float) getMixViewData().getHistR().length); getMixViewData().getMixContext().updateSmoothRotation(getMixViewData().getSmoothR()); } catch (Exception ex) { ex.printStackTrace(); } } @Override public boolean onTouchEvent(MotionEvent me) { try { killOnError(); float xPress = me.getX(); float yPress = me.getY(); if (me.getAction() == MotionEvent.ACTION_UP) { getDataView().clickEvent(xPress, yPress); }//TODO add gesture events (low) return true; } catch (Exception ex) { // doError(ex); ex.printStackTrace(); return super.onTouchEvent(me); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { try { killOnError(); if (keyCode == KeyEvent.KEYCODE_BACK) { if (getDataView().isDetailsView()) { getDataView().keyEvent(keyCode); getDataView().setDetailsView(false); return true; } else { //TODO handle keyback to finish app correctly return super.onKeyDown(keyCode, event); } } else if (keyCode == KeyEvent.KEYCODE_MENU) { return super.onKeyDown(keyCode, event); } else { getDataView().keyEvent(keyCode); return false; } } catch (Exception ex) { ex.printStackTrace(); return super.onKeyDown(keyCode, event); } } public void onAccuracyChanged(Sensor sensor, int accuracy) { if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD && accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE && getMixViewData().getCompassErrorDisplayed() == 0) { for (int i = 0; i < 2; i++) { Toast.makeText(getMixViewData().getMixContext(), "Compass data unreliable. Please recalibrate compass.", Toast.LENGTH_LONG).show(); } getMixViewData().setCompassErrorDisplayed(getMixViewData() .getCompassErrorDisplayed() + 1); } } @Override public boolean onTouch(View v, MotionEvent event) { getDataView().setFrozen(false); if (getMixViewData().getSearchNotificationTxt() != null) { getMixViewData().getSearchNotificationTxt().setVisibility(View.GONE); getMixViewData().setSearchNotificationTxt(null); } return false; } /* ************ Handlers *************/ public void doError(Exception ex1) { if (!fError) { fError = true; setErrorDialog(); ex1.printStackTrace(); try { } catch (Exception ex2) { ex2.printStackTrace(); } } try { augScreen.invalidate(); } catch (Exception ignore) { } } public void killOnError() throws Exception { if (fError) throw new Exception(); } private void handleIntent(Intent intent) { if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); doMixSearch(query); } } @Override protected void onNewIntent(Intent intent) { setIntent(intent); handleIntent(intent); } private void doMixSearch(String query) { DataHandler jLayer = getDataView().getDataHandler(); if (!getDataView().isFrozen()) { MixListView.originalMarkerList = jLayer.getMarkerList(); MixMap.originalMarkerList = jLayer.getMarkerList(); } ArrayList<Marker> searchResults = new ArrayList<Marker>(); Log.d("SEARCH-------------------0", "" + query); if (jLayer.getMarkerCount() > 0) { for (int i = 0; i < jLayer.getMarkerCount(); i++) { Marker ma = jLayer.getMarker(i); if (ma.getTitle().toLowerCase().indexOf(query.toLowerCase()) != -1) { searchResults.add(ma); /* the website for the corresponding title */ } } } if (searchResults.size() > 0) { getDataView().setFrozen(true); jLayer.setMarkerList(searchResults); } else Toast.makeText(this, getString(R.string.search_failed_notification), Toast.LENGTH_LONG).show(); } /* ******* Getter and Setters ********** */ public boolean isZoombarVisible() { return getMixViewData().getMyZoomBar() != null && getMixViewData().getMyZoomBar().getVisibility() == View.VISIBLE; } public String getZoomLevel() { return getMixViewData().getZoomLevel(); } /** * @return the dWindow */ static PaintScreen getdWindow() { return dWindow; } /** * @param dWindow * the dWindow to set */ static void setdWindow(PaintScreen dWindow) { MixView.dWindow = dWindow; } /** * @return the dataView */ static DataView getDataView() { return dataView; } /** * @param dataView * the dataView to set */ static void setDataView(DataView dataView) { MixView.dataView = dataView; } public int getZoomProgress() { return getMixViewData().getZoomProgress(); } private void setZoomLevel() { float myout = calcZoomLevel(); getDataView().setRadius(myout); //caller has the to control of zoombar visibility, not setzoom //mixViewData.getMyZoomBar().setVisibility(View.INVISIBLE); mixViewData.setZoomLevel(String.valueOf(myout)); //setZoomLevel, caller has to call refreash download if needed. // mixViewData.setDownloadThread(new Thread(mixViewData.getMixContext().getDownloadManager())); // mixViewData.getDownloadThread().start(); getMixViewData().getMixContext().getDownloadManager().switchOn(); }; } /** * @author daniele * */ class CameraSurface extends SurfaceView implements SurfaceHolder.Callback { MixView app; SurfaceHolder holder; Camera camera; CameraSurface(Context context) { super(context); try { app = (MixView) context; holder = getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } catch (Exception ex) { } } public void surfaceCreated(SurfaceHolder holder) { try { if (camera != null) { try { camera.stopPreview(); } catch (Exception ignore) { } try { camera.release(); } catch (Exception ignore) { } camera = null; } camera = Camera.open(); camera.setPreviewDisplay(holder); } catch (Exception ex) { try { if (camera != null) { try { camera.stopPreview(); } catch (Exception ignore) { } try { camera.release(); } catch (Exception ignore) { } camera = null; } } catch (Exception ignore) { } } } public void surfaceDestroyed(SurfaceHolder holder) { try { if (camera != null) { try { camera.stopPreview(); } catch (Exception ignore) { } try { camera.release(); } catch (Exception ignore) { } camera = null; } } catch (Exception ex) { ex.printStackTrace(); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { try { Camera.Parameters parameters = camera.getParameters(); try { List<Camera.Size> supportedSizes = null; // On older devices (<1.6) the following will fail // the camera will work nevertheless supportedSizes = Compatibility.getSupportedPreviewSizes(parameters); // preview form factor float ff = (float) w / h; Log.d("Mixare", "Screen res: w:" + w + " h:" + h + " aspect ratio:" + ff); // holder for the best form factor and size float bff = 0; int bestw = 0; int besth = 0; Iterator<Camera.Size> itr = supportedSizes.iterator(); // we look for the best preview size, it has to be the closest // to the // screen form factor, and be less wide than the screen itself // the latter requirement is because the HTC Hero with update // 2.1 will // report camera preview sizes larger than the screen, and it // will fail // to initialize the camera // other devices could work with previews larger than the screen // though while (itr.hasNext()) { Camera.Size element = itr.next(); // current form factor float cff = (float) element.width / element.height; // check if the current element is a candidate to replace // the best match so far // current form factor should be closer to the bff // preview width should be less than screen width // preview width should be more than current bestw // this combination will ensure that the highest resolution // will win Log.d("Mixare", "Candidate camera element: w:" + element.width + " h:" + element.height + " aspect ratio:" + cff); if ((ff - cff <= ff - bff) && (element.width <= w) && (element.width >= bestw)) { bff = cff; bestw = element.width; besth = element.height; } } Log.d("Mixare", "Chosen camera element: w:" + bestw + " h:" + besth + " aspect ratio:" + bff); // Some Samsung phones will end up with bestw and besth = 0 // because their minimum preview size is bigger then the screen // size. // In this case, we use the default values: 480x320 if ((bestw == 0) || (besth == 0)) { Log.d("Mixare", "Using default camera parameters!"); bestw = 480; besth = 320; } parameters.setPreviewSize(bestw, besth); } catch (Exception ex) { parameters.setPreviewSize(480, 320); } camera.setParameters(parameters); camera.startPreview(); } catch (Exception ex) { ex.printStackTrace(); } } } class AugmentedView extends View { MixView app; int xSearch = 200; int ySearch = 10; int searchObjWidth = 0; int searchObjHeight = 0; Paint zoomPaint = new Paint(); public AugmentedView(Context context) { super(context); try { app = (MixView) context; app.killOnError(); } catch (Exception ex) { app.doError(ex); } } @Override protected void onDraw(Canvas canvas) { try { // if (app.fError) { // // Paint errPaint = new Paint(); // errPaint.setColor(Color.RED); // errPaint.setTextSize(16); // // /*Draws the Error code*/ // canvas.drawText("ERROR: ", 10, 20, errPaint); // canvas.drawText("" + app.fErrorTxt, 10, 40, errPaint); // // return; // } app.killOnError(); MixView.getdWindow().setWidth(canvas.getWidth()); MixView.getdWindow().setHeight(canvas.getHeight()); MixView.getdWindow().setCanvas(canvas); if (!MixView.getDataView().isInited()) { MixView.getDataView().init(MixView.getdWindow().getWidth(), MixView.getdWindow().getHeight()); } if (app.isZoombarVisible()) { zoomPaint.setColor(Color.WHITE); zoomPaint.setTextSize(14); String startKM, endKM; endKM = "80km"; startKM = "0km"; /* * if(MixListView.getDataSource().equals("Twitter")){ startKM = * "1km"; } */ canvas.drawText(startKM, canvas.getWidth() / 100 * 4, canvas.getHeight() / 100 * 85, zoomPaint); canvas.drawText(endKM, canvas.getWidth() / 100 * 99 + 25, canvas.getHeight() / 100 * 85, zoomPaint); int height = canvas.getHeight() / 100 * 85; int zoomProgress = app.getZoomProgress(); if (zoomProgress > 92 || zoomProgress < 6) { height = canvas.getHeight() / 100 * 80; } canvas.drawText(app.getZoomLevel(), (canvas.getWidth()) / 100 * zoomProgress + 20, height, zoomPaint); } MixView.getDataView().draw(MixView.getdWindow()); } catch (Exception ex) { app.doError(ex); } } } /** * Internal class that holds Mixview field Data. * * @author A B */ class MixViewDataHolder { private final MixContext mixContext; private float[] RTmp; private float[] Rot; private float[] I; private float[] grav; private float[] mag; private SensorManager sensorMgr; private List<Sensor> sensors; private Sensor sensorGrav; private Sensor sensorMag; private int rHistIdx; private Matrix tempR; private Matrix finalR; private Matrix smoothR; private Matrix[] histR; private Matrix m1; private Matrix m2; private Matrix m3; private Matrix m4; private SeekBar myZoomBar; private WakeLock mWakeLock; private int compassErrorDisplayed; private String zoomLevel; private int zoomProgress; private TextView searchNotificationTxt; public MixViewDataHolder(MixContext mixContext) { this.mixContext=mixContext; this.RTmp = new float[9]; this.Rot = new float[9]; this.I = new float[9]; this.grav = new float[3]; this.mag = new float[3]; this.rHistIdx = 0; this.tempR = new Matrix(); this.finalR = new Matrix(); this.smoothR = new Matrix(); this.histR = new Matrix[60]; this.m1 = new Matrix(); this.m2 = new Matrix(); this.m3 = new Matrix(); this.m4 = new Matrix(); this.compassErrorDisplayed = 0; } /* ******* Getter and Setters ********** */ public MixContext getMixContext() { return mixContext; } public float[] getRTmp() { return RTmp; } public void setRTmp(float[] rTmp) { RTmp = rTmp; } public float[] getRot() { return Rot; } public void setRot(float[] rot) { Rot = rot; } public float[] getI() { return I; } public void setI(float[] i) { I = i; } public float[] getGrav() { return grav; } public void setGrav(float[] grav) { this.grav = grav; } public float[] getMag() { return mag; } public void setMag(float[] mag) { this.mag = mag; } public SensorManager getSensorMgr() { return sensorMgr; } public void setSensorMgr(SensorManager sensorMgr) { this.sensorMgr = sensorMgr; } public List<Sensor> getSensors() { return sensors; } public void setSensors(List<Sensor> sensors) { this.sensors = sensors; } public Sensor getSensorGrav() { return sensorGrav; } public void setSensorGrav(Sensor sensorGrav) { this.sensorGrav = sensorGrav; } public Sensor getSensorMag() { return sensorMag; } public void setSensorMag(Sensor sensorMag) { this.sensorMag = sensorMag; } public int getrHistIdx() { return rHistIdx; } public void setrHistIdx(int rHistIdx) { this.rHistIdx = rHistIdx; } public Matrix getTempR() { return tempR; } public void setTempR(Matrix tempR) { this.tempR = tempR; } public Matrix getFinalR() { return finalR; } public void setFinalR(Matrix finalR) { this.finalR = finalR; } public Matrix getSmoothR() { return smoothR; } public void setSmoothR(Matrix smoothR) { this.smoothR = smoothR; } public Matrix[] getHistR() { return histR; } public void setHistR(Matrix[] histR) { this.histR = histR; } public Matrix getM1() { return m1; } public void setM1(Matrix m1) { this.m1 = m1; } public Matrix getM2() { return m2; } public void setM2(Matrix m2) { this.m2 = m2; } public Matrix getM3() { return m3; } public void setM3(Matrix m3) { this.m3 = m3; } public Matrix getM4() { return m4; } public void setM4(Matrix m4) { this.m4 = m4; } public SeekBar getMyZoomBar() { return myZoomBar; } public void setMyZoomBar(SeekBar myZoomBar) { this.myZoomBar = myZoomBar; } public WakeLock getmWakeLock() { return mWakeLock; } public void setmWakeLock(WakeLock mWakeLock) { this.mWakeLock = mWakeLock; } public int getCompassErrorDisplayed() { return compassErrorDisplayed; } public void setCompassErrorDisplayed(int compassErrorDisplayed) { this.compassErrorDisplayed = compassErrorDisplayed; } public String getZoomLevel() { return zoomLevel; } public void setZoomLevel(String zoomLevel) { this.zoomLevel = zoomLevel; } public int getZoomProgress() { return zoomProgress; } public void setZoomProgress(int zoomProgress) { this.zoomProgress = zoomProgress; } public TextView getSearchNotificationTxt() { return searchNotificationTxt; } public void setSearchNotificationTxt(TextView searchNotificationTxt) { this.searchNotificationTxt = searchNotificationTxt; } }