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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 package org.altusmetrum.AltosDroid;
25 import org.altusmetrum.AltosDroid.R;
27 import android.app.Activity;
28 import android.bluetooth.BluetoothAdapter;
29 import android.bluetooth.BluetoothDevice;
30 import android.content.BroadcastReceiver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.os.Bundle;
35 import android.view.View;
36 import android.view.Window;
37 import android.view.View.OnClickListener;
38 import android.widget.*;
39 import android.widget.AdapterView.*;
40 import android.location.Location;
41 import android.location.LocationManager;
42 import android.location.LocationListener;
43 import android.location.Criteria;
45 import org.altusmetrum.altoslib_13.*;
48 * This Activity appears as a dialog. It lists any paired devices and
49 * devices detected in the area after discovery. When a device is chosen
50 * by the user, the MAC address of the device is sent back to the parent
51 * Activity in the result Intent.
53 public class PreloadMapActivity extends Activity implements AltosLaunchSiteListener, AltosMapLoaderListener, LocationListener {
55 private ArrayAdapter<AltosLaunchSite> known_sites_adapter;
58 private CheckBox hybrid;
59 private CheckBox satellite;
60 private CheckBox roadmap;
61 private CheckBox terrain;
64 private Spinner known_sites_spinner;
65 private Spinner min_zoom;
66 private Spinner max_zoom;
67 private TextView radius_label;
68 private Spinner radius;
70 private EditText latitude;
71 private EditText longitude;
73 private ProgressBar progress;
75 private AltosMapLoader loader;
77 long loader_notify_time;
79 /* AltosMapLoaderListener interfaces */
80 public void loader_start(final int max) {
81 loader_notify_time = System.currentTimeMillis();
83 this.runOnUiThread(new Runnable() {
86 progress.setProgress(0);
91 public void loader_notify(final int cur, final int max, final String name) {
92 long now = System.currentTimeMillis();
94 if (now - loader_notify_time < 100)
97 loader_notify_time = now;
99 this.runOnUiThread(new Runnable() {
101 progress.setProgress(cur);
106 public void loader_done(int max) {
108 this.runOnUiThread(new Runnable() {
110 progress.setProgress(0);
116 public void debug(String format, Object ... arguments) {
117 AltosDebug.debug(format, arguments);
120 /* AltosLaunchSiteListener interface */
122 public void notify_launch_sites(final List<AltosLaunchSite> sites) {
123 this.runOnUiThread(new Runnable() {
125 for (AltosLaunchSite site : sites)
126 known_sites_adapter.add(site);
131 /* LocationProvider interface */
133 AltosLaunchSite current_location_site;
135 public void onLocationChanged(Location location) {
136 AltosDebug.debug("location changed");
137 if (current_location_site == null) {
138 AltosLaunchSite selected_item = (AltosLaunchSite) known_sites_spinner.getSelectedItem();
140 current_location_site = new AltosLaunchSite("Current Location", location.getLatitude(), location.getLongitude());
141 known_sites_adapter.insert(current_location_site, 0);
143 if (selected_item != null)
144 known_sites_spinner.setSelection(known_sites_adapter.getPosition(selected_item));
146 latitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.latitude)));
147 longitude.setText(new StringBuffer(String.format("%12.6f", current_location_site.longitude)));
150 current_location_site.latitude = location.getLatitude();
151 current_location_site.longitude = location.getLongitude();
155 public void onStatusChanged(String provider, int status, Bundle extras) {
158 public void onProviderEnabled(String provider) {
161 public void onProviderDisabled(String provider) {
164 private double text(EditText view) throws ParseException {
165 return AltosParse.parse_double_locale(view.getEditableText().toString());
168 private double latitude() throws ParseException {
169 return text(latitude);
172 private double longitude() throws ParseException {
173 return text(longitude);
176 private int value(Spinner spinner) {
177 return (Integer) spinner.getSelectedItem();
180 private int min_z() {
181 return value(min_zoom);
184 private int max_z() {
185 return value(max_zoom);
188 private double value_distance(Spinner spinner) {
189 return (Double) spinner.getSelectedItem();
192 private double radius() {
193 double r = value_distance(radius);
194 if (AltosPreferences.imperial_units())
195 r = AltosConvert.miles_to_meters(r);
202 private int bit(CheckBox box, int value) {
209 private int types() {
211 return (bit(hybrid, AltosMap.maptype_hybrid) |
212 bit(satellite, AltosMap.maptype_satellite) |
213 bit(roadmap, AltosMap.maptype_roadmap) |
214 bit(terrain, AltosMap.maptype_terrain));
216 return 1 << AltosMap.maptype_hybrid;
219 private void load() {
224 double lat = latitude();
225 double lon = longitude();
231 AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
232 lat, lon, min, max, r, t);
233 loader = new AltosMapLoader(this, lat, lon, min, max, r, t, AltosMapOffline.scale);
234 } catch (ParseException e) {
235 AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
239 private void add_numbers(Spinner spinner, int min, int max, int def) {
241 ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item);
246 for (int i = min; i <= max; i++) {
247 adapter.add(new Integer(i));
253 spinner.setAdapter(adapter);
254 spinner.setSelection(spinner_def);
258 private void add_distance(Spinner spinner, double[] distances_km, double def_km, double[] distances_mi, double def_mi) {
260 ArrayAdapter<Double> adapter = new ArrayAdapter<Double>(this, android.R.layout.simple_spinner_item);
267 if (AltosPreferences.imperial_units()) {
268 distances = distances_mi;
271 distances = distances_km;
275 for (int i = 0; i < distances.length; i++) {
276 adapter.add(distances[i]);
277 if (distances[i] == def)
282 spinner.setAdapter(adapter);
283 spinner.setSelection(spinner_def);
288 class SiteListListener implements OnItemSelectedListener {
289 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
290 AltosLaunchSite site = (AltosLaunchSite) parent.getItemAtPosition(pos);
291 latitude.setText(new StringBuffer(String.format("%12.6f", site.latitude)));
292 longitude.setText(new StringBuffer(String.format("%12.6f", site.longitude)));
294 public void onNothingSelected(AdapterView<?> parent) {
297 public SiteListListener() {
301 double[] radius_mi = { 1, 2, 5, 10, 20 };
302 double radius_def_mi = 2;
303 double[] radius_km = { 1, 2, 5, 10, 20, 30 };
304 double radius_def_km = 2;
307 protected void onCreate(Bundle savedInstanceState) {
308 super.onCreate(savedInstanceState);
311 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
312 setContentView(R.layout.map_preload);
314 // Set result CANCELED incase the user backs out
315 setResult(Activity.RESULT_CANCELED);
317 // Initialize the button to perform device discovery
318 Button loadButton = (Button) findViewById(R.id.preload_load);
319 loadButton.setOnClickListener(new OnClickListener() {
320 public void onClick(View v) {
325 latitude = (EditText) findViewById(R.id.preload_latitude);
326 longitude = (EditText) findViewById(R.id.preload_longitude);
329 hybrid = (CheckBox) findViewById(R.id.preload_hybrid);
330 satellite = (CheckBox) findViewById(R.id.preload_satellite);
331 roadmap = (CheckBox) findViewById(R.id.preload_roadmap);
332 terrain = (CheckBox) findViewById(R.id.preload_terrain);
334 hybrid.setChecked(true);
337 min_zoom = (Spinner) findViewById(R.id.preload_min_zoom);
338 add_numbers(min_zoom,
339 AltosMap.min_zoom - AltosMap.default_zoom,
340 AltosMap.max_zoom - AltosMap.default_zoom, -2);
341 max_zoom = (Spinner) findViewById(R.id.preload_max_zoom);
342 add_numbers(max_zoom,
343 AltosMap.min_zoom - AltosMap.default_zoom,
344 AltosMap.max_zoom - AltosMap.default_zoom, 2);
345 radius_label = (TextView) findViewById(R.id.preload_radius_label);
346 radius = (Spinner) findViewById(R.id.preload_radius);
347 if (AltosPreferences.imperial_units())
348 radius_label.setText("Radius (miles)");
350 radius_label.setText("Radius (km)");
351 add_distance(radius, radius_km, radius_def_km, radius_mi, radius_def_mi);
353 progress = (ProgressBar) findViewById(R.id.preload_progress);
355 // Initialize array adapters. One for already paired devices and
356 // one for newly discovered devices
357 known_sites_spinner = (Spinner) findViewById(R.id.preload_site_list);
359 known_sites_adapter = new ArrayAdapter<AltosLaunchSite>(this, android.R.layout.simple_spinner_item);
361 known_sites_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
363 known_sites_spinner.setAdapter(known_sites_adapter);
364 known_sites_spinner.setOnItemSelectedListener(new SiteListListener());
366 // Listen for GPS and Network position updates
367 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
369 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
371 new AltosLaunchSites(this);
375 protected void onDestroy() {
381 // Stop listening for location updates
382 ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);