X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altosdroid%2Fsrc%2Forg%2Faltusmetrum%2FAltosDroid%2FAltosDroid.java;h=4e7bdd6b331dc7b2d3bd10274d6f75e00f81aef0;hp=54b61c67ca793849d19e0c3707e49977d7165d93;hb=cdd7ad469728fde178c69b9c99d70d6e0ab3f12d;hpb=ffdfc08c317f503e30604d058749b24c3ca7bafa diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 54b61c67..4e7bdd6b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Mike Beattie + * Copyright © 2012-2013 Mike Beattie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,11 @@ package org.altusmetrum.AltosDroid; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Timer; +import java.util.TimerTask; + import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -24,73 +29,125 @@ import android.content.Intent; import android.content.Context; import android.content.ComponentName; import android.content.ServiceConnection; +import android.content.DialogInterface; import android.os.IBinder; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; -import android.text.method.ScrollingMovementMethod; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.util.DisplayMetrics; import android.util.Log; -//import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -//import android.view.View; import android.view.Window; -//import android.view.View.OnClickListener; -//import android.view.inputmethod.EditorInfo; -//import android.widget.Button; -//import android.widget.EditText; +import android.view.View; +import android.widget.TabHost; import android.widget.TextView; +import android.widget.RelativeLayout; import android.widget.Toast; -import org.altusmetrum.AltosDroid.R; +import android.app.AlertDialog; +import android.location.Location; -/** - * This is the main Activity that displays the current chat session. - */ -public class AltosDroid extends Activity { +import org.altusmetrum.altoslib_6.*; + +public class AltosDroid extends FragmentActivity implements AltosUnitsListener { // Debugging - private static final String TAG = "AltosDroid"; - private static final boolean D = true; + static final String TAG = "AltosDroid"; + static final boolean D = true; - // Message types sent from the BluetoothChatService Handler - public static final int MESSAGE_STATE_CHANGE = 1; - public static final int MESSAGE_READ = 2; - public static final int MESSAGE_WRITE = 3; - public static final int MESSAGE_DEVICE_NAME = 4; - public static final int MESSAGE_TOAST = 5; + // Message types received by our Handler - // Key names received from the BluetoothChatService Handler - public static final String DEVICE_NAME = "device_name"; - public static final String TOAST = "toast"; + public static final int MSG_STATE = 1; + public static final int MSG_UPDATE_AGE = 2; + // Intent request codes + public static final int REQUEST_CONNECT_DEVICE = 1; + public static final int REQUEST_ENABLE_BT = 2; + public static FragmentManager fm; - // Intent request codes - private static final int REQUEST_CONNECT_DEVICE = 1; - private static final int REQUEST_ENABLE_BT = 2; + private BluetoothAdapter mBluetoothAdapter = null; // Layout Views private TextView mTitle; - private TextView mSerialView; - //private EditText mOutEditText; - //private Button mSendButton; - - private boolean mIsBound; - Messenger mService = null; - - // Name of the connected device - private String mConnectedDeviceName = null; - // Local Bluetooth adapter - private BluetoothAdapter mBluetoothAdapter = null; + // Flight state values + private TextView mCallsignView; + private TextView mRSSIView; + private TextView mSerialView; + private TextView mFlightView; + private RelativeLayout mStateLayout; + private TextView mStateView; + private TextView mAgeView; + + // field to display the version at the bottom of the screen + private TextView mVersion; + + private double frequency; + private int telemetry_rate; + + // Tabs + TabHost mTabHost; + AltosViewPager mViewPager; + TabsAdapter mTabsAdapter; + ArrayList mTabs = new ArrayList(); + int tabHeight; + + // Timer and Saved flight state for Age calculation + private Timer timer; + AltosState saved_state; + + // Service + private boolean mIsBound = false; + private Messenger mService = null; + final Messenger mMessenger = new Messenger(new IncomingHandler(this)); + + // Text to Speech + private AltosVoice mAltosVoice = null; + + // The Handler that gets information back from the Telemetry Service + static class IncomingHandler extends Handler { + private final WeakReference mAltosDroid; + IncomingHandler(AltosDroid ad) { mAltosDroid = new WeakReference(ad); } + + @Override + public void handleMessage(Message msg) { + AltosDroid ad = mAltosDroid.get(); + + switch (msg.what) { + case MSG_STATE: + if(D) Log.d(TAG, "MSG_STATE"); + TelemetryState telemetry_state = (TelemetryState) msg.obj; + if (telemetry_state == null) { + Log.d(TAG, "telemetry_state null!"); + return; + } + + ad.update_state(telemetry_state); + break; + case MSG_UPDATE_AGE: + if(D) Log.d(TAG, "MSG_UPDATE_AGE"); + ad.update_age(); + break; + } + } }; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = new Messenger(service); + try { + Message msg = Message.obtain(null, TelemetryService.MSG_REGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + } catch (RemoteException e) { + // In this case the service has crashed before we could even do anything with it + } } public void onServiceDisconnected(ComponentName className) { @@ -99,27 +156,245 @@ public class AltosDroid extends Activity { } }; + void doBindService() { + bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + // If we have received the service, and hence registered with it, then now is the time to unregister. + if (mService != null) { + try { + Message msg = Message.obtain(null, TelemetryService.MSG_UNREGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + } catch (RemoteException e) { + // There is nothing special we need to do if the service has crashed. + } + } + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } + } + + public void registerTab(AltosDroidTab mTab) { + mTabs.add(mTab); + } + + public void unregisterTab(AltosDroidTab mTab) { + mTabs.remove(mTab); + } + + public void units_changed(boolean imperial_units) { + for (AltosDroidTab mTab : mTabs) + mTab.units_changed(imperial_units); + } + + void update_title(TelemetryState telemetry_state) { + switch (telemetry_state.connect) { + case TelemetryState.CONNECT_CONNECTED: + if (telemetry_state.config != null) { + String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial, + telemetry_state.frequency); + if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400) + str = str.concat(String.format(" %d bps", + AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate])); + mTitle.setText(str); + } else { + mTitle.setText(R.string.title_connected_to); + } + break; + case TelemetryState.CONNECT_CONNECTING: + if (telemetry_state.address != null) + mTitle.setText(String.format("Connecting to %s...", telemetry_state.address.name)); + else + mTitle.setText("Connecting to something..."); + break; + case TelemetryState.CONNECT_DISCONNECTED: + case TelemetryState.CONNECT_NONE: + mTitle.setText(R.string.title_not_connected); + break; + } + } + + void start_timer() { + if (timer == null) { + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L); + } + } + + void stop_timer() { + if (timer != null) { + timer.cancel(); + timer.purge(); + timer = null; + } + } + + boolean registered_units_listener; + + void update_state(TelemetryState telemetry_state) { + + if (!registered_units_listener) { + registered_units_listener = true; + AltosPreferences.register_units_listener(this); + } + + update_title(telemetry_state); + update_ui(telemetry_state.state, telemetry_state.location); + if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) + start_timer(); + } + + boolean same_string(String a, String b) { + if (a == null) { + if (b == null) + return true; + return false; + } else { + if (b == null) + return false; + return a.equals(b); + } + } + + void update_age() { + if (saved_state != null) + mAgeView.setText(String.format("%d", (System.currentTimeMillis() - saved_state.received_time + 500) / 1000)); + } + + void update_ui(AltosState state, Location location) { + + int prev_state = AltosLib.ao_flight_invalid; + + AltosGreatCircle from_receiver = null; + + if (saved_state != null) + prev_state = saved_state.state; + + if (state != null) { + if (state.state == AltosLib.ao_flight_stateless) { + boolean prev_locked = false; + boolean locked = false; + + if(state.gps != null) + locked = state.gps.locked; + if (saved_state != null && saved_state.gps != null) + prev_locked = saved_state.gps.locked; + if (prev_locked != locked) { + String currentTab = mTabHost.getCurrentTabTag(); + if (locked) { + if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); + } else { + if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("pad"); + } + } + } else { + if (prev_state != state.state) { + String currentTab = mTabHost.getCurrentTabTag(); + switch (state.state) { + case AltosLib.ao_flight_boost: + if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); + break; + case AltosLib.ao_flight_drogue: + if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent"); + break; + case AltosLib.ao_flight_landed: + if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed"); + break; + case AltosLib.ao_flight_stateless: + if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); + break; + } + } + } + + if (location != null && state.gps != null && state.gps.locked) { + double altitude = 0; + if (location.hasAltitude()) + altitude = location.getAltitude(); + from_receiver = new AltosGreatCircle(location.getLatitude(), + location.getLongitude(), + altitude, + state.gps.lat, + state.gps.lon, + state.gps.alt); + } + + if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) { + mCallsignView.setText(state.callsign); + } + if (saved_state == null || state.serial != saved_state.serial) { + mSerialView.setText(String.format("%d", state.serial)); + } + if (saved_state == null || state.flight != saved_state.flight) { + if (state.flight == AltosLib.MISSING) + mFlightView.setText(""); + else + mFlightView.setText(String.format("%d", state.flight)); + } + if (saved_state == null || state.state != saved_state.state) { + if (state.state == AltosLib.ao_flight_stateless) { + mStateLayout.setVisibility(View.GONE); + } else { + mStateView.setText(state.state_name()); + mStateLayout.setVisibility(View.VISIBLE); + } + } + if (saved_state == null || state.rssi != saved_state.rssi) { + mRSSIView.setText(String.format("%d", state.rssi)); + } + } + + for (AltosDroidTab mTab : mTabs) + mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem()); + + if (state != null && mAltosVoice != null) + mAltosVoice.tell(state, from_receiver); + + saved_state = state; + } + + private void onTimerTick() { + try { + mMessenger.send(Message.obtain(null, MSG_UPDATE_AGE)); + } catch (RemoteException e) { + } + } + + static String pos(double p, String pos, String neg) { + String h = pos; + if (p == AltosLib.MISSING) + return ""; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%d°%9.4f\" %s", deg, min, h); + } + + static String number(String format, double value) { + if (value == AltosLib.MISSING) + return ""; + return String.format(format, value); + } + + static String integer(String format, int value) { + if (value == AltosLib.MISSING) + return ""; + return String.format(format, value); + } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(D) Log.e(TAG, "+++ ON CREATE +++"); - // Set up the window layout - requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); - setContentView(R.layout.main); - getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); - - // Set up the custom title - mTitle = (TextView) findViewById(R.id.title_left_text); - mTitle.setText(R.string.app_name); - mTitle = (TextView) findViewById(R.id.title_right_text); - - mSerialView = (TextView) findViewById(R.id.in); - mSerialView.setMovementMethod(new ScrollingMovementMethod()); - mSerialView.setClickable(false); - mSerialView.setLongClickable(false); - // Get local Bluetooth adapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -127,13 +402,69 @@ public class AltosDroid extends Activity { if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); finish(); - return; } - // Start Telemetry Service - startService(new Intent(AltosDroid.this, TelemetryService.class)); + fm = getSupportFragmentManager(); - doBindService(); + // Set up the window layout + requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); + setContentView(R.layout.altosdroid); + getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); + + // Create the Tabs and ViewPager + mTabHost = (TabHost)findViewById(android.R.id.tabhost); + mTabHost.setup(); + + mViewPager = (AltosViewPager)findViewById(R.id.pager); + mViewPager.setOffscreenPageLimit(4); + + mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); + + mTabsAdapter.addTab(mTabHost.newTabSpec("pad").setIndicator("Pad"), TabPad.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("ascent").setIndicator("Ascent"), TabAscent.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("descent").setIndicator("Descent"), TabDescent.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("landed").setIndicator("Landed"), TabLanded.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("map").setIndicator("Map"), TabMap.class, null); + + + // Scale the size of the Tab bar for different screen densities + // This probably won't be needed when we start supporting ICS+ tabs. + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + int density = metrics.densityDpi; + + if (density==DisplayMetrics.DENSITY_XHIGH) + tabHeight = 65; + else if (density==DisplayMetrics.DENSITY_HIGH) + tabHeight = 45; + else if (density==DisplayMetrics.DENSITY_MEDIUM) + tabHeight = 35; + else if (density==DisplayMetrics.DENSITY_LOW) + tabHeight = 25; + else + tabHeight = 65; + + for (int i = 0; i < 5; i++) + mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = tabHeight; + + // Set up the custom title + mTitle = (TextView) findViewById(R.id.title_left_text); + mTitle.setText(R.string.app_name); + mTitle = (TextView) findViewById(R.id.title_right_text); + + // Display the Version + mVersion = (TextView) findViewById(R.id.version); + mVersion.setText("Version: " + BuildInfo.version + + " Built: " + BuildInfo.builddate + " " + BuildInfo.buildtime + " " + BuildInfo.buildtz + + " (" + BuildInfo.branch + "-" + BuildInfo.commitnum + "-" + BuildInfo.commithash + ")"); + + mCallsignView = (TextView) findViewById(R.id.callsign_value); + mRSSIView = (TextView) findViewById(R.id.rssi_value); + mSerialView = (TextView) findViewById(R.id.serial_value); + mFlightView = (TextView) findViewById(R.id.flight_value); + mStateLayout = (RelativeLayout) findViewById(R.id.state_container); + mStateView = (TextView) findViewById(R.id.state_value); + mAgeView = (TextView) findViewById(R.id.age_value); } @Override @@ -141,33 +472,28 @@ public class AltosDroid extends Activity { super.onStart(); if(D) Log.e(TAG, "++ ON START ++"); + // Start Telemetry Service + startService(new Intent(AltosDroid.this, TelemetryService.class)); + if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableIntent, REQUEST_ENABLE_BT); - } else { - //if (mChatService == null) setupChat(); + startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT); } + + doBindService(); + + if (mAltosVoice == null) + mAltosVoice = new AltosVoice(this); } @Override - public synchronized void onResume() { + public void onResume() { super.onResume(); if(D) Log.e(TAG, "+ ON RESUME +"); - - // Performing this check in onResume() covers the case in which BT was - // not enabled during onStart(), so we were paused to enable it... - // onResume() will be called when ACTION_REQUEST_ENABLE activity returns. - //if (mChatService != null) { - // Only if the state is STATE_NONE, do we know that we haven't started already - //if (mChatService.getState() == BluetoothChatService.STATE_NONE) { - // Start the Bluetooth chat services - //mChatService.start(); - //} - //} } @Override - public synchronized void onPause() { + public void onPause() { super.onPause(); if(D) Log.e(TAG, "- ON PAUSE -"); } @@ -176,85 +502,22 @@ public class AltosDroid extends Activity { public void onStop() { super.onStop(); if(D) Log.e(TAG, "-- ON STOP --"); + + doUnbindService(); + if (mAltosVoice != null) { + mAltosVoice.stop(); + mAltosVoice = null; + } } @Override public void onDestroy() { super.onDestroy(); - - doUnbindService(); - if(D) Log.e(TAG, "--- ON DESTROY ---"); - } - - -/* - private void setupChat() { - Log.d(TAG, "setupChat()"); - - // Initialize the compose field with a listener for the return key - mOutEditText = (EditText) findViewById(R.id.edit_text_out); - mOutEditText.setOnEditorActionListener(mWriteListener); - - // Initialize the send button with a listener that for click events - mSendButton = (Button) findViewById(R.id.button_send); - mSendButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - // Send a message using content of the edit text widget - TextView view = (TextView) findViewById(R.id.edit_text_out); - String message = view.getText().toString(); - sendMessage(message); - } - }); - - // Initialize the BluetoothChatService to perform bluetooth connections - mChatService = new BluetoothChatService(this, mHandler); - - // Initialize the buffer for outgoing messages - mOutStringBuffer = new StringBuffer(""); + if (mAltosVoice != null) mAltosVoice.stop(); + stop_timer(); } -*/ - - /** - * Sends a message. - * @param message A string of text to send. - */ - /* - private void sendMessage(String message) { - // Check that we're actually connected before trying anything - if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { - Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show(); - return; - } - - // Check that there's actually something to send - if (message.length() > 0) { - // Get the message bytes and tell the BluetoothChatService to write - byte[] send = message.getBytes(); - mChatService.write(send); - - // Reset out string buffer to zero and clear the edit text field - mOutStringBuffer.setLength(0); - mOutEditText.setText(mOutStringBuffer); - } - } - - - // The action listener for the EditText widget, to listen for the return key - private TextView.OnEditorActionListener mWriteListener = - new TextView.OnEditorActionListener() { - public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { - // If the action is a key-up event on the return key, send the message - if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { - String message = view.getText().toString(); - sendMessage(message); - } - if(D) Log.i(TAG, "END onEditorAction"); - return true; - } - }; - */ public void onActivityResult(int requestCode, int resultCode, Intent data) { if(D) Log.d(TAG, "onActivityResult " + resultCode); @@ -272,22 +535,36 @@ public class AltosDroid extends Activity { //setupChat(); } else { // User did not enable Bluetooth or an error occured - Log.d(TAG, "BT not enabled"); + Log.e(TAG, "BT not enabled"); stopService(new Intent(AltosDroid.this, TelemetryService.class)); - Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show(); finish(); } + break; } } private void connectDevice(Intent data) { - // Get the device MAC address - String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); - // Get the BLuetoothDevice object - BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device + try { + String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); + String name = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_NAME); + + if (D) Log.d(TAG, "Connecting to " + address + " " + name); + DeviceAddress a = new DeviceAddress(address, name); + mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, a)); + if (D) Log.d(TAG, "Sent connecting message"); + } catch (RemoteException e) { + if (D) Log.e(TAG, "connect device message failed"); + } } + private void disconnectDevice() { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_DISCONNECT, null)); + } catch (RemoteException e) { + } + } @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -296,6 +573,47 @@ public class AltosDroid extends Activity { return true; } + void setFrequency(double freq) { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_SETFREQUENCY, freq)); + } catch (RemoteException e) { + } + } + + void setFrequency(String freq) { + try { + setFrequency (Double.parseDouble(freq.substring(11, 17))); + } catch (NumberFormatException e) { + } + } + + void setBaud(int baud) { + try { + mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud)); + } catch (RemoteException e) { + } + } + + void setBaud(String baud) { + try { + int value = Integer.parseInt(baud); + int rate = AltosLib.ao_telemetry_rate_38400; + switch (value) { + case 2400: + rate = AltosLib.ao_telemetry_rate_2400; + break; + case 9600: + rate = AltosLib.ao_telemetry_rate_9600; + break; + case 38400: + rate = AltosLib.ao_telemetry_rate_38400; + break; + } + setBaud(rate); + } catch (NumberFormatException e) { + } + } + @Override public boolean onOptionsItemSelected(MenuItem item) { Intent serverIntent = null; @@ -305,23 +623,69 @@ public class AltosDroid extends Activity { serverIntent = new Intent(this, DeviceListActivity.class); startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); return true; + case R.id.disconnect: + /* Disconnect the bluetooth device + */ + disconnectDevice(); + return true; + case R.id.quit: + Log.d(TAG, "R.id.quit"); + disconnectDevice(); + finish(); + return true; + case R.id.select_freq: + // Set the TBT radio frequency + + final String[] frequencies = { + "Channel 0 (434.550MHz)", + "Channel 1 (434.650MHz)", + "Channel 2 (434.750MHz)", + "Channel 3 (434.850MHz)", + "Channel 4 (434.950MHz)", + "Channel 5 (435.050MHz)", + "Channel 6 (435.150MHz)", + "Channel 7 (435.250MHz)", + "Channel 8 (435.350MHz)", + "Channel 9 (435.450MHz)" + }; + + AlertDialog.Builder builder_freq = new AlertDialog.Builder(this); + builder_freq.setTitle("Pick a frequency"); + builder_freq.setItems(frequencies, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + setFrequency(frequencies[item]); + } + }); + AlertDialog alert_freq = builder_freq.create(); + alert_freq.show(); + return true; + case R.id.select_rate: + // Set the TBT baud rate + + final String[] rates = { + "38400", + "9600", + "2400", + }; + + AlertDialog.Builder builder_rate = new AlertDialog.Builder(this); + builder_rate.setTitle("Pick a baud rate"); + builder_rate.setItems(rates, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + setBaud(rates[item]); + } + }); + AlertDialog alert_rate = builder_rate.create(); + alert_rate.show(); + return true; + case R.id.change_units: + boolean imperial = AltosPreferences.imperial_units(); + AltosPreferences.set_imperial_units(!imperial); + return true; } return false; } - - void doBindService() { - bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - - void doUnbindService() { - if (mIsBound) { - // If we have received the service, and hence registered with it, then now is the time to unregister. - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } - }