source: other-projects/tipple-android/tipple-ar/tipple-standalone-hpg/src/org/greenstone/android/tipple/base/TippleActivity.java@ 26528

Last change on this file since 26528 was 26528, checked in by davidb, 11 years ago

Code developed by the Tipple-AR Smoke and Mirrors team, based on the main tipple trunk

File size: 17.0 KB
Line 
1package org.greenstone.android.tipple.base;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.InputStream;
6import java.util.ArrayList;
7import java.util.Locale;
8
9import android.hardware.Sensor;
10import android.hardware.SensorManager;
11import android.location.Criteria;
12import android.location.LocationManager;
13import android.os.Bundle;
14import android.os.Environment;
15import android.os.Handler;
16import android.preference.PreferenceManager;
17import android.speech.tts.TextToSpeech;
18import android.speech.tts.TextToSpeech.OnInitListener;
19import android.text.method.ScrollingMovementMethod;
20import android.util.Log;
21import android.view.Gravity;
22import android.view.Menu;
23import android.view.MenuItem;
24import android.view.View;
25import android.view.ViewGroup;
26import android.content.Context;
27import android.content.Intent;
28import android.content.SharedPreferences;
29import android.content.res.AssetManager;
30import android.widget.FrameLayout;
31import android.widget.LinearLayout;
32import android.widget.LinearLayout.LayoutParams;
33import android.widget.TextView;
34
35
36import org.greenstone.android.tipple.R;
37import org.greenstone.android.tipple.base.MapViewTipple;
38import org.mapsforge.android.maps.MapActivity;
39import org.mapsforge.android.maps.MapView;
40import java.util.Timer;
41import java.util.TimerTask;
42
43public class TippleActivity extends MapActivity implements OnInitListener {
44 private final boolean debug_mode = true;
45
46 enum TextAudioModeEnum {
47 TEXT_ONLY, TEXT_PLUS_AUDIO, AUDIO_ONLY, AUDIO_PLUS_TEXT
48 };
49
50 // File storage
51 public static String geodataDirectory;
52 public static String logDirectory;
53 public static String audioDirectory;
54
55 // Preferences
56 public static SharedPreferences sharedPreferences;
57 public static boolean centreOnGPSLocation;
58 public static boolean showScaleBar;
59 public static boolean showSights;
60 public static boolean showUserTrail;
61 public static TextAudioModeEnum textAudioMode;
62
63 // Logging
64 public static TippleLog log;
65
66 // Views
67 protected TextView longlat_view_;
68 protected MapView map_view_;
69 protected TextView text_view_;
70 protected FrameLayout text_map_composite_;
71
72 protected AudioPlayerView audio_player_view_;
73
74 protected ARLauncherView ar_view_;
75
76 protected TipLocationManager tip_location_manager_;
77
78 protected ArrayList<TipLocation> user_trail_ = null;
79 protected String user_trail_filename_ = null;
80
81 //update timer
82 TimerTask update_task;
83 final Handler handler = new Handler();
84 Timer t = new Timer();
85
86 public void updateMapView(){
87 update_task = new TimerTask() {
88 public void run() {
89 handler.post(new Runnable() {
90 public void run() {
91 map_view_.postInvalidate();
92 }
93 });
94 }
95 };
96 t.schedule(update_task, 1000, 80);
97 }
98
99 // Text to Speech
100 protected TextToSpeech tts_ = null;
101
102 // GPS
103 protected LocationManager location_manager_ = null;
104 protected TippleLocationListener location_listener_ = null;
105
106 // Request codes
107 protected final int TTS_DATA_CHECK = 0;
108 private static final int SELECT_LOG_FILE = 1;
109
110 protected boolean assetToExternalStorage(String asset_filename, String external_storage_filename, boolean debug_mode) {
111 boolean status = true;
112
113 try {
114
115 File external_storage_file = new File(external_storage_filename);
116 if (!external_storage_file.exists() || (debug_mode)) {
117 // Need to create the /sdcard version
118
119 AssetManager assetManager = getAssets();
120
121 InputStream ais = assetManager.open(asset_filename); // ais = asset input stream
122 FileOutputStream fos = new FileOutputStream(external_storage_file); // fos = file output stream
123
124 byte[] buffer = new byte[1024];
125
126 int buflen;
127 while ((buflen = ais.read(buffer)) > 0) {
128 fos.write(buffer, 0, buflen);
129 }
130
131 ais.close();
132 fos.close();
133 }
134
135 } catch (Exception e) {
136 e.printStackTrace();
137 status = false;
138 }
139
140 return status;
141 }
142
143 protected boolean initTippleStore(String location) {
144
145 // Locate map data directory
146 File external_root_file = Environment.getExternalStorageDirectory();
147 String external_root = external_root_file.getAbsolutePath();
148 String tipple_store_dir = external_root + "/tipple-store";
149
150 geodataDirectory = tipple_store_dir + "/geodata/";
151 logDirectory = tipple_store_dir + "/logs/";
152 audioDirectory = tipple_store_dir + "/audio/";
153
154 File tipple_store_file = new File(tipple_store_dir);
155 if (!tipple_store_file.exists()) {
156 if (!tipple_store_file.mkdir()) {
157 System.err.println("Failed to create directory: " + tipple_store_dir);
158 return false;
159 }
160 }
161
162 File geodataDirFile = new File(geodataDirectory);
163 if (!geodataDirFile.exists()) {
164 if (!geodataDirFile.mkdir()) {
165 System.err.println("Failed to create directory: " + geodataDirectory);
166 return false;
167 }
168 }
169
170 File logDirFile = new File(logDirectory);
171 if (!logDirFile.exists()) {
172 if (!logDirFile.mkdir()) {
173 System.err.println("Failed to create directory: " + logDirectory);
174 return false;
175 }
176 }
177
178 File audioDirFile = new File(audioDirectory);
179 if (!audioDirFile.exists()) {
180 if (!audioDirFile.mkdir()) {
181 System.err.println("Failed to create directory: " + audioDirectory);
182 return false;
183 }
184 }
185
186 // dig out the audio files
187 String[] audio_filenames = { "BeepMorseSonar.wav", "Ding.wav", "DingExtended.wav" };
188 for (String audio_filename : audio_filenames) {
189 String audio_asset_filename = "audio/" + audio_filename;
190 String audio_exstore_filename = audioDirectory + audio_filename;
191
192 if (!assetToExternalStorage(audio_asset_filename, audio_exstore_filename, debug_mode)) {
193 System.err.println("Failed to transfer asset " + audio_asset_filename + " to " + audio_exstore_filename);
194 return false;
195 }
196 }
197
198 if ((location != null) && (!location.equals(""))) {
199 // get out map and XML location file
200
201 String map_asset_filename = "geodata/" + location + ".map";
202 String map_exstore_filename = geodataDirectory + location + ".map";
203
204 if (!assetToExternalStorage(map_asset_filename, map_exstore_filename, debug_mode)) {
205 System.err.println("Failed to transfer asset " + map_asset_filename + " to " + map_exstore_filename);
206 return false;
207 }
208
209 String loc_asset_filename = "geodata/" + location + ".loc";
210 String loc_exstore_filename = geodataDirectory + location + ".loc";
211
212 if (!assetToExternalStorage(loc_asset_filename, loc_exstore_filename, debug_mode)) {
213 System.err.println("Failed to transfer asset " + loc_asset_filename + " to " + loc_exstore_filename);
214 return false;
215 }
216 }
217
218 return true;
219 }
220
221 protected boolean initTippleStore() {
222 return initTippleStore(null);
223 }
224
225 protected TextView createLongLatView() {
226 // Lat,Long line at top
227 TextView longlat_view = new TextView(this);
228 longlat_view.setText("(Long,Lat): ");
229
230 LayoutParams longlat_view_layout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 35, 0);
231 longlat_view.setLayoutParams(longlat_view_layout);
232
233 return longlat_view;
234 }
235
236 protected MapViewTipple createMapView(String map_filename) {
237
238 // Map view in middle
239 MapViewTipple map_view = new MapViewTipple(this, SensorFusion.getInstance());
240 map_view.setClickable(true);
241 map_view.setBuiltInZoomControls(true);
242 map_view.zoom((byte) 1, 4);
243 String full_map_filename = geodataDirectory + map_filename;
244 // String full_map_filename = geodataDirectory + "mymap.map";
245
246 map_view.setMapFile(new File(full_map_filename));
247
248 LayoutParams map_view_layout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
249
250 map_view.setLayoutParams(map_view_layout);
251
252 return map_view;
253 }
254
255 protected MapView createMapViewFromAsset(String map_filename) {
256 // Transfer asset to file in dataDirectory if it does not already exist
257
258 String asset_filename = "geodata" + File.separator + map_filename;
259 String external_storage_filename = geodataDirectory + map_filename;
260
261 assetToExternalStorage(asset_filename, external_storage_filename, debug_mode);
262
263 return createMapView(map_filename);
264
265 }
266
267 protected TextView createTextView() {
268 // Text view in middle (ultimately on top of map view)
269 TextView text_view = new TextView(this);
270
271 LayoutParams text_view_layout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
272 text_view.setLayoutParams(text_view_layout);
273
274 text_view.setGravity(Gravity.BOTTOM | Gravity.FILL_HORIZONTAL);
275
276 text_view.setPadding(12, 12, 12, 12);
277 text_view.setTextColor(0xffffffff);
278 text_view.setBackgroundColor(0xCC000000);
279 text_view.setTextSize(20.0f);
280
281 text_view.setVerticalScrollBarEnabled(true);
282 text_view.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
283
284 text_view.setMovementMethod(new ScrollingMovementMethod());
285
286 text_view.setVisibility(View.INVISIBLE);
287
288 return text_view;
289 }
290
291 protected FrameLayout compositTextViewOnMapView(MapView map_view, TextView text_view) {
292 FrameLayout frame_layout = new FrameLayout(this);
293
294 LayoutParams view_layout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
295
296 frame_layout.setLayoutParams(view_layout);
297 frame_layout.addView(map_view);
298 frame_layout.addView(text_view);
299
300 return frame_layout;
301 }
302
303 protected AudioPlayerView createAudioPlayerView() {
304 // Player at the bottom
305 AudioPlayerView audio_player_view = new AudioPlayerView(this, text_view_);
306
307 LayoutParams audio_player_layout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 50, 0);
308 audio_player_view.setLayoutParams(audio_player_layout);
309
310 return audio_player_view;
311 }
312
313 protected void refreshPreferences() {
314 // Restore preferences
315 sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
316
317 // shared_preferences_ = getPreferences(MODE_PRIVATE);
318 showScaleBar = sharedPreferences.getBoolean("showScaleBar", false);
319 centreOnGPSLocation = sharedPreferences.getBoolean("centreOnGPSLoc", false);
320
321 showSights = sharedPreferences.getBoolean("showSights", true);
322 showUserTrail = sharedPreferences.getBoolean("showUserTrail", false);
323
324 String textAudioModeStr = sharedPreferences.getString("textAudioMode", "AUDIO_PLUS_TEXT");
325 textAudioMode = Enum.valueOf(TextAudioModeEnum.class, textAudioModeStr);
326 }
327
328 protected void onCreateXXX(Bundle savedInstanceState) {
329 System.err.println("*** TippleActivity::onCreate()");
330 super.onCreate(savedInstanceState);
331
332 if (!initTippleStore("hamilton")) {
333 System.err.println("Failed to initialize TippleStore on sdcard. Quiting");
334 onDestroy();
335 }
336
337 // Set up logging
338 log = new TippleLog(this, logDirectory);
339 log.optStartLog();
340
341 // "refresh" preferences here so views can be configured correctly
342 // and ensure showUserTrail is reset to off (as not log file has been
343 // selected yet)
344 refreshPreferences();
345 SharedPreferences.Editor editor = sharedPreferences.edit();
346 editor.putBoolean("showUserTrail", false);
347
348 // Set up Text to Speech
349 Intent checkIntent = new Intent();
350 checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
351 startActivityForResult(checkIntent, TTS_DATA_CHECK);
352
353 // startActivityForResult(new Intent(this, LogFileBrowser.class),
354 // SELECT_LOG_FILE);
355
356 // Screen dived into:
357 // Top: GPS location
358 // Middle: Map view
359 // Bottom: Media player
360
361 LinearLayout linearLayout = new LinearLayout(this);
362 linearLayout.setOrientation(LinearLayout.VERTICAL);
363
364 longlat_view_ = createLongLatView();
365 // map_view_ = createMapView("new-zealand.map");
366 map_view_ = createMapViewFromAsset("hamilton.map");
367
368 text_view_ = createTextView();
369 text_map_composite_ = compositTextViewOnMapView(map_view_, text_view_);
370
371 audio_player_view_ = createAudioPlayerView();
372
373 linearLayout.addView(longlat_view_);
374 linearLayout.addView(text_map_composite_);
375 linearLayout.addView(audio_player_view_);
376
377 setContentView(linearLayout);
378 }
379
380 @Override
381 protected void onResume() {
382 super.onResume();
383 System.err.println("*** TippleActivity::onResume()");
384
385 refreshPreferences();
386 audio_player_view_.refreshView();
387
388 // map_view_.setScaleBar(showScaleBar);
389 map_view_.getMapScaleBar().setShowMapScaleBar(showScaleBar);
390
391 if (tip_location_manager_ != null) {
392 if (showSights) {
393 // tip_location_manager_.createTourLocationsOverlay(map_view_,locations_);
394 tip_location_manager_.addTourLocations(map_view_);
395 } else {
396 tip_location_manager_.removeTourLocations(map_view_);
397 }
398
399 if (user_trail_filename_ != null) {
400
401 if (showUserTrail) {
402 // tip_location_manager_.createLogRouteLocationsOverlay(map_view_,user_trail_);
403 tip_location_manager_.addLogRouteLocations(map_view_);
404 } else {
405 tip_location_manager_.removeLogRouteLocations(map_view_);
406 }
407 }
408 }
409
410 SensorFusion.getInstance().addClient("TippleActivity");
411 LocationFusion.getInstance().addClient("TippleActivity");
412 }
413
414 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
415 System.err.println("*** TippleActivity::onActivityResult(), requestCode: " + requestCode);
416
417 if (requestCode == TTS_DATA_CHECK) {
418 if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
419 // success, create the TTS instance
420 tts_ = new TextToSpeech(this, (TextToSpeech.OnInitListener) this);
421 tts_.setLanguage(Locale.UK);
422 Global.tts = tts_;
423
424 // now TTS initialized, init TTS aware place-locations
425 String loc_filename = geodataDirectory + "hamilton.loc";
426 System.err.println("*** loc filename = " + loc_filename);
427
428 tip_location_manager_ = new TipLocationManager(this, audio_player_view_, tts_);
429 Global.locations = tip_location_manager_.loadTour(loc_filename);
430 tip_location_manager_.createTourLocationsOverlay(map_view_, Global.locations);
431
432 // Set up a callback method for handling GPS location updates
433 // connected with our place-locations
434 location_manager_ = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
435 location_listener_ = new TippleLocationListener(this, map_view_, longlat_view_, tip_location_manager_, Global.locations);
436
437 Criteria location_criteria_ = new Criteria();
438 location_criteria_.setAccuracy(Criteria.ACCURACY_LOW);
439 location_manager_.requestLocationUpdates(location_manager_.getBestProvider(location_criteria_, true), 0, 0, location_listener_);
440
441 } else {
442 // missing data, install it
443 Intent installIntent = new Intent();
444 installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
445 startActivity(installIntent);
446 }
447 }
448
449 else if (requestCode == SELECT_LOG_FILE) {
450
451 if (resultCode == RESULT_OK) {
452 if (data != null && data.getStringExtra("logFile") != null) {
453 if (user_trail_filename_ != null) {
454 // have a previously loaded route => scrub it
455 tip_location_manager_.removeLogRouteLocations(map_view_);
456 user_trail_filename_ = null;
457 }
458 // set up route overlay
459 user_trail_filename_ = data.getStringExtra("logFile");
460 user_trail_ = tip_location_manager_.loadUserTrail(user_trail_filename_);
461 tip_location_manager_.createLogRouteLocationsOverlay(map_view_, user_trail_);
462 }
463 } else if (resultCode == RESULT_CANCELED) {
464 // nothing to do
465 }
466
467 }
468
469 }
470
471 @Override
472 public void onInit(int status) {
473 System.err.println("*** TippleActivity::onInit(), status (zero == good): " + status);
474
475 if (status == TextToSpeech.SUCCESS) {
476 Log.d("TippleActivity::onInit()", "Text-to-speech engine initialized");
477 } else if (status == TextToSpeech.ERROR) {
478 Log.e("TippleActivity::onInit()", "Text-to-speech engine failed initialized");
479 System.err.println("Error occured while initializing text-to-speech engine");
480 }
481
482 }
483
484 @Override
485 public boolean onCreateOptionsMenu(Menu menu) {
486 getMenuInflater().inflate(R.menu.options_menu, menu);
487 return true;
488 }
489
490 @Override
491 public boolean onOptionsItemSelected(MenuItem item) {
492 int item_id = item.getItemId();
493
494 if (item_id == R.id.menu_info) {
495 startActivity(new Intent(this, InfoView.class));
496 return true;
497 } else if (item_id == R.id.menu_preferences) {
498 startActivity(new Intent(this, EditPreferences.class));
499 return true;
500 } else if (item_id == R.id.menu_logfile) {
501 startActivityForResult(new Intent(this, TippleLogFileBrowser.class), SELECT_LOG_FILE);
502 return true;
503 } else {
504 return false;
505 }
506 }
507
508 @Override
509 protected void onPause() {
510 System.err.println("*** TippleActivity::onPause()");
511
512 // Switch off location updates
513 if (location_manager_ != null) {
514
515 if (location_listener_ != null) {
516
517 location_manager_.removeUpdates(location_listener_);
518 location_listener_ = null;
519 }
520 location_manager_ = null;
521 }
522
523 SensorFusion.getInstance().removeClient("TippleActivity");
524 LocationFusion.getInstance().removeClient("TippleActivity");
525
526 super.onPause();
527 }
528
529 @Override
530 protected void onStop() {
531 System.err.println("*** TippleActivity::onStop()");
532 super.onStop();
533 // Is this needed?
534 // Go through an Editor object to make preference changes stick
535 SharedPreferences.Editor editor = sharedPreferences.edit();
536 editor.commit();
537 }
538
539 @Override
540 protected void onDestroy() {
541 System.err.println("*** TippleActivity::onDestroy()");
542 super.onDestroy();
543
544 if (tts_ != null) tts_.shutdown();
545 tts_ = null;
546
547 user_trail_filename_ = null;
548
549 TipLocationManager.stopOverlayThreads();
550
551 log.optStopLog();
552 }
553
554}
Note: See TracBrowser for help on using the repository browser.