Java tutorial
/* * DanceStepApp - Android App * Copyright (C) 2009 Levente Bagi * * 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 * the Free Software Foundation, either version 3 of tsetuphe License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package name.setup.dance; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import name.setup.dance.R; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.net.Uri; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.ImageView; import android.widget.Toast; public class DanceStepApp extends Activity { private static final String TAG = "DanceStepApp"; private SharedPreferences mSettings; private DanceStepAppSettings mDanceStepAppSettings; private Utils mUtils; private TextView mStepValueView; private Button mOkayButton; private Button mScoreButton; private EditText mTextField; private String mUserName; // private TextView mPaceValueView; // private TextView mDistanceValueView; // private TextView mSpeedValueView; // private TextView mCaloriesValueView; private ImageView mDanceLeftImage; private ImageView mDanceRightImage; private TextView mDesiredPaceView; private int mStepValue; private int mPaceValue; private float mDistanceValue; private float mSpeedValue; private int mCaloriesValue; private float mDesiredPaceOrSpeed; private int mMaintain; private boolean mIsMetric; private float mMaintainInc; private boolean mQuitting = false; // Set when user selected Quit from menu, can be used by onPause, onStop, onDestroy /** * True, when service is running. */ private boolean mIsRunning; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "[ACTIVITY] onCreate"); super.onCreate(savedInstanceState); //mStepValue = 0; mPaceValue = 0; setContentView(R.layout.main); mUtils = Utils.getInstance(); String m_szDevIDShort = "35" + //we make this look like a valid IMEI Build.BOARD.length() % 10 + Build.BRAND.length() % 10 + Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 + Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 + Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 + Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 + Build.TAGS.length() % 10 + Build.TYPE.length() % 10 + Build.USER.length() % 10; //13 digits mUtils.DeviceName = m_szDevIDShort; Log.v(TAG, "ID: " + m_szDevIDShort); Log.v(TAG, "UTILS: " + mUtils.DeviceName); // user name mTextField = (EditText) findViewById(R.id.name_area); mTextField.setCursorVisible(false); if (!(mUtils.UserName == "My Name")) { mTextField.setText(mUtils.UserName); } mTextField.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // only will trigger it if no physical keyboard is open mgr.showSoftInput(mTextField, InputMethodManager.SHOW_IMPLICIT); mTextField.requestFocus(); mTextField.setCursorVisible(true); mOkayButton.setVisibility(View.VISIBLE); } }); // init okay Button mOkayButton = (Button) findViewById(R.id.okay_button); mOkayButton.setVisibility(View.INVISIBLE); mOkayButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0); mTextField.setCursorVisible(false); mTextField.clearFocus(); mUtils.UserName = mTextField.getText().toString(); // post name via HHTP new Thread(new Runnable() { public void run() { if (mIsMetric) { postHTTP(mUtils.DeviceName, mUtils.UserName, mStepValue, mDistanceValue); } else { postHTTP(mUtils.DeviceName, mUtils.UserName, mStepValue, mDistanceValue * 1.609344f); } } }).start(); mOkayButton.setVisibility(View.INVISIBLE); // Post TOAST MESSAGE Toast.makeText(getApplicationContext(), getText(R.string.name_saved), Toast.LENGTH_SHORT).show(); } }); // init Score Button mScoreButton = (Button) findViewById(R.id.scoreButton); mScoreButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click String url = "http://www.setup.nl/tools/dancestep_app/index.php?id=" + mUtils.DeviceName + "&time=" + System.currentTimeMillis(); Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); } }); } @Override protected void onStart() { Log.i(TAG, "[ACTIVITY] onStart"); super.onStart(); } @Override protected void onResume() { Log.i(TAG, "[ACTIVITY] onResume"); super.onResume(); mSettings = PreferenceManager.getDefaultSharedPreferences(this); mDanceStepAppSettings = new DanceStepAppSettings(mSettings); mUtils.setSpeak(mSettings.getBoolean("speak", false)); // Read from preferences if the service was running on the last onPause mIsRunning = mDanceStepAppSettings.isServiceRunning(); // Start the service if this is considered to be an application start (last onPause was long ago) if (!mIsRunning && mDanceStepAppSettings.isNewStart()) { startStepService(); bindStepService(); } else if (mIsRunning) { bindStepService(); } mDanceStepAppSettings.clearServiceRunning(); mStepValueView = (TextView) findViewById(R.id.step_value); mDanceLeftImage = (ImageView) findViewById(R.id.dance_left_image); mDanceRightImage = (ImageView) findViewById(R.id.dance_right_image); mIsMetric = mDanceStepAppSettings.isMetric(); mUtils.UserName = mDanceStepAppSettings.getName(); mTextField.setText(mUtils.UserName); mStepValue = mDanceStepAppSettings.getSteps(); Log.i(TAG, "[ACTIVITY] loaded value; " + mUtils.UserName + " " + mStepValue); } @Override protected void onPause() { Log.i(TAG, "[ACTIVITY] onPause"); if (mIsRunning) { unbindStepService(); } if (mQuitting) { mDanceStepAppSettings.saveServiceRunningWithNullTimestamp(mIsRunning, mStepValue, mUtils.UserName); } else { mDanceStepAppSettings.saveServiceRunningWithTimestamp(mIsRunning, mStepValue, mUtils.UserName); } super.onPause(); savePaceSetting(); } @Override protected void onStop() { Log.i(TAG, "[ACTIVITY] onStop"); super.onStop(); } protected void onDestroy() { Log.i(TAG, "[ACTIVITY] onDestroy"); super.onDestroy(); } protected void onRestart() { Log.i(TAG, "[ACTIVITY] onRestart"); super.onDestroy(); } private void setDesiredPaceOrSpeed(float desiredPaceOrSpeed) { if (mService != null) { if (mMaintain == DanceStepAppSettings.M_PACE) { mService.setDesiredPace((int) desiredPaceOrSpeed); } else if (mMaintain == DanceStepAppSettings.M_SPEED) { mService.setDesiredSpeed(desiredPaceOrSpeed); } } } private void savePaceSetting() { mDanceStepAppSettings.savePaceOrSpeedSetting(mMaintain, mDesiredPaceOrSpeed); } private StepService mService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = ((StepService.StepBinder) service).getService(); mService.registerCallback(mCallback); mService.reloadSettings(); } public void onServiceDisconnected(ComponentName className) { mService = null; } }; private void startStepService() { if (!mIsRunning) { Log.i(TAG, "[SERVICE] Start"); mIsRunning = true; startService(new Intent(DanceStepApp.this, StepService.class)); } } private void bindStepService() { Log.i(TAG, "[SERVICE] Bind"); bindService(new Intent(DanceStepApp.this, StepService.class), mConnection, Context.BIND_AUTO_CREATE + Context.BIND_DEBUG_UNBIND); } private void unbindStepService() { Log.i(TAG, "[SERVICE] Unbind"); unbindService(mConnection); } private void stopStepService() { Log.i(TAG, "[SERVICE] Stop"); if (mService != null) { Log.i(TAG, "[SERVICE] stopService"); stopService(new Intent(DanceStepApp.this, StepService.class)); } mIsRunning = false; } private void resetValues(boolean updateDisplay) { if (mService != null && mIsRunning) { mService.resetValues(); } else { mStepValueView.setText("0"); SharedPreferences state = getSharedPreferences("state", 0); SharedPreferences.Editor stateEditor = state.edit(); if (updateDisplay) { stateEditor.putInt("steps", 0); stateEditor.putInt("pace", 0); stateEditor.putFloat("distance", 0); stateEditor.putFloat("speed", 0); stateEditor.putFloat("calories", 0); stateEditor.commit(); } } } private static final int MENU_SETTINGS = 8; private static final int MENU_QUIT = 9; private static final int MENU_PAUSE = 1; private static final int MENU_RESUME = 2; private static final int MENU_RESET = 3; /* Creates the menu items */ public boolean onPrepareOptionsMenu(Menu menu) { menu.clear(); if (mIsRunning) { menu.add(0, MENU_PAUSE, 0, R.string.pause).setIcon(android.R.drawable.ic_media_pause).setShortcut('1', 'p'); } else { menu.add(0, MENU_RESUME, 0, R.string.resume).setIcon(android.R.drawable.ic_media_play).setShortcut('1', 'p'); } menu.add(0, MENU_RESET, 0, R.string.reset).setIcon(android.R.drawable.ic_menu_close_clear_cancel) .setShortcut('2', 'r'); menu.add(0, MENU_SETTINGS, 0, R.string.settings).setIcon(android.R.drawable.ic_menu_preferences) .setShortcut('8', 's').setIntent(new Intent(this, Settings.class)); menu.add(0, MENU_QUIT, 0, R.string.quit).setIcon(android.R.drawable.ic_lock_power_off).setShortcut('9', 'q'); return true; } /* Handles item selections */ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_PAUSE: unbindStepService(); stopStepService(); return true; case MENU_RESUME: startStepService(); bindStepService(); return true; case MENU_RESET: resetValues(true); return true; case MENU_QUIT: //resetValues(false); unbindStepService(); stopStepService(); mQuitting = true; finish(); return true; } return false; } // TODO: unite all into 1 type of message private StepService.ICallback mCallback = new StepService.ICallback() { public void stepsChanged(int value) { mHandler.sendMessage(mHandler.obtainMessage(STEPS_MSG, value, 0)); } public void paceChanged(int value) { mHandler.sendMessage(mHandler.obtainMessage(PACE_MSG, value, 0)); } public void distanceChanged(float value) { mHandler.sendMessage(mHandler.obtainMessage(DISTANCE_MSG, (int) (value * 1000), 0)); } public void speedChanged(float value) { mHandler.sendMessage(mHandler.obtainMessage(SPEED_MSG, (int) (value * 1000), 0)); } public void caloriesChanged(float value) { mHandler.sendMessage(mHandler.obtainMessage(CALORIES_MSG, (int) (value), 0)); } }; public void postHTTP(String id, String name, int steps, float km) { // Create a new HttpClient and Post Header HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://www.setup.nl/tools/dancestep_app/post/write.php"); try { // Add your data List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4); nameValuePairs.add(new BasicNameValuePair("id", id)); nameValuePairs.add(new BasicNameValuePair("name", name)); nameValuePairs.add(new BasicNameValuePair("steps", Integer.toString(steps))); nameValuePairs.add(new BasicNameValuePair("km", Float.toString(km))); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // Execute HTTP Post Request httpclient.execute(httppost); } catch (ClientProtocolException e) { // TODO Auto-generated catch block } catch (IOException e) { // TODO Auto-generated catch block } }; private static final int STEPS_MSG = 1; private static final int PACE_MSG = 2; private static final int DISTANCE_MSG = 3; private static final int SPEED_MSG = 4; private static final int CALORIES_MSG = 5; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case STEPS_MSG: mStepValue = (int) msg.arg1; if ((mStepValue % 2) == 0) { mStepValueView.setText("" + mStepValue); mDanceLeftImage.setVisibility(View.VISIBLE); mDanceRightImage.setVisibility(View.INVISIBLE); } else { mStepValueView.setText("" + mStepValue); mDanceLeftImage.setVisibility(View.INVISIBLE); mDanceRightImage.setVisibility(View.VISIBLE); } break; case PACE_MSG: mPaceValue = msg.arg1; if (mPaceValue <= 0) { // mPaceValueView.setText("0"); } else { // mPaceValueView.setText("" + (int)mPaceValue); } break; case DISTANCE_MSG: mDistanceValue = ((int) msg.arg1) / 1000f; if (mDistanceValue <= 0) { // mDistanceValueView.setText("0"); } else { // mDistanceValueView.setText( // ("" + (mDistanceValue + 0.000001f)).substring(0, 5) // ); } break; case SPEED_MSG: mSpeedValue = ((int) msg.arg1) / 1000f; if (mSpeedValue <= 0) { // mSpeedValueView.setText("0"); } else { // mSpeedValueView.setText( // ("" + (mSpeedValue + 0.000001f)).substring(0, 4) // ); } break; case CALORIES_MSG: mCaloriesValue = msg.arg1; if (mCaloriesValue <= 0) { // mCaloriesValueView.setText("0"); } else { // mCaloriesValueView.setText("" + (int)mCaloriesValue); } break; default: super.handleMessage(msg); } } }; }