Android Open Source - speedofsound Speed Activity






From Project

Back to project page speedofsound.

License

The source code is released under:

GNU General Public License

If you think the Android project speedofsound listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package net.codechunk.speedofsound;
/* w w  w  .j a  v  a  2s  .c  om*/
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.google.android.gms.common.GooglePlayServicesUtil;

import net.codechunk.speedofsound.service.SoundService;
import net.codechunk.speedofsound.util.SpeedConversions;

/**
 * Main status activity. Displays the current speed and set volume. Does not
 * actually track the volume itself; that is handled in SoundService.
 */
public class SpeedActivity extends ActionBarActivity implements View.OnClickListener {
  private static final String TAG = "SpeedActivity";

  private enum UIState {
    INACTIVE, ACTIVE, TRACKING
  }

  private UIState uiState;

  /**
   * Disclaimer dialog unique ID.
   */
  private static final int DIALOG_DISCLAIMER = 1;

  /**
   * GPS nag dialog unique ID.
   */
  private static final int DIALOG_GPS = 2;

  /**
   * Application's shared preferences.
   */
  private SharedPreferences settings;

  /**
   * The main "Enable Speed of Sound" checkbox.
   */
  private CheckBox enabledCheckBox;

  /**
   * Whether we're bound to the background service or not. If everything is
   * working, this should be true.
   */
  private boolean bound = false;

  /**
   * The background service.
   */
  private SoundService service;

  /**
   * Load the view and attach a checkbox listener.
   */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.main);

    // hook up the checkbox
    this.settings = PreferenceManager.getDefaultSharedPreferences(this);
    this.enabledCheckBox = (CheckBox) findViewById(R.id.checkbox_enabled);
    this.enabledCheckBox.setOnClickListener(this);
    this.uiState = UIState.INACTIVE;

    // show disclaimer and/or GPS nag
    this.startupMessages();
  }

  /**
   * Start the service with the view, if it wasn't already running.
   */
  @Override
  public void onStart() {
    super.onStart();
    Log.d(TAG, "View starting");

    // bind to our service after explicitly starting it
    Intent intent = new Intent(this, SoundService.class);
    startService(intent);
    bindService(intent, this.serviceConnection, 0);
  }

  /**
   * Stop the view and unbind from the service (but don't stop that).
   */
  @Override
  public void onStop() {
    super.onStop();
    Log.d(TAG, "View stopping");

    // unbind from our service
    if (this.bound) {
      unbindService(this.serviceConnection);
      this.bound = false;
    }
  }

  /**
   * Pause the view and stop listening to broadcasts.
   */
  @Override
  public void onPause() {
    super.onPause();
    Log.d(TAG, "Paused, unsubscribing from updates");

    LocalBroadcastManager.getInstance(this).unregisterReceiver(this.messageReceiver);
  }

  /**
   * Resume the view and subscribe to broadcasts.
   */
  @Override
  public void onResume() {
    super.onResume();
    Log.d(TAG, "Resumed, subscribing to service updates");

    LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
    IntentFilter filter = new IntentFilter();
    filter.addAction(SoundService.LOCATION_UPDATE_BROADCAST);
    filter.addAction(SoundService.TRACKING_STATE_BROADCAST);
    lbm.registerReceiver(this.messageReceiver, filter);
  }

  /**
   * Create disclaimer/gps dialogs to show.
   */
  protected Dialog onCreateDialog(int id) {
    Dialog dialog;
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    switch (id) {
      case DIALOG_DISCLAIMER:
        builder.setMessage(getString(R.string.launch_disclaimer))
            .setTitle(getString(R.string.warning))
            .setCancelable(false)
            .setPositiveButton(getString(R.string.launch_disclaimer_accept),
                new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int id) {
                    SpeedActivity.this.checkGPS();
                  }
                });
        dialog = builder.create();
        break;

      case DIALOG_GPS:
        builder.setMessage(getString(R.string.gps_warning))
            .setCancelable(false)
            .setPositiveButton(getString(R.string.location_settings),
                new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int which) {
                    startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                  }
                })
            .setNegativeButton(getString(R.string.gps_warning_dismiss), null);
        dialog = builder.create();
        break;

      default:
        dialog = null;
    }
    return dialog;
  }

  /**
   * Show some startup messages. Will show the disclaimer dialog if this is
   * the first run. If GPS is disabled, will show another dialog to ask to
   * enable it.
   */
  @SuppressWarnings("deprecation")
  private void startupMessages() {
    // only show disclaimers and the like once
    boolean runonce = this.settings.getBoolean("runonce", false);

    // firstrun things
    if (!runonce) {
      SharedPreferences.Editor editor = this.settings.edit();
      editor.putBoolean("runonce", true);
      editor.commit();

      // driving disclaimer (followed by GPS)
      this.showDialog(DIALOG_DISCLAIMER);
    } else {
      // GPS notice
      this.checkGPS();
    }
  }

  /**
   * Check if GPS is enabled. If it isn't, bug the user to turn it on.
   */
  @SuppressWarnings("deprecation")
  private void checkGPS() {
    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
      this.showDialog(DIALOG_GPS);
    }
  }

  /**
   * Start or stop tracking in the service on checked/unchecked.
   */
  @Override
  public void onClick(View view) {
    boolean isChecked = ((CheckBox) view).isChecked();
    Log.d(TAG, "Checkbox changed to " + isChecked);

    // uh-oh
    if (!this.bound) {
      Log.e(TAG, "Service is unavailable");
      return;
    }

    // start up the service
    if (isChecked) {
      this.service.startTracking();

      // update the UI
      this.updateStatusState(UIState.ACTIVE);

      // reset speed/volume to waiting state.
      // we don't do this in updateStatusState as that would happen too
      // frequently.
      TextView speed = (TextView) findViewById(R.id.speed_value);
      TextView volume = (TextView) findViewById(R.id.volume_value);
      speed.setText(getString(R.string.waiting));
      volume.setText(getString(R.string.waiting));
    }
    // stop the service
    else {
      this.service.stopTracking();

      // update the UI
      this.updateStatusState(UIState.INACTIVE);
    }
  }

  /**
   * Switch between the intro message and the speed details.
   *
   * @param tracking The current tracking state
   */
  private void updateStatusState(UIState state) {
    View trackingDetails = findViewById(R.id.tracking_details);
    trackingDetails.setVisibility(state == UIState.TRACKING ? View.VISIBLE : View.GONE);

    View waitingForGps = findViewById(R.id.waiting_for_gps);
    waitingForGps.setVisibility(state == UIState.ACTIVE ? View.VISIBLE : View.GONE);

    View inactiveIntro = findViewById(R.id.inactive_intro);
    inactiveIntro.setVisibility(state == UIState.INACTIVE ? View.VISIBLE : View.GONE);
  }

  /**
   * Handle incoming broadcasts from the service.
   */
  private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
    /**
     * Receive a speed/sound status update.
     */
    @Override
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      Log.v(TAG, "Received broadcast " + action);

      if (SoundService.TRACKING_STATE_BROADCAST.equals(action)) {
        boolean tracking = intent.getBooleanExtra("tracking", false);
        SpeedActivity.this.enabledCheckBox.setChecked(tracking);
        SpeedActivity.this.updateStatusState(tracking ? UIState.ACTIVE : UIState.INACTIVE);
      }

      // new location data
      else if (SoundService.LOCATION_UPDATE_BROADCAST.equals(action)) {
        // unpack the speed/volume
        float speed = intent.getFloatExtra("speed", -1.0f);
        int volume = intent.getIntExtra("volumePercent", -1);

        // convert the speed to the appropriate units
        String units = SpeedActivity.this.settings.getString("speed_units", "");
        float localizedSpeed = SpeedConversions.localizedSpeed(units, speed);

        SpeedActivity.this.updateStatusState(UIState.TRACKING);

        // display the speed
        TextView speedView = (TextView) findViewById(R.id.speed_value);
        speedView.setText(String.format("%.1f %s", localizedSpeed, units));

        // display the volume as well
        TextView volumeView = (TextView) findViewById(R.id.volume_value);
        volumeView.setText(String.format("%d%%", volume));

        // ui goodies
        TextView volumeDesc = (TextView) findViewById(R.id.volume_description);
        int lowVolume = SpeedActivity.this.settings.getInt("low_volume", 0);
        int highVolume = SpeedActivity.this.settings.getInt("high_volume", 100);

        // show different text values depending on the limits hit
        if (volume <= lowVolume) {
          volumeDesc.setText(getString(R.string.volume_header_low));
        } else if (volume >= highVolume) {
          volumeDesc.setText(getText(R.string.volume_header_high));
        } else {
          volumeDesc.setText(getText(R.string.volume_header_scaled));
        }
      }
    }
  };

  /**
   * Attach to the sound service.
   */
  private ServiceConnection serviceConnection = new ServiceConnection() {
    /**
     * Trigger service and UI actions once we have a connection.
     */
    public void onServiceConnected(ComponentName className, IBinder service) {
      Log.v(TAG, "ServiceConnection connected");

      SoundService.LocalBinder binder = (SoundService.LocalBinder) service;
      SpeedActivity.this.service = binder.getService();
      SpeedActivity.this.bound = true;

      // update the enabled check box
      SpeedActivity.this.enabledCheckBox.setChecked(SpeedActivity.this.service.isTracking());
      SpeedActivity.this.updateStatusState(SpeedActivity.this.service.isTracking() ? UIState.ACTIVE : UIState.INACTIVE);

      // start tracking if preference set
      if (SpeedActivity.this.settings.getBoolean("enable_on_launch", false)) {
        SpeedActivity.this.service.startTracking();
      }
    }

    /**
     * Mark the service as unbound on disconnect.
     */
    public void onServiceDisconnected(ComponentName arg) {
      Log.v(TAG, "ServiceConnection disconnected");
      SpeedActivity.this.bound = false;
    }
  };

  /**
   * Show a menu on menu button press. Where supported, show an action item
   * instead.
   */
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.speed_menu, menu);
    MenuItemCompat.setShowAsAction(menu.findItem(R.id.preferences), MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
    MenuItemCompat.setShowAsAction(menu.findItem(R.id.view_map), MenuItemCompat.SHOW_AS_ACTION_ALWAYS);

    return true;
  }

  /**
   * Handle actions from the menu/action bar.
   */
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.preferences:
        startActivity(new Intent(this, PreferencesActivity.class));
        break;

      case R.id.view_map:
        // verify Google Play Services is available
        int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        Dialog dlg = GooglePlayServicesUtil.getErrorDialog(result, this, 0);
        if (dlg != null) {
          dlg.show();
          return true;
        }

        // launch the map
        startActivity(new Intent(this, MapperActivity.class));
        break;
    }
    return true;
  }
}




Java Source Code List

net.codechunk.speedofsound.LocaleActivity.java
net.codechunk.speedofsound.MapperActivity.java
net.codechunk.speedofsound.PreferencesActivity.java
net.codechunk.speedofsound.SongTracker.java
net.codechunk.speedofsound.SpeedActivity.java
net.codechunk.speedofsound.players.AndroidMusicPlayer.java
net.codechunk.speedofsound.players.BasePlayer.java
net.codechunk.speedofsound.players.HTCPlayer.java
net.codechunk.speedofsound.players.LastFmAPIPlayer.java
net.codechunk.speedofsound.players.SLSAPIPlayer.java
net.codechunk.speedofsound.players.SamsungPlayer.java
net.codechunk.speedofsound.players.WinampPlayer.java
net.codechunk.speedofsound.service.SoundServiceManager.java
net.codechunk.speedofsound.service.SoundService.java
net.codechunk.speedofsound.service.VolumeConversion.java
net.codechunk.speedofsound.service.VolumeThread.java
net.codechunk.speedofsound.util.AppPreferences.java
net.codechunk.speedofsound.util.AverageSpeed.java
net.codechunk.speedofsound.util.ColorCreator.java
net.codechunk.speedofsound.util.SliderPreference.java
net.codechunk.speedofsound.util.SongInfo.java
net.codechunk.speedofsound.util.SpeedConversions.java
net.codechunk.speedofsound.util.SpeedSliderPreference.java