TrackBuilder for mock location providers

Tutorials that use the MapActivity. Many using GPS functionality.

TrackBuilder for mock location providers

Postby jeremian » Thu Dec 27, 2007 10:41 pm

[align=center]TrackBuilder for mock location providers[/align]

What is this: This tutorial shows how to generate the track file for mock providers.

What you will learn:
  • How to open files and write to them.
  • How to display alerts from different threads
  • How to use submenus
  • How to transfer complex data between sub-activities

Problems/Questions:
  • Is it possible to manipulate files in /data/misc/location/ directly from the application?
  • Is it possible to 'reset' location providers?


Difficulty: 3 of 5

Usage:
1): We have to create the path. New points are added by pressing 'P' (or choosing the appropriate option from the menu).
Image
2): After clicking 'Save track' (or pressing 'X') the new sub-activity is displayed. We have to enter the filename and speed of the recorded track (in microdegrees per second). I think 20 is a quick walk.
Image
3): The track file is saved as 'filename_track' in the application's files directory.
Image
Image
4): We have to use adb in order to copy our track file to /data/misc/location/ directory. Here comes a small example, where I create the provider named 'test1' with the previously written track file.

a) We have to create /data/misc/location/test1 directory.
Code: Select all
adb shell
# cd /data/misc/location
# mkdir test1
# exit

b) We have to download the track file from the emulator.
Code: Select all
adb pull /data/data/net.mobilefight.trackbuilder/files/test1_track track

c) We have to upload the track file to /data/misc/location/test1/ directory.
Code: Select all
adb push track /data/misc/location/test1/track


5): We can check the created track by choosing it from the 'GPS providers' submenu.
Image
Image
6): The violet dot is the location received from provider.
Image

Description:
Because most of the code is taken from other tutorials from this site, I have decided to attach only full sources without detailed step-by-step description. However, if you have any questions, don't hesitate to ask. Any ideas will be welcomed.

The full source:

"/res/layout/main.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  5.  
  6.    android:orientation="vertical"
  7.  
  8.    android:layout_width="fill_parent"
  9.  
  10.    android:layout_height="fill_parent"
  11.  
  12.    >
  13.  
  14.    
  15.  
  16.     <TextView  
  17.  
  18.        android:layout_width="fill_parent"
  19.  
  20.        android:layout_height="wrap_content"
  21.  
  22.        android:text="Hello World, TrackBuilder!"
  23.  
  24.    />
  25.  
  26.    
  27.  
  28. </LinearLayout>
  29.  
  30.  
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


"/res/layout/save_file.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  5.  
  6.    android:layout_width="fill_parent"
  7.  
  8.    android:layout_height="wrap_content"
  9.  
  10.    android:padding="10dip">
  11.  
  12.    
  13.  
  14.     <TextView
  15.  
  16.        id="@+id/save_points_label1"
  17.  
  18.        android:layout_width="fill_parent"
  19.  
  20.        android:layout_height="wrap_content"
  21.  
  22.        android:text="@string/save_points_label1"
  23.  
  24.    />
  25.  
  26.    
  27.  
  28.     <EditText
  29.  
  30.        id="@+id/save_points_edit_returnvalue"
  31.  
  32.        android:layout_width="fill_parent"
  33.  
  34.        android:layout_height="wrap_content"
  35.  
  36.        android:background="@android:drawable/editbox_background"
  37.  
  38.        android:singleLine="true"
  39.  
  40.        android:layout_below="@id/save_points_label1"
  41.  
  42.    />
  43.  
  44.        
  45.  
  46.     <TextView
  47.  
  48.        id="@+id/save_points_label2"
  49.  
  50.        android:layout_width="fill_parent"
  51.  
  52.        android:layout_height="wrap_content"
  53.  
  54.        android:text="@string/save_points_label2"
  55.  
  56.        android:layout_below="@id/save_points_edit_returnvalue"
  57.  
  58.    />
  59.  
  60.        
  61.  
  62.     <EditText
  63.  
  64.        id="@+id/save_points_edit_step"
  65.  
  66.        android:layout_width="fill_parent"
  67.  
  68.        android:layout_height="wrap_content"
  69.  
  70.        android:background="@android:drawable/editbox_background"
  71.  
  72.        android:singleLine="true"
  73.  
  74.        android:layout_below="@id/save_points_label2"
  75.  
  76.        android:drawSelectorOnTop="true"
  77.  
  78.        android:numeric="true"
  79.  
  80.        android:text="@string/save_points_default_step"
  81.  
  82.    />
  83.  
  84.  
  85.  
  86.     <Button
  87.  
  88.        id="@+id/save_points_cmd_cancel"
  89.  
  90.        android:layout_width="wrap_content"
  91.  
  92.        android:layout_height="wrap_content"
  93.  
  94.        android:layout_below="@id/save_points_edit_step"
  95.  
  96.        android:layout_alignParentRight="true"
  97.  
  98.        android:layout_marginLeft="10dip"
  99.  
  100.        android:text="@string/save_points_cmd_cancel"
  101.  
  102.    />
  103.  
  104.    
  105.  
  106.     <Button
  107.  
  108.        id="@+id/save_points_cmd_save"
  109.  
  110.        android:layout_width="wrap_content"
  111.  
  112.        android:layout_height="wrap_content"
  113.  
  114.        android:layout_toLeft="@id/save_points_cmd_cancel"
  115.  
  116.        android:layout_alignTop="@id/save_points_cmd_cancel"
  117.  
  118.        android:text="@string/save_points_cmd_save"
  119.  
  120.    />
  121.  
  122.        
  123.  
  124. </RelativeLayout>
  125.  
  126.  
Parsed in 0.006 seconds, using GeSHi 1.0.8.4


"/res/layout/file_row.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <TextView
  5.  
  6.     xmlns:android="http://schemas.android.com/apk/res/android"
  7.  
  8.     android:layout_width="fill_parent"
  9.  
  10.     android:layout_height="wrap_content"
  11.  
  12. />
  13.  
  14.  
Parsed in 0.001 seconds, using GeSHi 1.0.8.4


"/res/values/strings.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <resources>
  5.  
  6.     <string name="app_name">TrackBuilder</string>
  7.  
  8.    
  9.  
  10.     <string name="map_menu_zoom_in">Zoom in (Key: I)</string>
  11.  
  12.     <string name="map_menu_zoom_out">Zoom out (Key: O)</string>
  13.  
  14.     <string name="map_menu_exit">Exit</string>
  15.  
  16.     <string name="map_menu_satellite">Toggle Satellite (Key: S)</string>
  17.  
  18.     <string name="map_menu_traffic">Toggle Traffic (Key: T)</string>
  19.  
  20.     <string name="map_menu_set_point">Set point (Key: P)</string>
  21.  
  22.     <string name="map_menu_remove_point">Remove last point (Key: R)</string>
  23.  
  24.     <string name="map_menu_clear_points">Clear all points (Key: C)</string>
  25.  
  26.     <string name="map_menu_providers">GPS providers</string>
  27.  
  28.     <string name="map_menu_save_points">Save track (Key: X)</string>
  29.  
  30.     <string name="map_menu_save_path">Save path</string>
  31.  
  32.     <string name="map_menu_load_path">Load path</string>        
  33.  
  34.     <string name="map_submenu_none">none</string>
  35.  
  36.  
  37.  
  38.     <string name="save_points_name">Save track</string>
  39.  
  40.     <string name="save_points_cmd_save">Save</string>
  41.  
  42.     <string name="save_points_cmd_cancel">Cancel</string>
  43.  
  44.     <string name="save_points_default_step">20</string>
  45.  
  46.     <string name="save_points_label1">Filename:</string>
  47.  
  48.     <string name="save_points_label2">Step (in microdegrees):</string>
  49.  
  50.    
  51.  
  52.     <string name="save_path_name">Save path</string>
  53.  
  54.     <string name="load_path_name">Load path</string>
  55.  
  56. </resources>
  57.  
  58.  
Parsed in 0.007 seconds, using GeSHi 1.0.8.4


"AndroidManifest.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  5.  
  6.    package="net.mobilefight.trackbuilder">
  7.  
  8.     <application android:icon="@drawable/icon">
  9.  
  10.         <activity class=".TrackBuilder" android:label="@string/app_name">
  11.  
  12.             <intent-filter>
  13.  
  14.                 <action android:value="android.intent.action.MAIN" />
  15.  
  16.                 <category android:value="android.intent.category.LAUNCHER" />
  17.  
  18.             </intent-filter>
  19.  
  20.             <intent-filter>
  21.  
  22.                 <action android:value="android.intent.action.VIEW" />
  23.  
  24.                 <category android:value="android.intent.category.DEFAULT" />
  25.  
  26.             </intent-filter>
  27.  
  28.         </activity>
  29.  
  30.         <activity class=".SavePoints" android:label="@string/save_points_name" />
  31.  
  32.         <activity class=".LoadPath" android:label="@string/load_path_name" />
  33.  
  34.     </application>
  35.  
  36. </manifest>
  37.  
  38.  
Parsed in 0.004 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/TrackBuilder.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. package net.mobilefight.trackbuilder;
  3.  
  4.  
  5.  
  6. import java.util.ArrayList;
  7.  
  8. import java.util.Collection;
  9.  
  10. import java.util.List;
  11.  
  12.  
  13.  
  14. import com.google.android.maps.MapActivity;
  15.  
  16. import com.google.android.maps.MapController;
  17.  
  18. import com.google.android.maps.MapView;
  19.  
  20. import com.google.android.maps.Overlay;
  21.  
  22. import com.google.android.maps.OverlayController;
  23.  
  24. import com.google.android.maps.Point;
  25.  
  26.  
  27.  
  28. import android.app.NotificationManager;
  29.  
  30. import android.app.ProgressDialog;
  31.  
  32. import android.content.Context;
  33.  
  34. import android.content.Intent;
  35.  
  36. import android.content.IntentFilter;
  37.  
  38. import android.content.IntentReceiver;
  39.  
  40. import android.graphics.Canvas;
  41.  
  42. import android.graphics.Paint;
  43.  
  44. import android.graphics.RectF;
  45.  
  46. import android.graphics.Paint.Style;
  47.  
  48. import android.location.Location;
  49.  
  50. import android.location.LocationManager;
  51.  
  52. import android.location.LocationProvider;
  53.  
  54. import android.os.Bundle;
  55.  
  56. import android.os.Looper;
  57.  
  58. import android.view.KeyEvent;
  59.  
  60. import android.view.Menu;
  61.  
  62. import android.view.SubMenu;
  63.  
  64.  
  65.  
  66. public class TrackBuilder extends MapActivity {
  67.  
  68.        
  69.  
  70.         protected LocationManager myLocationManager = null;
  71.  
  72.         protected Location myLocation = null;
  73.  
  74.         protected MyIntentReceiver myIntentReceiver = new MyIntentReceiver();
  75.  
  76.         protected final long MINIMUM_DISTANCECHANGE_FOR_UPDATE = 5; // in Meters
  77.  
  78.     protected final long MINIMUM_TIME_BETWEEN_UPDATE = 1000; // in Milliseconds
  79.  
  80.         protected static final String LOCATION_CHANGED_ACTION =
  81.  
  82.         new String("android.intent.action.LOCATION_CHANGED");
  83.  
  84.     protected final IntentFilter myIntentFilter = new IntentFilter(LOCATION_CHANGED_ACTION);
  85.  
  86.     protected final Intent myIntent = new Intent(LOCATION_CHANGED_ACTION);
  87.  
  88.     protected boolean doUpdates = true;
  89.  
  90.    
  91.  
  92.     protected ProgressDialog myProgressDialog;
  93.  
  94.        
  95.  
  96.         protected MapView myMapView = null;
  97.  
  98.         protected MapController myMapController = null;
  99.  
  100.     protected OverlayController myOverlayController = null;
  101.  
  102.    
  103.  
  104.     protected List<Location> path = new ArrayList<Location>();
  105.  
  106.     protected SubMenu providers;
  107.  
  108.     protected LocationProvider provider;
  109.  
  110.    
  111.  
  112.     protected static final int SAVE_POINTS_REQUEST_CODE = 666;
  113.  
  114.     protected static final int SAVE_PATH_REQUEST_CODE = 667;
  115.  
  116.     protected static final int LOAD_PATH_REQUEST_CODE = 668;
  117.  
  118.    
  119.  
  120.     protected boolean providersLoaded = false;
  121.  
  122.     protected boolean loadingProviders = false;
  123.  
  124.     protected boolean loadedPath = false;
  125.  
  126.    
  127.  
  128.    
  129.  
  130.     class MyIntentReceiver extends IntentReceiver {
  131.  
  132.         @Override
  133.  
  134.         public void onReceiveIntent(Context context, Intent intent) {
  135.  
  136.              if(TrackBuilder.this.doUpdates)
  137.  
  138.                  TrackBuilder.this.updateView();
  139.  
  140.         }
  141.  
  142.    }
  143.  
  144.    
  145.  
  146.     protected class MyLocationOverlay extends Overlay {
  147.  
  148.         @Override
  149.  
  150.         public void draw(Canvas canvas, PixelCalculator calculator, boolean shadow) {
  151.  
  152.                 super.draw(canvas, calculator, shadow);
  153.  
  154.                 Paint paint = new Paint();
  155.  
  156.                 paint.setStyle(Style.FILL);
  157.  
  158.                
  159.  
  160.                 paint.setARGB(255, 105, 105, 105);
  161.  
  162.                 Point mapCentre = myMapView.getMapCenter();
  163.  
  164.                
  165.  
  166.                 // we are always drawing the long/lat of the mapCentre
  167.  
  168.             canvas.drawText("longitude: " + mapCentre.getLongitudeE6() +
  169.  
  170.                         ", latitude: " + mapCentre.getLatitudeE6(),
  171.  
  172.                         5, 15, paint);
  173.  
  174.            
  175.  
  176.             // if there is GPS provider available, we draw the violet dot at the current
  177.  
  178.             // position and the long/lat at the top of the screen
  179.  
  180.                 if (doUpdates && myLocation != null && provider != null) {                     
  181.  
  182.                         Double lat = TrackBuilder.this.myLocation.getLatitude() * 1E6;
  183.  
  184.                         Double lng = TrackBuilder.this.myLocation.getLongitude() * 1E6;
  185.  
  186.                         Point point = new Point(lat.intValue(), lng.intValue());
  187.  
  188.  
  189.  
  190.                         int[] myScreenCoords = new int[2];
  191.  
  192.                         calculator.getPointXY(point, myScreenCoords);
  193.  
  194.                        
  195.  
  196.                         paint.setARGB(255, 80, 30, 150);
  197.  
  198.                         canvas.drawOval(new RectF(myScreenCoords[0] - 5, myScreenCoords[1] + 5,
  199.  
  200.                         myScreenCoords[0] + 5, myScreenCoords[1] - 5), paint);
  201.  
  202.                 canvas.drawText("longitude: " + point.getLongitudeE6() +
  203.  
  204.                                 ", latitude: " + point.getLatitudeE6(),
  205.  
  206.                                 5, 26, paint);
  207.  
  208.                 }
  209.  
  210.                 int[] prevScreenCoords = new int[2];
  211.  
  212.                 boolean first = true;
  213.  
  214.                 // we are iterating all the path's points and draw the green dots at the
  215.  
  216.                 // points' positions and red lines between them
  217.  
  218.                 for (Location loc : path) {
  219.  
  220.                         Point point = new Point((int) loc.getLatitude(), (int) loc.getLongitude());          
  221.  
  222.                         int[] screenCoords = new int[2];
  223.  
  224.                         calculator.getPointXY(point, screenCoords);
  225.  
  226.                         paint.setARGB(80, 156, 192, 36);
  227.  
  228.                         canvas.drawOval(new RectF(screenCoords[0] - 5, screenCoords[1] + 5,
  229.  
  230.                         screenCoords[0] + 5, screenCoords[1] - 5), paint);
  231.  
  232.                         if (!first) {
  233.  
  234.                                 paint.setARGB(80, 255, 0, 0);
  235.  
  236.                                 canvas.drawLine(prevScreenCoords[0], prevScreenCoords[1],
  237.  
  238.                             screenCoords[0], screenCoords[1], paint);
  239.  
  240.                         }
  241.  
  242.                         prevScreenCoords[0] = screenCoords[0];
  243.  
  244.                         prevScreenCoords[1] = screenCoords[1];
  245.  
  246.                         first = false;
  247.  
  248.                 }
  249.  
  250.         }
  251.  
  252.     }
  253.  
  254.        
  255.  
  256.     @Override
  257.  
  258.     public void onCreate(Bundle icicle) {
  259.  
  260.         super.onCreate(icicle);
  261.  
  262.        
  263.  
  264.         myLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
  265.  
  266.         myMapView = new MapView(this);
  267.  
  268.         setContentView(myMapView);
  269.  
  270.         myMapController = this.myMapView.getController();        
  271.  
  272.         myOverlayController = this.myMapView.createOverlayController();
  273.  
  274.         MyLocationOverlay myLocationOverlay = new MyLocationOverlay();
  275.  
  276.         myOverlayController.add(myLocationOverlay, true);        
  277.  
  278.         myMapController.zoomTo(2);
  279.  
  280.     }
  281.  
  282.    
  283.  
  284.     @Override
  285.  
  286.     public void onResume() {
  287.  
  288.          super.onResume();
  289.  
  290.          doUpdates = true;
  291.  
  292.          registerReceiver(myIntentReceiver, myIntentFilter);
  293.  
  294.     }
  295.  
  296.    
  297.  
  298.     @Override
  299.  
  300.     public void onFreeze(Bundle icicle) {
  301.  
  302.          doUpdates = false;
  303.  
  304.          unregisterReceiver(myIntentReceiver);
  305.  
  306.          super.onFreeze(icicle);
  307.  
  308.     }
  309.  
  310.    
  311.  
  312.     private void updateView() {
  313.  
  314.         if (provider != null) {
  315.  
  316.                 myLocation = myLocationManager.getCurrentLocation(provider.getName());
  317.  
  318.                 myMapView.invalidate();
  319.  
  320.         }
  321.  
  322.     }
  323.  
  324.    
  325.  
  326.     @Override
  327.  
  328.     public boolean onCreateOptionsMenu(Menu menu) {
  329.  
  330.          boolean supRetVal = super.onCreateOptionsMenu(menu);
  331.  
  332.          menu.add(0, 0, getString(R.string.map_menu_zoom_in));
  333.  
  334.          menu.add(0, 1, getString(R.string.map_menu_zoom_out));
  335.  
  336.          menu.add(0, 2, getString(R.string.map_menu_satellite));
  337.  
  338.          menu.add(0, 3, getString(R.string.map_menu_traffic));
  339.  
  340.          menu.add(0, 4, getString(R.string.map_menu_set_point));
  341.  
  342.          menu.add(0, 5, getString(R.string.map_menu_remove_point));
  343.  
  344.          menu.add(0, 6, getString(R.string.map_menu_clear_points));
  345.  
  346.          // we remember the reference to submenu in order to modify it in the future
  347.  
  348.          providers = menu.addSubMenu(0, 7, getString(R.string.map_menu_providers));
  349.  
  350.          menu.add(0, 8, getString(R.string.map_menu_save_points));
  351.  
  352.          menu.addSeparator(0, 9);
  353.  
  354.          menu.add(0, 10, getString(R.string.map_menu_save_path));
  355.  
  356.          menu.add(0, 11, getString(R.string.map_menu_load_path));
  357.  
  358.          menu.addSeparator(0, 12);
  359.  
  360.          menu.add(0, 13, getString(R.string.map_menu_exit));
  361.  
  362.          return supRetVal;
  363.  
  364.     }
  365.  
  366.    
  367.  
  368.  
  369.  
  370.    
  371.  
  372.     @Override
  373.  
  374.     protected void onActivityResult(int requestCode, int resultCode,
  375.  
  376.                 final String data, final Bundle extras) {
  377.  
  378.         super.onActivityResult(requestCode, resultCode, data, extras);
  379.  
  380.         switch (requestCode) {
  381.  
  382.         case SAVE_POINTS_REQUEST_CODE: // this is the result from save points subactivity
  383.  
  384.                 if (resultCode == RESULT_OK) {
  385.  
  386.                         // display the progress dialog
  387.  
  388.                         myProgressDialog = ProgressDialog.show(TrackBuilder.this,
  389.  
  390.                                         "Please wait...", "Saving track...", true);
  391.  
  392.                         // start the thread, which will do the hard work
  393.  
  394.                         new Thread() {
  395.  
  396.                                 public void run() {
  397.  
  398.                                         boolean resultOK = TrackFactory.saveFile(path, TrackBuilder.this, data, extras.getInteger("step"));
  399.  
  400.                                         myProgressDialog.dismiss();
  401.  
  402.                                         // we have to call Looper.prepare() before calling showAlert
  403.  
  404.                                         Looper.prepare();
  405.  
  406.                                         if (resultOK) {
  407.  
  408.                                                 showAlert("File saved", "Track successfully saved as " + data, "OK", false);
  409.  
  410.                                         }
  411.  
  412.                                         else {
  413.  
  414.                                                 showAlert("Error", "Track cannot be saved as " + data, "OK", false);
  415.  
  416.                                         }
  417.  
  418.                                         // in order to display alert dialog we have to call Looper.loop()
  419.  
  420.                                         Looper.loop();
  421.  
  422.                                         // after Looper.loop() we have to call quit() on our looper
  423.  
  424.                                         Looper.myLooper().quit();
  425.  
  426.                                 }
  427.  
  428.                         }.start();
  429.  
  430.                 }
  431.  
  432.                 break;
  433.  
  434.         case SAVE_PATH_REQUEST_CODE:
  435.  
  436.                 if (resultCode == RESULT_OK) {
  437.  
  438.                         myProgressDialog = ProgressDialog.show(TrackBuilder.this,
  439.  
  440.                                         "Please wait...", "Saving path...", true);
  441.  
  442.                         new Thread() {
  443.  
  444.                                 public void run() {
  445.  
  446.                                         boolean resultOK = TrackFactory.savePath(path, TrackBuilder.this, data);
  447.  
  448.                                         myProgressDialog.dismiss();
  449.  
  450.                                         Looper.prepare();
  451.  
  452.                                         if (resultOK) {
  453.  
  454.                                                 showAlert("File saved", "Path successfully saved as " + data, "OK", false);
  455.  
  456.                                         }
  457.  
  458.                                         else {
  459.  
  460.                                                 showAlert("Error", "Path cannot be saved as " + data, "OK", false);
  461.  
  462.                                         }
  463.  
  464.                                         Looper.loop();
  465.  
  466.                                         Looper.myLooper().quit();
  467.  
  468.                                 }
  469.  
  470.                         }.start();
  471.  
  472.                 }
  473.  
  474.                 break;
  475.  
  476.         case LOAD_PATH_REQUEST_CODE:
  477.  
  478.                 if (resultCode == RESULT_OK) {
  479.  
  480.                         myProgressDialog = ProgressDialog.show(TrackBuilder.this,
  481.  
  482.                                         "Please wait...", "Loading path...", true);
  483.  
  484.                         loadedPath = false;
  485.  
  486.                         new Thread() {
  487.  
  488.                                 public void run() {
  489.  
  490.                                         List<Location> newPath = new ArrayList<Location>();
  491.  
  492.                                         boolean resultOK = TrackFactory.loadPath(newPath, TrackBuilder.this, data);
  493.  
  494.                                         myProgressDialog.dismiss();
  495.  
  496.                                         Looper.prepare();
  497.  
  498.                                         if (resultOK) {
  499.  
  500.                                                 path.clear();
  501.  
  502.                                                 path.addAll(newPath);
  503.  
  504.                                                 showAlert("File loaded", "Path file " + data + " successfully loaded", "OK", false);
  505.  
  506.                                         }
  507.  
  508.                                         else {
  509.  
  510.                                                 showAlert("Error", "Path file " + data + " cannot be loaded", "OK", false);
  511.  
  512.                                         }
  513.  
  514.                                         // we have to release the main thread before calling Looper.lopp()!
  515.  
  516.                                         loadedPath = true;
  517.  
  518.                                         Looper.loop();
  519.  
  520.                                         Looper.myLooper().quit();
  521.  
  522.                                 }
  523.  
  524.                         }.start();
  525.  
  526.                         // we have to wait on the worker thread to invalidate the map view at the
  527.  
  528.                         // proper moment
  529.  
  530.                         while (true) {
  531.  
  532.                                 if (loadedPath) {
  533.  
  534.                                         break;
  535.  
  536.                                 }                                              
  537.  
  538.                                 try {
  539.  
  540.                                         Thread.sleep(500);
  541.  
  542.                                 }
  543.  
  544.                                 catch (InterruptedException e) {
  545.  
  546.                                         // do nothing
  547.  
  548.                                 }
  549.  
  550.                         }
  551.  
  552.                         // invalidate the map view in order to redraw the screen
  553.  
  554.                         myMapView.invalidate();
  555.  
  556.                 }
  557.  
  558.                 else if (resultCode == LoadPath.RESULT_EMPTY) {
  559.  
  560.                         showAlert("Error", "There are no saved path files!", "OK", false);
  561.  
  562.                 }
  563.  
  564.                 break;
  565.  
  566.         }
  567.  
  568.     }
  569.  
  570.    
  571.  
  572.     @Override
  573.  
  574.     public boolean onOptionsItemSelected(Menu.Item item){
  575.  
  576.         if (item.getGroup() == 0) { // main menu
  577.  
  578.                 switch (item.getId()) {
  579.  
  580.                 case 0: return zoomIn();
  581.  
  582.                 case 1: return zoomOut();                
  583.  
  584.                 case 2: return toggleSatellite();                
  585.  
  586.                 case 3: return toggleTraffic();                
  587.  
  588.                 case 4: return setPoint();               
  589.  
  590.                 case 5: return removePoint();
  591.  
  592.                 case 6: return clearAllPoints();
  593.  
  594.                 case 7: return updateProviders();
  595.  
  596.                 case 8: return savePoints();
  597.  
  598.                 case 10: return savePath();
  599.  
  600.                 case 11: return loadPath();
  601.  
  602.                 case 13: return exit();                  
  603.  
  604.                 }
  605.  
  606.         }
  607.  
  608.         else { // submenu
  609.  
  610.                 if (item.getId() == 0) { // none
  611.  
  612.                         myLocationManager.removeUpdates(myIntent);
  613.  
  614.                         doUpdates = false;
  615.  
  616.                         myLocation = null;
  617.  
  618.                         provider = null;
  619.  
  620.                         myMapView.invalidate();
  621.  
  622.                 }
  623.  
  624.                 else {
  625.  
  626.                         List<LocationProvider> locProviders = myLocationManager.getProviders();
  627.  
  628.                         provider = locProviders.get(item.getId()-1);
  629.  
  630.  
  631.  
  632.                         myLocationManager.requestUpdates(provider, MINIMUM_TIME_BETWEEN_UPDATE,
  633.  
  634.                                         MINIMUM_DISTANCECHANGE_FOR_UPDATE, myIntent);
  635.  
  636.                         onResume();
  637.  
  638.                 }
  639.  
  640.         }
  641.  
  642.         return false;
  643.  
  644.     }
  645.  
  646.    
  647.  
  648.     @Override
  649.  
  650.     public boolean onKeyDown(int keyCode, KeyEvent event) {
  651.  
  652.         switch (keyCode) {
  653.  
  654.         case KeyEvent.KEYCODE_I: return zoomIn();
  655.  
  656.         case KeyEvent.KEYCODE_O: return zoomOut();
  657.  
  658.         case KeyEvent.KEYCODE_S: return toggleSatellite();        
  659.  
  660.         case KeyEvent.KEYCODE_T: return toggleTraffic();
  661.  
  662.         case KeyEvent.KEYCODE_P: return setPoint();
  663.  
  664.         case KeyEvent.KEYCODE_R: return removePoint();
  665.  
  666.         case KeyEvent.KEYCODE_C: return clearAllPoints();
  667.  
  668.         case KeyEvent.KEYCODE_X: return savePoints();
  669.  
  670.         }
  671.  
  672.         return false;
  673.  
  674.     }
  675.  
  676.    
  677.  
  678.     // menu methods
  679.  
  680.     private boolean zoomIn() {
  681.  
  682.         this.myMapController.zoomTo(Math.min(21, this.myMapView.getZoomLevel() + 1));
  683.  
  684.         return true;
  685.  
  686.     }
  687.  
  688.    
  689.  
  690.     private boolean zoomOut() {
  691.  
  692.         this.myMapController.zoomTo(Math.max(1, this.myMapView.getZoomLevel() - 1));
  693.  
  694.         return true;
  695.  
  696.     }
  697.  
  698.    
  699.  
  700.     private boolean toggleSatellite() {
  701.  
  702.         myMapView.toggleSatellite();
  703.  
  704.             return true;
  705.  
  706.     }
  707.  
  708.    
  709.  
  710.     private boolean toggleTraffic() {
  711.  
  712.         myMapView.toggleTraffic();
  713.  
  714.         return true;
  715.  
  716.     }
  717.  
  718.    
  719.  
  720.     private boolean setPoint() {
  721.  
  722.         Point mapCentre = myMapView.getMapCenter();
  723.  
  724.         Location centreLocation = new Location();
  725.  
  726.         centreLocation.setLatitude(mapCentre.getLatitudeE6());
  727.  
  728.         centreLocation.setLongitude(mapCentre.getLongitudeE6());
  729.  
  730.         path.add(centreLocation);
  731.  
  732.         myMapView.invalidate();
  733.  
  734.         return true;
  735.  
  736.     }
  737.  
  738.    
  739.  
  740.     private boolean removePoint() {
  741.  
  742.         if (!path.isEmpty()) {
  743.  
  744.                 path.remove(path.size()-1);
  745.  
  746.                 myMapView.invalidate();
  747.  
  748.         }
  749.  
  750.         return true;
  751.  
  752.     }
  753.  
  754.    
  755.  
  756.     private boolean exit() {
  757.  
  758.         this.finish();
  759.  
  760.         return true;
  761.  
  762.     }
  763.  
  764.    
  765.  
  766.     private boolean updateProviders() {
  767.  
  768.         synchronized (this) {
  769.  
  770.                 if (providersLoaded) {
  771.  
  772.                         // the worker thread has finished and we simply update the
  773.  
  774.                         // providers sumbenu with retrieved providers
  775.  
  776.                 providers.removeGroup(1);
  777.  
  778.                 providers.add(1, 0, getString(R.string.map_submenu_none));
  779.  
  780.                         Collection<LocationProvider> locProviders = myLocationManager.getProviders();
  781.  
  782.                         int counter = 1;
  783.  
  784.                         for (LocationProvider provider : locProviders) {
  785.  
  786.                                 providers.add(1, counter, provider.getName());
  787.  
  788.                                 counter++;
  789.  
  790.                         }
  791.  
  792.                         return true;
  793.  
  794.                 }
  795.  
  796.                 else if (loadingProviders) { // the working thread hasn't finished yet
  797.  
  798.                         return true;
  799.  
  800.                 }
  801.  
  802.                 // we have to set this flag at this moment to avoid creation of multiple threads
  803.  
  804.                 loadingProviders = true;
  805.  
  806.         }
  807.  
  808.  
  809.  
  810.         myProgressDialog = ProgressDialog.show(TrackBuilder.this,
  811.  
  812.                         "Please wait...", "Retrieving available providers...", true);
  813.  
  814.         new Thread() {
  815.  
  816.                 // this working thread simply calls getProviders() method in order
  817.  
  818.                 // to initialize the providers
  819.  
  820.                 public void run() {
  821.  
  822.                         myLocationManager.getProviders();
  823.  
  824.                         myProgressDialog.dismiss();
  825.  
  826.                         synchronized (TrackBuilder.this) {
  827.  
  828.                                 providersLoaded = true;
  829.  
  830.                         }                              
  831.  
  832.                 }
  833.  
  834.         }.start();     
  835.  
  836.         return true;
  837.  
  838.     }
  839.  
  840.    
  841.  
  842.     private boolean clearAllPoints() {
  843.  
  844.         path.clear();
  845.  
  846.         this.myMapView.invalidate();
  847.  
  848.         return true;
  849.  
  850.     }
  851.  
  852.    
  853.  
  854.     private boolean savePoints() {
  855.  
  856.         if (path.size() < 2) {
  857.  
  858.                 NotificationManager nm = (NotificationManager)
  859.  
  860.                 getSystemService(NOTIFICATION_SERVICE);
  861.  
  862.                 nm.notifyWithText(100, "You have to put at least two points on the map!",
  863.  
  864.                                 NotificationManager.LENGTH_SHORT, null);
  865.  
  866.         }
  867.  
  868.         else {
  869.  
  870.                 // start save points subactivity
  871.  
  872.                 Intent i = new Intent(TrackBuilder.this, SavePoints.class);
  873.  
  874.                 // we are adding the bundle to the intent with 'path' set to false
  875.  
  876.                 Bundle extras = new Bundle();
  877.  
  878.                 extras.putBoolean("path", false);
  879.  
  880.                 i.putExtras(extras);
  881.  
  882.                 startSubActivity(i, SAVE_POINTS_REQUEST_CODE);
  883.  
  884.         }
  885.  
  886.         return true;
  887.  
  888.     }
  889.  
  890.    
  891.  
  892.     private boolean savePath() {
  893.  
  894.         if (path.size() < 2) {
  895.  
  896.                 NotificationManager nm = (NotificationManager)
  897.  
  898.                 getSystemService(NOTIFICATION_SERVICE);
  899.  
  900.                 nm.notifyWithText(100, "You have to put at least two points on the map!",
  901.  
  902.                                 NotificationManager.LENGTH_SHORT, null);
  903.  
  904.         }
  905.  
  906.         else {
  907.  
  908.                 Intent i = new Intent(TrackBuilder.this, SavePoints.class);
  909.  
  910.                 // we are adding the bundle to the intent with 'path' set to true              
  911.  
  912.                 Bundle extras = new Bundle();
  913.  
  914.                 extras.putBoolean("path", true);
  915.  
  916.                 i.putExtras(extras);
  917.  
  918.                 startSubActivity(i, SAVE_PATH_REQUEST_CODE);
  919.  
  920.         }
  921.  
  922.         return true;
  923.  
  924.     }
  925.  
  926.    
  927.  
  928.     private boolean loadPath() {
  929.  
  930.         Intent i = new Intent(TrackBuilder.this, LoadPath.class);
  931.  
  932.                 startSubActivity(i, LOAD_PATH_REQUEST_CODE);
  933.  
  934.                 return true;
  935.  
  936.     }
  937.  
  938. }
  939.  
  940.  
Parsed in 0.102 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/TrackFactory.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. package net.mobilefight.trackbuilder;
  3.  
  4.  
  5.  
  6. import java.io.BufferedInputStream;
  7.  
  8. import java.io.BufferedOutputStream;
  9.  
  10. import java.io.IOException;
  11.  
  12. import java.util.List;
  13.  
  14. import java.util.StringTokenizer;
  15.  
  16. import java.util.Vector;
  17.  
  18.  
  19.  
  20. import com.google.android.maps.Point;
  21.  
  22.  
  23.  
  24. import android.location.Location;
  25.  
  26.  
  27.  
  28. public class TrackFactory {
  29.  
  30.        
  31.  
  32.         private static long time = 0;
  33.  
  34.    
  35.  
  36.     public static double euclDistance(Point p1, Point p2) {
  37.  
  38.         return Math.sqrt(((double)p1.getLatitudeE6()-p2.getLatitudeE6())*((double)p1.getLatitudeE6()-p2.getLatitudeE6())
  39.  
  40.                         + ((double)p1.getLongitudeE6()-p2.getLongitudeE6())*((double)p1.getLongitudeE6()-p2.getLongitudeE6()));
  41.  
  42.     }
  43.  
  44.    
  45.  
  46.     private static double genStepSmallPoints(double fstep, Point start, Point end, final double step, List<Point> computed) {
  47.  
  48.         double dist = euclDistance(start, end);
  49.  
  50.         if (fstep > dist) {
  51.  
  52.                 return fstep - dist;
  53.  
  54.         }
  55.  
  56.         double t = fstep / dist;
  57.  
  58.         computed.add(new Point((int) (start.getLatitudeE6() * (1 - t) + end.getLatitudeE6() * t),
  59.  
  60.                                       (int) (start.getLongitudeE6() * (1 - t) + end.getLongitudeE6() * t)));
  61.  
  62.        
  63.  
  64.         int points_no = (int)((dist-fstep)/step);
  65.  
  66.         for (int i = 0; i < points_no; ++i) {
  67.  
  68.                 t += step / dist;
  69.  
  70.                 computed.add(new Point((int) (start.getLatitudeE6() * (1 - t) + end.getLatitudeE6() * t),
  71.  
  72.                               (int) (start.getLongitudeE6() * (1 - t) + end.getLongitudeE6() * t)));
  73.  
  74.         }
  75.  
  76.         return step - (dist - fstep - (points_no*step));
  77.  
  78.     }
  79.  
  80.    
  81.  
  82.     public static List<Point> genAllSteps(List<Location> big_points, double step) {
  83.  
  84.         List<Point> ret = new Vector<Point>();
  85.  
  86.         double fstep = 0.0;
  87.  
  88.         for (int i = 0; i < big_points.size() - 1; ++i) {
  89.  
  90.                 Location loc = big_points.get(i);
  91.  
  92.                 Point pointI = new Point((int) loc.getLatitude(), (int) loc.getLongitude());
  93.  
  94.                 loc = big_points.get(i+1);
  95.  
  96.                 Point pointIp1 = new Point((int) loc.getLatitude(), (int) loc.getLongitude());
  97.  
  98.             fstep = genStepSmallPoints(fstep, pointI, pointIp1, step, ret);
  99.  
  100.         }
  101.  
  102.         return ret;
  103.  
  104.     }
  105.  
  106.    
  107.  
  108.     private static String prepareTrackSequence(Point point) {
  109.  
  110.         StringBuilder toReturn = new StringBuilder();
  111.  
  112.         toReturn.append(time);
  113.  
  114.         toReturn.append(" ");
  115.  
  116.         toReturn.append((double)point.getLongitudeE6() / 1E6);
  117.  
  118.         toReturn.append(" ");
  119.  
  120.         toReturn.append((double)point.getLatitudeE6() / 1E6);
  121.  
  122.         toReturn.append(" 0");
  123.  
  124.         time += 1000;
  125.  
  126.         return toReturn.toString();
  127.  
  128.     }
  129.  
  130.    
  131.  
  132.         public final static boolean saveFile(List<Location> path, TrackBuilder context, String filename, int step) {           
  133.  
  134.                 try {
  135.  
  136.                         BufferedOutputStream output = new BufferedOutputStream(context.openFileOutput(filename + "_track", 0));
  137.  
  138.                         List<Point> points = genAllSteps(path, step);
  139.  
  140.                         for (Point point : points) {
  141.  
  142.                                 output.write((prepareTrackSequence(point) + "\n").getBytes());
  143.  
  144.                         }
  145.  
  146.                         output.close();
  147.  
  148.                 } catch (IOException e) {
  149.  
  150.                         return false;
  151.  
  152.                 }
  153.  
  154.                 return true;
  155.  
  156.         }
  157.  
  158.        
  159.  
  160.         public final static boolean savePath(List<Location> path, TrackBuilder context, String filename) {             
  161.  
  162.                 try {
  163.  
  164.                         BufferedOutputStream output = new BufferedOutputStream(context.openFileOutput(filename + "_path", 0));
  165.  
  166.                         for (Location loc : path) {
  167.  
  168.                                 output.write((loc.getLongitude() + " " + loc.getLatitude() + "\n").getBytes());
  169.  
  170.                         }
  171.  
  172.                         output.close();
  173.  
  174.                 } catch (IOException e) {
  175.  
  176.                         return false;
  177.  
  178.                 }
  179.  
  180.                 return true;
  181.  
  182.         }
  183.  
  184.        
  185.  
  186.         public final static boolean loadPath(List<Location> path, TrackBuilder context, String filename) {             
  187.  
  188.                 try {
  189.  
  190.                         BufferedInputStream input = new BufferedInputStream(context.openFileInput(filename));
  191.  
  192.                         StringBuilder data = new StringBuilder();
  193.  
  194.                         byte[] buffer = new byte[4096];
  195.  
  196.                         while (input.read(buffer) != -1) {
  197.  
  198.                                 data.append(new String(buffer));
  199.  
  200.                         }
  201.  
  202.                         StringTokenizer tokenizer = new StringTokenizer(data.toString(), " \n");
  203.  
  204.                         try {
  205.  
  206.                                 while (tokenizer.hasMoreTokens()) {
  207.  
  208.                                         Location location = new Location();
  209.  
  210.                                         location.setLongitude(Double.valueOf(tokenizer.nextToken()));
  211.  
  212.                                         location.setLatitude(Double.valueOf(tokenizer.nextToken()));
  213.  
  214.                                         path.add(location);
  215.  
  216.                                 }
  217.  
  218.                         }
  219.  
  220.                         catch (Exception e) {
  221.  
  222.                                 // do nothing
  223.  
  224.                         }
  225.  
  226.                         input.close();
  227.  
  228.                 } catch (IOException e) {
  229.  
  230.                         return false;
  231.  
  232.                 }
  233.  
  234.                 return true;
  235.  
  236.         }
  237.  
  238. }
  239.  
  240.  
Parsed in 0.052 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/SavePoints.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. package net.mobilefight.trackbuilder;
  3.  
  4.  
  5.  
  6. import android.app.Activity;
  7.  
  8. import android.os.Bundle;
  9.  
  10. import android.view.View;
  11.  
  12. import android.view.View.OnClickListener;
  13.  
  14. import android.widget.Button;
  15.  
  16. import android.widget.EditText;
  17.  
  18. import android.widget.TextView;
  19.  
  20.  
  21.  
  22. public class SavePoints extends Activity {
  23.  
  24.  
  25.  
  26.     @Override
  27.  
  28.     public void onCreate(Bundle icicle) {
  29.  
  30.         super.onCreate(icicle);
  31.  
  32.         setContentView(R.layout.save_file);
  33.  
  34.        
  35.  
  36.         // we are checking the bundle attached to intent for the 'path' value.
  37.  
  38.         // if it's true, we have to change the activity title and hide label
  39.  
  40.         // end edit widget for step value
  41.  
  42.         if (getIntent().getExtras().getBoolean("path")) {
  43.  
  44.                 setTitle(getString(R.string.save_path_name));
  45.  
  46.                 TextView label = (TextView)findViewById(R.id.save_points_label2);
  47.  
  48.                 label.setVisibility(View.INVISIBLE);
  49.  
  50.             EditText step = (EditText)findViewById(R.id.save_points_edit_step);
  51.  
  52.             step.setVisibility(View.INVISIBLE);
  53.  
  54.         }
  55.  
  56.        
  57.  
  58.         Button cmd_save = (Button)findViewById(R.id.save_points_cmd_save);
  59.  
  60.         cmd_save.setOnClickListener(new OnClickListener(){
  61.  
  62.                 // @Override
  63.  
  64.                 public void onClick(View arg0) {
  65.  
  66.                         EditText edit_returvalue = (EditText)findViewById(
  67.  
  68.                                         R.id.save_points_edit_returnvalue);
  69.  
  70.                         Bundle extras = new Bundle();
  71.  
  72.                         EditText step = (EditText)findViewById(
  73.  
  74.                                         R.id.save_points_edit_step);
  75.  
  76.                         Integer stepValue;
  77.  
  78.                         try {
  79.  
  80.                                 stepValue = Integer.valueOf(step.getText().toString());
  81.  
  82.                         }
  83.  
  84.                         catch (Exception e) {
  85.  
  86.                                 stepValue = new Integer(20);
  87.  
  88.                         }
  89.  
  90.                         extras.putInteger("step", stepValue);
  91.  
  92.                         SavePoints.this.setResult(RESULT_OK,
  93.  
  94.                                         edit_returvalue.getText().toString(),
  95.  
  96.                                         extras);
  97.  
  98.                         SavePoints.this.finish();
  99.  
  100.                 }
  101.  
  102.         });
  103.  
  104.        
  105.  
  106.         Button cmd_cancel = (Button)findViewById(R.id.save_points_cmd_cancel);
  107.  
  108.         cmd_cancel.setOnClickListener(new OnClickListener(){
  109.  
  110.                 // @Override
  111.  
  112.                 public void onClick(View arg0) {
  113.  
  114.                         SavePoints.this.finish();
  115.  
  116.                 }
  117.  
  118.         });
  119.  
  120.     }
  121.  
  122. }
  123.  
  124.  
Parsed in 0.043 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/LoadPath.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. package net.mobilefight.trackbuilder;
  3.  
  4.  
  5.  
  6. import java.io.File;
  7.  
  8. import java.io.FileNotFoundException;
  9.  
  10. import java.util.ArrayList;
  11.  
  12. import java.util.List;
  13.  
  14.  
  15.  
  16. import android.app.AlertDialog;
  17.  
  18. import android.app.ListActivity;
  19.  
  20. import android.content.DialogInterface;
  21.  
  22. import android.content.DialogInterface.OnClickListener;
  23.  
  24. import android.os.Bundle;
  25.  
  26. import android.view.View;
  27.  
  28. import android.widget.ArrayAdapter;
  29.  
  30. import android.widget.ListView;
  31.  
  32.  
  33.  
  34. public class LoadPath extends ListActivity {
  35.  
  36.        
  37.  
  38.         public static final int RESULT_EMPTY = 2;
  39.  
  40.                
  41.  
  42.         private List<String> directoryEntries = new ArrayList<String>();
  43.  
  44.        
  45.  
  46.      @Override
  47.  
  48.      public void onCreate(Bundle icicle) {
  49.  
  50.          super.onCreate(icicle);
  51.  
  52.          try {
  53.  
  54.                  browseTo(getFileStreamPath(""));
  55.  
  56.          } catch (FileNotFoundException e) {
  57.  
  58.                  LoadPath.this.setResult(RESULT_EMPTY);
  59.  
  60.                  LoadPath.this.finish();
  61.  
  62.          }
  63.  
  64.      }
  65.  
  66.          
  67.  
  68.      private void browseTo(final File aDirectory){
  69.  
  70.           if (aDirectory.isDirectory()){
  71.  
  72.                fill(aDirectory.listFiles());
  73.  
  74.           }else{
  75.  
  76.                OnClickListener okButtonListener = new OnClickListener(){
  77.  
  78.                     // @Override
  79.  
  80.                     public void onClick(DialogInterface arg0, int arg1) {
  81.  
  82.                         LoadPath.this.setResult(RESULT_OK, aDirectory.getName());
  83.  
  84.                                 LoadPath.this.finish();
  85.  
  86.                     }
  87.  
  88.                };
  89.  
  90.                OnClickListener cancelButtonListener = new OnClickListener(){
  91.  
  92.                     // @Override
  93.  
  94.                     public void onClick(DialogInterface arg0, int arg1) {
  95.  
  96.                          // Do nothing ^^
  97.  
  98.                     }
  99.  
  100.                };
  101.  
  102.                AlertDialog.show(this,"Question", "Do you want to load: "
  103.  
  104.                                         + aDirectory.getName() + "?",
  105.  
  106.                                         "OK", okButtonListener,
  107.  
  108.                                         "Cancel", cancelButtonListener, false, null);
  109.  
  110.           }
  111.  
  112.      }
  113.  
  114.  
  115.  
  116.      private void fill(File[] files) {
  117.  
  118.          directoryEntries.clear();
  119.  
  120.          boolean empty = true;
  121.  
  122.  
  123.  
  124.          for (File file : files){
  125.  
  126.                  String filename = file.getName();
  127.  
  128.                  if (filename.endsWith("_path")) {
  129.  
  130.                          directoryEntries.add(filename);
  131.  
  132.                          empty = false;
  133.  
  134.                  }
  135.  
  136.          }
  137.  
  138.          
  139.  
  140.  
  141.  
  142.          ArrayAdapter<String> directoryList = new ArrayAdapter<String>(this,
  143.  
  144.                          R.layout.file_row, this.directoryEntries);
  145.  
  146.  
  147.  
  148.          this.setListAdapter(directoryList);
  149.  
  150.          
  151.  
  152.          if (empty) {
  153.  
  154.                  LoadPath.this.setResult(RESULT_EMPTY);
  155.  
  156.                  LoadPath.this.finish();
  157.  
  158.          }
  159.  
  160.      }
  161.  
  162.  
  163.  
  164.      @Override
  165.  
  166.      protected void onListItemClick(ListView l, View v, int position, long id) {
  167.  
  168.          super.onListItemClick(l, v, position, id);
  169.  
  170.          int selectionRowID = (int) this.getSelectionRowID();
  171.  
  172.  
  173.  
  174.          File clickedFile = null;
  175.  
  176.          clickedFile = new File(this.directoryEntries.get(selectionRowID));
  177.  
  178.          if(clickedFile != null)
  179.  
  180.                  this.browseTo(clickedFile);
  181.  
  182.      }
  183.  
  184. }
  185.  
  186.  
Parsed in 0.049 seconds, using GeSHi 1.0.8.4



Regards,
jeremian.
Attachments
TrackBuilder.zip
(19.18 KiB) Downloaded 1452 times
Last edited by jeremian on Tue Mar 09, 2010 1:45 pm, edited 2 times in total.
jeremian
Freshman
Freshman
 
Posts: 6
Joined: Thu Dec 13, 2007 11:28 pm

Top

Postby plusminus » Fri Dec 28, 2007 2:53 pm

Hello jeremian, :)

this is so damn useful for developers of all map-applications :!:
Big thx for letting us participate in your code.

Just one bad I got ;) : A bit of commenting in the tricky parts would be fine :)

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby jeremian » Sun Dec 30, 2007 10:27 pm

Hi,

I have updated the tutorial. The list of changes:
- Added save/load of the paths.
- Commented the code.
- Fixed generation of the track.

Regards,
jeremian.
jeremian
Freshman
Freshman
 
Posts: 6
Joined: Thu Dec 13, 2007 11:28 pm

Postby bavarol » Thu Jan 31, 2008 10:21 am

Hi, it's a wonderful program but I have a foolish question, how can I see that Menu?
I cannot access it.

Kind Regards

Edit: I know it, thank you anyway
bavarol
Experienced Developer
Experienced Developer
 
Posts: 52
Joined: Mon Dec 10, 2007 9:19 pm

Postby res » Mon Feb 04, 2008 11:04 pm

Excellent tutorial jeremian.

bavarol: you need to the push the middle button below the emulator screen to bring up the menu. Its between the "home" and "back" keys on the emulator.
res
Senior Developer
Senior Developer
 
Posts: 146
Joined: Tue Nov 20, 2007 8:14 pm
Location: United States

Can I change the LocationProvider dynamically?

Postby don » Sun Feb 10, 2008 2:05 am

Thanks for the post Jeremian, it has proven helpful so far, though I did struggle figuring out the adb part (btw, for any other newbs like me out there the step-by-step for adb is Here) I was wondering however, is it possible to dynamically create or alter the LocationProvider GPS sentences in real time?

As an example of what mean, imagine the Traveling Salesperson problem. The users would select different cities on the map, the code would then build the graph and determine the shortest path, then create or alter the locationProvider to show the GPS overlay moving through the graph of cities (hopefully this example isn't confusing the issue!).

The TrackBuilder app is very close to what I am looking for, except for the manual copy with ADB. Any ideas on how to do that step programmatically?

Any help would be greatly appreciated.
don
Junior Developer
Junior Developer
 
Posts: 18
Joined: Fri Dec 07, 2007 5:17 am

Top

Simple correction for new SDK

Postby fernan.do » Sat Feb 16, 2008 12:09 am

Hi Jeremian!
Awesome tutorial, for those that are as excited as I am about the new sdk here is a small correction to a deprecated method:

inside the thread that shows the message in TestTrack.java

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Looper.prepare();
  2.  
  3.                                                
  4.  
  5.                                                 if (resultOK) {
  6.  
  7.                                                         showAlert("File Saved", "Track Saved as "+data,
  8.  
  9.                                                                         "OK",false);
  10.  
  11.                                                 } else {
  12.  
  13.                                                         showAlert("Error","Track could not be saved as "+data,
  14.  
  15.                                                                         "OK",false);
  16.  
  17.                                                        
  18.  
  19.                                                 }
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


should be replaced with:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Looper.prepare();
  2.  
  3.                                                
  4.  
  5.                                                 if (resultOK) {
  6.  
  7.                                                         showAlert("File Saved",0, "Track Saved as "+data,
  8.  
  9.                                                                         "OK",false);
  10.  
  11.                                                 } else {
  12.  
  13.                                                         showAlert("Error",0,"Track could not be saved as "+data,
  14.  
  15.                                                                         "OK",false);
  16.  
  17.                                                        
  18.  
  19.                                                 }
Parsed in 0.037 seconds, using GeSHi 1.0.8.4

(the new parameter is simple a resource id of an icon to display which in this case is zero since we do not
display any)
simple correction, yet annoying to find! Hope I can save someone some time.

Best of Luck! And thanks again Jeremian.
fernan.do
Freshman
Freshman
 
Posts: 2
Joined: Sat Feb 16, 2008 12:02 am

Make that for every one...

Postby fernan.do » Sat Feb 16, 2008 5:33 am

Extending the comment above,
All showAlert methods should be extended to be of the form:
public abstract DialogInterface showAlert(CharSequence title, int iconId, CharSequence message, CharSequence buttonText, boolean cancelable)

meaning the parameter int iconId should be added.
fernan.do
Freshman
Freshman
 
Posts: 2
Joined: Sat Feb 16, 2008 12:02 am

Postby jeremian » Sun Feb 24, 2008 9:06 pm

Hi,

I have updated the TrackBuilder sources to use m5-rc14 SDK.

List of changes:

- the mentioned iconId arguments have been added to showAlert()
- removed menu.addSeparator() calls
- Bundle.getInteger() (putInteger) has been renamed to Bundle.getInt() (putInt)
- removed calling of getProviders() in additional thread - in the current Android this method returns so fast, that can be used synchronously
- used Toast.makeText(...).show() instead NotificationManager.notifyWithText(...)
- used getSelectedItemId() instead getSelectionRowID()
- small modifications in manifest/layout files:
* id --> android:id
* class --> android:name
* android:value --> android:name
* added two new permissions: ACCESS_GPS and ACCESS_LOCATION

I hope the next Android SDK will be more back-compatible ;)
Attachments
TrackBuilder.zip
(18.91 KiB) Downloaded 895 times
jeremian
Freshman
Freshman
 
Posts: 6
Joined: Thu Dec 13, 2007 11:28 pm

Postby wmellon » Mon Mar 03, 2008 5:17 am

Jeremian, et al.

Thanks for posting your TrackBuilder updates for the new SDK. I was following along great until I tried to add the saved track to the list of GPS providers. My steps:

1. Add points, save track, do adb pull / push on 6,432 byte track file (attached).
2. adb echoes back 402 KB/s (0 bytes in 6432.000s). I'll go out on a limb here and say that the I/O operations worked fine, and that the adb guys just got these data backwards.
3. Select "GPS providers" from TrackBuilder menu, but here only "none" and "gps" are shown; no uploaded track file.

Is there any way to view the file contents of the device to make sure the track file got to /data/misc/location/ ? Am I missing an important step?


Thanks again -- Will
Attachments
track.rar
my saved track file
(1.09 KiB) Downloaded 543 times
wmellon
Freshman
Freshman
 
Posts: 3
Joined: Mon Mar 03, 2008 4:39 am
Location: Rochester, NY

vamsi

Postby gvkreddyvamsi » Mon Mar 03, 2008 6:10 am

HI,


I have loaded with Track Builder application..

Working well without alert boxes.


As syntaxes changed in m5 ...


plz suggest what we have to initialize with context in Toast

Toast.makeText(Context , "You have to put at least two points on the map!", Toast.LENGTH_SHORT).show();


I got error at Context..

thanks in advance.


Any idea?
gvkreddyvamsi
Developer
Developer
 
Posts: 43
Joined: Mon Jan 21, 2008 5:10 am
Location: INDIA

Postby plusminus » Mon Mar 03, 2008 9:28 am

Hello vamsi,

where is that line located :?:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Toast.makeText(Context , "You have to put at least two points on the map!", Toast.LENGTH_SHORT).show();
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


Depending on the CodeContext, you need to use "this" or "OuterActivity.this".

Regards,
plusmonus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

vamsi

Postby gvkreddyvamsi » Mon Mar 03, 2008 9:51 am

Hello plusminus,


I have used that Toast syntax to replace notification manager .

In TrackBuilder class notification manager is used in 2-3 methods.

I am replacing all those with Toast method.

Now these are working fine with Context this.


And one thing ...here showAlert method is used at a lot places.

It is not working in m5.

How we can replace this method.


showAlert("File loaded", "Path file " + data + " successfully loaded", "OK", false);


Thank u.


by
vamsi
gvkreddyvamsi
Developer
Developer
 
Posts: 43
Joined: Mon Jan 21, 2008 5:10 am
Location: INDIA

Postby wannaberunner » Mon Mar 03, 2008 4:55 pm

Hi all,

first of all I'd like to say thx to the author since the tutorial is really great!

However, I'm running m5 sdk and after I'd upload created track file to the emulator, it wasn't being recognized as a Location Provider. Only after I copied the properties file from default Gps provider, my new provider was recognized.

It took me two hours to figure it so I hope I save time for the others. :)
wannaberunner
Freshman
Freshman
 
Posts: 3
Joined: Mon Mar 03, 2008 4:46 pm

Postby wmellon » Mon Mar 03, 2008 7:35 pm

wannabe,

It sounds like you and I were experiencing the same problem. Could you be please be more specific about how you "copied the properties file from the default Gps provider?" I'm not sure what this means, or perhaps more importantly, why it worked. Thanks so much for the post. It's good to know I'm not alone in my frustration as I'm learning the ins and outs of this great new platform.

--Will
wmellon
Freshman
Freshman
 
Posts: 3
Joined: Mon Mar 03, 2008 4:39 am
Location: Rochester, NY

Top
Next

Return to Map Tutorials

Who is online

Users browsing this forum: Yahoo [Bot] and 2 guests