2 * Copyright © 2015 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 package org.altusmetrum.AltosDroid;
24 import org.altusmetrum.AltosDroid.R;
26 import android.app.Activity;
27 import android.bluetooth.BluetoothAdapter;
28 import android.bluetooth.BluetoothDevice;
29 import android.content.BroadcastReceiver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.os.Bundle;
34 import android.view.View;
35 import android.view.Window;
36 import android.view.View.OnClickListener;
37 import android.widget.*;
38 import android.widget.AdapterView.*;
39 import android.location.Location;
40 import android.location.LocationManager;
41 import android.location.LocationListener;
42 import android.location.Criteria;
44 import org.altusmetrum.altoslib_7.*;
47 * This Activity appears as a dialog. It lists any paired devices and
48 * devices detected in the area after discovery. When a device is chosen
49 * by the user, the MAC address of the device is sent back to the parent
50 * Activity in the result Intent.
52 public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapInterface, AltosMapLoaderListener, LocationListener {
54 private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
56 private CheckBox hybrid;
57 private CheckBox satellite;
58 private CheckBox roadmap;
59 private CheckBox terrain;
61 private Spinner known_sites_spinner;
62 private Spinner min_zoom;
63 private Spinner max_zoom;
64 private TextView radius_label;
65 private Spinner radius;
67 private EditText latitude;
68 private EditText longitude;
70 private ProgressBar progress;
72 /* AltosMapLoaderListener interfaces */
73 public void loader_start(final int max) {
74 this.runOnUiThread(new Runnable() {
77 progress.setProgress(0);
82 public void loader_notify(final int cur, final int max, final String name) {
83 this.runOnUiThread(new Runnable() {
85 progress.setProgress(cur);
90 public void loader_done(int max) {
91 this.runOnUiThread(new Runnable() {
93 progress.setProgress(0);
99 /* AltosLaunchSiteListener interface */
100 public void notify_launch_sites(final List<AltosLaunchSite> sites) {
101 this.runOnUiThread(new Runnable() {
103 for (AltosLaunchSite site : sites)
104 known_sites_adapter.add(site);
110 AltosMapLoader loader;
112 class PreloadMapImage implements AltosImage {
113 public void flush() {
116 public PreloadMapImage(File file) {
120 public AltosMapPath new_path() {
124 public AltosMapLine new_line() {
128 public AltosImage load_image(File file) throws Exception {
129 return new PreloadMapImage(file);
132 public AltosMapMark new_mark(double lat, double lon, int state) {
136 class PreloadMapTile extends AltosMapTile {
137 public void paint(AltosMapTransform t) {
140 public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
141 super(listener, upper_left, center, zoom, maptype, px_size, 2);
146 public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
147 return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
151 return AltosMap.px_size;
154 public int height() {
155 return AltosMap.px_size;
158 public void repaint() {
161 public void repaint(AltosRectangle damage) {
164 public void set_zoom_label(String label) {
167 public void select_object(AltosLatLon latlon) {
170 public void debug(String format, Object ... arguments) {
171 AltosDebug.debug(format, arguments);
174 /* LocationProvider interface */
176 AltosLaunchSite current_location_site;
178 public void onLocationChanged(Location location) {
179 AltosDebug.debug("location changed");
180 if (current_location_site == null) {
181 AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
183 current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
184 known_sites_adapter.insert(current_location_site, 0);
186 if (selected_item != null)
187 known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
189 latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
190 longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
193 current_location_site.latitude = location.getLatitude();
194 current_location_site.longitude = location.getLongitude();
198 public void onStatusChanged(String provider, int status, Bundle extras) {
201 public void onProviderEnabled(String provider) {
204 public void onProviderDisabled(String provider) {
207 private double text(EditText view) throws ParseException {
208 return AltosParse.parse_double_locale(view.getEditableText().toString());
211 private double latitude() throws ParseException {
212 return text(latitude);
215 private double longitude() throws ParseException {
216 return text(longitude);
219 private int value(Spinner spinner) {
220 return (Integer) spinner.getSelectedItem();
223 private int min_z() {
224 return value(min_zoom);
227 private int max_z() {
228 return value(max_zoom);
231 private double value_distance(Spinner spinner) {
232 return (Double) spinner.getSelectedItem();
235 private double radius() {
236 double r = value_distance(radius);
237 if (AltosPreferences.imperial_units())
238 r = AltosConvert.distance.inverse(r);
244 private int bit(CheckBox box, int value) {
250 private int types() {
251 return (bit(hybrid, AltosMap.maptype_hybrid) |
252 bit(satellite, AltosMap.maptype_satellite) |
253 bit(roadmap, AltosMap.maptype_roadmap) |
254 bit(terrain, AltosMap.maptype_terrain));
257 private void load() {
259 double lat = latitude();
260 double lon = longitude();
266 AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
267 lat, lon, min, max, r, t);
268 loader.load(lat, lon, min, max, r, t);
269 } catch (ParseException e) {
270 AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
274 private void add_numbers(Spinner spinner, int min, int max, int def) {
276 ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
281 for (int i = min; i <= max; i++) {
282 adapter.add(new Integer(i));
288 spinner.setAdapter(adapter);
289 spinner.setSelection(spinner_def);
293 private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) {
295 ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item);
302 if (AltosPreferences.imperial_units()) {
303 distances = distances_mi;
306 distances = distances_km;
310 for (int i = 0; i < distances.length; i++) {
311 adapter.add(distances[i]);
312 if (distances[i] == def)
317 spinner.setAdapter(adapter);
318 spinner.setSelection(spinner_def);
323 class SiteListListener implements OnItemSelectedListener {
324 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
325 AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
326 latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
327 longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
329 public void onNothingSelected(AdapterView<?> parent) {
332 public SiteListListener() {
336 double[] radius_mi = { 1, 2, 5, 10, 20 };
337 double radius_def_mi = 2;
338 double[] radius_km = { 1, 2, 5, 10, 20, 30 };
339 double radius_def_km = 2;
342 protected void onCreate(Bundle savedInstanceState) {
343 super.onCreate(savedInstanceState);
346 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
347 setContentView(R.layout.map_preload);
349 // Set result CANCELED incase the user backs out
350 setResult(Activity.RESULT_CANCELED);
352 // Initialize the button to perform device discovery
353 Button loadButton = (Button) findViewById(R.id.preload_load);
354 loadButton.setOnClickListener(new OnClickListener() {
355 public void onClick(View v) {
360 latitude = (EditText) findViewById(R.id.preload_latitude);
361 longitude = (EditText) findViewById(R.id.preload_longitude);
363 hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
364 satellite = (CheckBox) findViewById(R.id.preload_satellite);
365 roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
366 terrain = (CheckBox) findViewById(R.id.preload_terrain);
368 hybrid.setChecked(true);
370 min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
371 add_numbers(min_zoom,
372 AltosMap.min_zoom - AltosMap.default_zoom,
373 AltosMap.max_zoom - AltosMap.default_zoom, -2);
374 max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
375 add_numbers(max_zoom,
376 AltosMap.min_zoom - AltosMap.default_zoom,
377 AltosMap.max_zoom - AltosMap.default_zoom, 2);
378 radius_label = (TextView) findViewById(R.id.preload_radius_label);
379 radius = (Spinner) findViewById(R.id.preload_radius);
380 if (AltosPreferences.imperial_units())
381 radius_label.setText("Radius (miles)");
383 radius_label.setText("Radius (km)");
384 add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);
386 progress = (ProgressBar) findViewById(R.id.preload_progress);
388 // Initialize array adapters. One for already paired devices and
389 // one for newly discovered devices
390 known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
392 known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
394 known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
396 known_sites_spinner.setAdapter(known_sites_adapter);
397 known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
399 map = new AltosMap(this);
401 loader = new AltosMapLoader(map, this);
403 // Listen for GPS and Network position updates
404 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
406 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
408 new AltosLaunchSites(this);
412 protected void onDestroy() {
415 // Stop listening for location updates
416 ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);