计步器

1.CaloriesNotifier.java

package com.tdc.jibuqi;

import java.util.Locale;


/**
 * Calculates and displays the approximate calories.  
 */
public class CaloriesNotifier implements StepListener, SpeakingTimer.Listener {

    public interface Listener {
        public void valueChanged(float value);
        public void passValue();
    }
    private Listener mListener;
    
    private static double METRIC_RUNNING_FACTOR = 1.02784823;
    private static double IMPERIAL_RUNNING_FACTOR = 0.75031498;

    private static double METRIC_WALKING_FACTOR = 0.708;
    private static double IMPERIAL_WALKING_FACTOR = 0.517;

    private double mCalories = 0;
    
    PedometerSettings mSettings;
    Utils mUtils;
    
    boolean mIsMetric;
    boolean mIsRunning;
    float mStepLength;
    float mBodyWeight;

    public CaloriesNotifier(Listener listener, PedometerSettings settings, Utils utils) {
        mListener = listener;
        mUtils = utils;
        mSettings = settings;
        reloadSettings();
    }
    public void setCalories(float calories) {
        mCalories = calories;
        notifyListener();
    }
    public void reloadSettings() {
        mIsMetric = mSettings.isMetric();
        mIsRunning = mSettings.isRunning();
        mStepLength = mSettings.getStepLength();
        mBodyWeight = mSettings.getBodyWeight();
        notifyListener();
    }
    public void resetValues() {
        mCalories = 0;
    }
    
    public void isMetric(boolean isMetric) {
        mIsMetric = isMetric;
    }
    public void setStepLength(float stepLength) {
        mStepLength = stepLength;
    }
    
    public void onStep() {
        
        if (mIsMetric) {
            mCalories += 
                (mBodyWeight * (mIsRunning ? METRIC_RUNNING_FACTOR : METRIC_WALKING_FACTOR))
                // Distance:
                * mStepLength // centimeters
                / 100000.0; // centimeters/kilometer
        }
        else {
            mCalories += 
                (mBodyWeight * (mIsRunning ? IMPERIAL_RUNNING_FACTOR : IMPERIAL_WALKING_FACTOR))
                // Distance:
                * mStepLength // inches
                / 63360.0; // inches/mile            
        }
        
        notifyListener();
    }
    
    private void notifyListener() {
        mListener.valueChanged((float)mCalories);
    }
    
    public void passValue() {
        
    }
    
    public void speak() {
        if (mSettings.shouldTellCalories()) {
            if (mCalories > 0) {
            	if(Locale.getDefault().getLanguage().equals("zh")&&
         				Locale.getDefault().getCountry().equals("CN")){
            		 mUtils.say("当前消耗" + (int)mCalories + "卡路里");
         		}else{
         			 mUtils.say("" + (int)mCalories + " calories burned");
         		}
               
            	
            }
        }
        
    }
    

}
2.DistanceNotifier.java


package com.tdc.jibuqi;

import java.util.Locale;


/**
 * Calculates and displays the distance walked.  
 * @author Levente Bagi
 */
public class DistanceNotifier implements StepListener, SpeakingTimer.Listener {

    public interface Listener {
        public void valueChanged(float value);
        public void passValue();
    }
    private Listener mListener;
    
    float mDistance = 0;
    
    PedometerSettings mSettings;
    Utils mUtils;
    
    boolean mIsMetric;
    float mStepLength;

    public DistanceNotifier(Listener listener, PedometerSettings settings, Utils utils) {
        mListener = listener;
        mUtils = utils;
        mSettings = settings;
        reloadSettings();
    }
    public void setDistance(float distance) {
        mDistance = distance;
        notifyListener();
    }
    
    public void reloadSettings() {
        mIsMetric = mSettings.isMetric();
        mStepLength = mSettings.getStepLength();
        notifyListener();
    }
    
    public void onStep() {
        //判断步长的距离
        if (mIsMetric) {//厘米转换为千米
            mDistance += (float)(// kilometers
                mStepLength // centimeters
                / 100000.0); // centimeters/kilometer
        }
        else {//英寸转换为英里
            mDistance += (float)(// miles
                mStepLength // inches
                / 63360.0); // inches/mile
        }
        
        notifyListener();
    }
    
    private void notifyListener() {
        mListener.valueChanged(mDistance);
    }
    
    public void passValue() {
        // Callback of StepListener - Not implemented
    }

    public void speak() {
        if (mSettings.shouldTellDistance()) {
            if (mDistance >= .001f) {
            	if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
            		mUtils.say("当前距离"+("" + (mDistance + 0.000001f)).substring(0, 5) + (mIsMetric ? "公里," : "英里,"));
         		}else{
         			mUtils.say(("" + (mDistance + 0.000001f)).substring(0, 5) + (mIsMetric ? " kilometers" : " miles"));
         		}
                
               
            }
        }
    }
    

}
3.PaceNotifier.java

package com.tdc.jibuqi;

import java.util.ArrayList;
import java.util.Locale;


public class PaceNotifier implements StepListener, SpeakingTimer.Listener {

    public interface Listener {
        public void paceChanged(int value);
        public void passValue();
    }
    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
    
    int mCounter = 0;
    
    private long mLastStepTime = 0;
    private long[] mLastStepDeltas = {-1, -1, -1, -1};
    private int mLastStepDeltasIndex = 0;
    private long mPace = 0;
    
    PedometerSettings mSettings;
    Utils mUtils;

    /** Desired pace, adjusted by the user */
    int mDesiredPace;

    /** Should we speak? */
    boolean mShouldTellFasterslower;

    /** When did the TTS speak last time */
    private long mSpokenAt = 0;

    public PaceNotifier(PedometerSettings settings, Utils utils) {
        mUtils = utils;
        mSettings = settings;
        mDesiredPace = mSettings.getDesiredPace();
        reloadSettings();
    }
    public void setPace(int pace) {
        mPace = pace;
        int avg = (int)(60*1000.0 / mPace);
        for (int i = 0; i < mLastStepDeltas.length; i++) {
            mLastStepDeltas[i] = avg;
        }
        notifyListener();
    }
    public void reloadSettings() {
        mShouldTellFasterslower = 
            mSettings.shouldTellFasterslower()
            && mSettings.getMaintainOption() == PedometerSettings.M_PACE;
        notifyListener();
    }
    
    public void addListener(Listener l) {
        mListeners.add(l);
    }

    public void setDesiredPace(int desiredPace) {
        mDesiredPace = desiredPace;
    }

    public void onStep() {
        long thisStepTime = System.currentTimeMillis();
        mCounter ++;
        
        // Calculate pace based on last x steps
        if (mLastStepTime > 0) {
            long delta = thisStepTime - mLastStepTime;
            
            mLastStepDeltas[mLastStepDeltasIndex] = delta;
            mLastStepDeltasIndex = (mLastStepDeltasIndex + 1) % mLastStepDeltas.length;
            
            long sum = 0;
            boolean isMeaningfull = true;
            for (int i = 0; i < mLastStepDeltas.length; i++) {
                if (mLastStepDeltas[i] < 0) {
                    isMeaningfull = false;
                    break;
                }
                sum += mLastStepDeltas[i];
            }
            if (isMeaningfull && sum > 0) {
                long avg = sum / mLastStepDeltas.length;
                mPace = 60*1000 / avg;
               
                // TODO: remove duplication. This also exists in SpeedNotifier
                if (mShouldTellFasterslower && mUtils.isSpeakingEnabled()) {
                    if (thisStepTime - mSpokenAt > 3000 && !mUtils.isSpeakingNow()) {
                        float little = 0.10f;
                        float normal = 0.30f;
                        float much = 0.50f;
                        boolean spoken = true;
                        if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
                        	if (mPace < mDesiredPace * (1 - much)) {
	                            mUtils.say("您的步调很慢!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + much)) {
	                            mUtils.say("您的步调很快!");
	                        }
	                        else if (mPace < mDesiredPace * (1 - normal)) {
	                            mUtils.say("您的步调有点慢!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + normal)) {
	                            mUtils.say("您的步调有点快!");
	                        }
	                        else if (mPace < mDesiredPace * (1 - little)) {
	                            mUtils.say("您的步调慢!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + little)) {
	                            mUtils.say("您的步调快!");
	                        }else {
	                            spoken = false;
	                        }
                 		}else{
	                        if (mPace < mDesiredPace * (1 - much)) {
	                            mUtils.say("much faster!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + much)) {
	                            mUtils.say("much slower!");
	                        }
	                        else if (mPace < mDesiredPace * (1 - normal)) {
	                            mUtils.say("faster!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + normal)) {
	                            mUtils.say("slower!");
	                        }
	                        else if (mPace < mDesiredPace * (1 - little)) {
	                            mUtils.say("a little faster!");
	                        }
	                        else if (mPace > mDesiredPace * (1 + little)) {
	                            mUtils.say("a little slower!");
	                        }else {
	                            spoken = false;
	                        }
                 		}
                        if (spoken) {
                            mSpokenAt = thisStepTime;
                        }
                    }
                }
            }
            else {
                mPace = -1;
            }
        }
        mLastStepTime = thisStepTime;
        notifyListener();
    }
    
    private void notifyListener() {
        for (Listener listener : mListeners) {
            listener.paceChanged((int)mPace);
        }
    }
    
    public void passValue() {
        // Not used
    }

    //-----------------------------------------------------
    // Speaking
    
    public void speak() {
        if (mSettings.shouldTellPace()) {
            if (mPace > 0) {
            	if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
            		mUtils.say("当前步速"+mPace + "步每分钟,");
            	}else{
            		mUtils.say(mPace + " steps per minute");
            	}
                
            }
        }
    }
    

}
4.Pedometer.java

package com.tdc.jibuqi;


import com.tdc.jibuqi.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.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.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;


//主Activity
public class Pedometer extends Activity {
	private static final String TAG = "Pedometer";
    private SharedPreferences mSettings;
    private PedometerSettings mPedometerSettings;
    private Utils mUtils;
    
    private TextView mStepValueView;
    private TextView mPaceValueView;
    private TextView mDistanceValueView;
    private TextView mSpeedValueView;
    private TextView mCaloriesValueView;
    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();//获取Utils这个类
    }
    
    @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);
        mPedometerSettings = new PedometerSettings(mSettings);
        
        mUtils.setSpeak(mSettings.getBoolean("speak", false));
        
        // Read from preferences if the service was running on the last onPause
        mIsRunning = mPedometerSettings.isServiceRunning();
        
        // Start the service if this is considered to be an application start (last onPause was long ago)
        if (!mIsRunning && mPedometerSettings.isNewStart()) {
            startStepService();
            bindStepService();
        }
        else if (mIsRunning) {
            bindStepService();
        }
        
        mPedometerSettings.clearServiceRunning();

        mStepValueView     = (TextView) findViewById(R.id.step_value);
        mPaceValueView     = (TextView) findViewById(R.id.pace_value);
        mDistanceValueView = (TextView) findViewById(R.id.distance_value);
        mSpeedValueView    = (TextView) findViewById(R.id.speed_value);
        mCaloriesValueView = (TextView) findViewById(R.id.calories_value);
        mDesiredPaceView   = (TextView) findViewById(R.id.desired_pace_value);

        mIsMetric = mPedometerSettings.isMetric();
        ((TextView) findViewById(R.id.distance_units)).setText(getString(
                mIsMetric
                ? R.string.kilometers
                : R.string.miles
        ));
        ((TextView) findViewById(R.id.speed_units)).setText(getString(
                mIsMetric
                ? R.string.kilometers_per_hour
                : R.string.miles_per_hour
        ));
        
        mMaintain = mPedometerSettings.getMaintainOption();
        ((LinearLayout) this.findViewById(R.id.desired_pace_control)).setVisibility(
                mMaintain != PedometerSettings.M_NONE
                ? View.VISIBLE
                : View.GONE
            );
        if (mMaintain == PedometerSettings.M_PACE) {
            mMaintainInc = 5f;
            mDesiredPaceOrSpeed = (float)mPedometerSettings.getDesiredPace();
        }else if (mMaintain == PedometerSettings.M_SPEED) {
            mDesiredPaceOrSpeed = mPedometerSettings.getDesiredSpeed();
            mMaintainInc = 0.1f;
        }
        Button button1 = (Button) findViewById(R.id.button_desired_pace_lower);
        button1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mDesiredPaceOrSpeed -= mMaintainInc;
                mDesiredPaceOrSpeed = Math.round(mDesiredPaceOrSpeed * 10) / 10f;
                displayDesiredPaceOrSpeed();
                setDesiredPaceOrSpeed(mDesiredPaceOrSpeed);
            }
        });
        Button button2 = (Button) findViewById(R.id.button_desired_pace_raise);
        button2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mDesiredPaceOrSpeed += mMaintainInc;
                mDesiredPaceOrSpeed = Math.round(mDesiredPaceOrSpeed * 10) / 10f;
                displayDesiredPaceOrSpeed();
                setDesiredPaceOrSpeed(mDesiredPaceOrSpeed);
            }
        });
        if (mMaintain != PedometerSettings.M_NONE) {
            ((TextView) findViewById(R.id.desired_pace_label)).setText(
                    mMaintain == PedometerSettings.M_PACE
                    ? R.string.desired_pace
                    : R.string.desired_speed
            );
        }
        
        
        displayDesiredPaceOrSpeed();
    }
    
    private void displayDesiredPaceOrSpeed() {
        if (mMaintain == PedometerSettings.M_PACE) {
            mDesiredPaceView.setText("" + (int)mDesiredPaceOrSpeed);
        }
        else {
            mDesiredPaceView.setText("" + mDesiredPaceOrSpeed);
        }
    }
    
    @Override
    protected void onPause() {
        Log.i(TAG, "[ACTIVITY] onPause");
        if (mIsRunning) {
            unbindStepService();
        }
        if (mQuitting) {
            mPedometerSettings.saveServiceRunningWithNullTimestamp(mIsRunning);
        }
        else {
            mPedometerSettings.saveServiceRunningWithTimestamp(mIsRunning);
        }

        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 == PedometerSettings.M_PACE) {
                mService.setDesiredPace((int)desiredPaceOrSpeed);
            }
            else
            if (mMaintain == PedometerSettings.M_SPEED) {
                mService.setDesiredSpeed(desiredPaceOrSpeed);
            }
        }
    }
    
    private void savePaceSetting() {
        mPedometerSettings.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(Pedometer.this,
                    StepService.class));
        }
    }
    
    private void bindStepService() {
        Log.i(TAG, "[SERVICE] Bind");
        bindService(new Intent(Pedometer.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(Pedometer.this,
                  StepService.class));
        }
        mIsRunning = false;
    }
    
    private void resetValues(boolean updateDisplay) {
        if (mService != null && mIsRunning) {
            mService.resetValues();                    
        }
        else {
            mStepValueView.setText("0");
            mPaceValueView.setText("0");
            mDistanceValueView.setText("0");
            mSpeedValueView.setText("0");
            mCaloriesValueView.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 */
    /*创建menu*/
    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));
        }
    };
    
    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;
                    mStepValueView.setText("" + mStepValue);
                    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);
            }
        }
        
    };
    

}

5.PedometerSettings.java


package com.tdc.jibuqi;

import android.content.SharedPreferences;


public class PedometerSettings {

    SharedPreferences mSettings;
    
    public static int M_NONE = 1;
    public static int M_PACE = 2;
    public static int M_SPEED = 3;
    
    public PedometerSettings(SharedPreferences settings) {
        mSettings = settings;
    }
    
    public boolean isMetric() {//判断距离的单位
        return mSettings.getString("units", "metric").equals("metric");//是千米/还是英寸
    }
    
    public float getStepLength() {//获取步长
        try {
            return Float.valueOf(mSettings.getString("step_length", "70").trim());
        }
        catch (NumberFormatException e) {
            // TODO: reset value, & notify user somehow
            return 0f;
        }
    }
    
    public float getBodyWeight() {//获取体重
        try {
            return Float.valueOf(mSettings.getString("body_weight", "50").trim());
        }
        catch (NumberFormatException e) {
            // TODO: reset value, & notify user somehow
            return 0f;
        }
    }

    public boolean isRunning() {//获取运动类型
        return mSettings.getString("exercise_type", "running").equals("running");
    }
    
    //是否设置目标步伐或者速度
    public int getMaintainOption() {
        String p = mSettings.getString("maintain", "none");
        return 
            p.equals("none") ? M_NONE : (
            p.equals("pace") ? M_PACE : (
            p.equals("speed") ? M_SPEED : ( 
            0)));
    }
    
    //-------------------------------------------------------------------
    // Desired pace & speed: 
    // these can not be set in the preference activity, only on the main
    // screen if "maintain" is set to "pace" or "speed" 
    
    public int getDesiredPace() {
        return mSettings.getInt("desired_pace", 180); // steps/minute
    }
    public float getDesiredSpeed() {
        return mSettings.getFloat("desired_speed", 4f); // km/h or mph
    }
    public void savePaceOrSpeedSetting(int maintain, float desiredPaceOrSpeed) {
        SharedPreferences.Editor editor = mSettings.edit();
        if (maintain == M_PACE) {
            editor.putInt("desired_pace", (int)desiredPaceOrSpeed);
        }
        else
        if (maintain == M_SPEED) {
            editor.putFloat("desired_speed", desiredPaceOrSpeed);
        }
        editor.commit();
    }
    
    //-------------------------------------------------------------------
    // Speaking:
    
    public boolean shouldSpeak() {
        return mSettings.getBoolean("speak", false);
    }
    public float getSpeakingInterval() {
        try {
            return Float.valueOf(mSettings.getString("speaking_interval", "1"));
        }
        catch (NumberFormatException e) {
            // This could not happen as the value is selected from a list.
            return 1;
        }
    }
    public boolean shouldTellSteps() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_steps", false);
    }
    public boolean shouldTellPace() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_pace", false);
    }
    public boolean shouldTellDistance() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_distance", false);
    }
    public boolean shouldTellSpeed() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_speed", false);
    }
    public boolean shouldTellCalories() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_calories", false);
    }
    public boolean shouldTellFasterslower() {
        return mSettings.getBoolean("speak", false) 
        && mSettings.getBoolean("tell_fasterslower", false);
    }
    
    public boolean wakeAggressively() {
        return mSettings.getString("operation_level", "run_in_background").equals("wake_up");
    }
    public boolean keepScreenOn() {
        return mSettings.getString("operation_level", "run_in_background").equals("keep_screen_on");
    }
    
    //
    // Internal
    
    public void saveServiceRunningWithTimestamp(boolean running) {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putBoolean("service_running", running);
        editor.putLong("last_seen", Utils.currentTimeInMillis());
        editor.commit();
    }
    
    public void saveServiceRunningWithNullTimestamp(boolean running) {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putBoolean("service_running", running);
        editor.putLong("last_seen", 0);
        editor.commit();
    }

    public void clearServiceRunning() {
        SharedPreferences.Editor editor = mSettings.edit();
        editor.putBoolean("service_running", false);
        editor.putLong("last_seen", 0);
        editor.commit();
    }

    public boolean isServiceRunning() {
        return mSettings.getBoolean("service_running", false);
    }
    
    public boolean isNewStart() {
        // activity last paused more than 10 minutes ago
        return mSettings.getLong("last_seen", 0) < Utils.currentTimeInMillis() - 1000*60*10;
    }

}

6.Settings.java

package com.tdc.jibuqi;

import com.tdc.jibuqi.R;
import android.os.Bundle;
import android.preference.PreferenceActivity;

public class Settings extends PreferenceActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        addPreferencesFromResource(R.xml.preferences);
    }
}

7.SpeakingTimer

package com.tdc.jibuqi;

import java.util.ArrayList;

public class SpeakingTimer implements StepListener {

    PedometerSettings mSettings;
    Utils mUtils;
    boolean mShouldSpeak;
    float mInterval;
    long mLastSpeakTime;
    
    public SpeakingTimer(PedometerSettings settings, Utils utils) {
        mLastSpeakTime = System.currentTimeMillis();
        mSettings = settings;
        mUtils = utils;
        reloadSettings();
    }
    public void reloadSettings() {
        mShouldSpeak = mSettings.shouldSpeak();
        mInterval = mSettings.getSpeakingInterval();
    }
    
    public void onStep() {
        long now = System.currentTimeMillis();
        long delta = now - mLastSpeakTime;
        
        if (delta / 60000.0 >= mInterval) {
            mLastSpeakTime = now;
            notifyListeners();
        }
    }
    
    public void passValue() {
        // not used
    }

    
    //-----------------------------------------------------
    // Listener
    
    public interface Listener {
        public void speak();
    }
    private ArrayList<Listener> mListeners = new ArrayList<Listener>();

    public void addListener(Listener l) {
        mListeners.add(l);
    }
    public void notifyListeners() {
        mUtils.ding();
        for (Listener listener : mListeners) {
            listener.speak();
        }
    }

    //-----------------------------------------------------
    // Speaking
    
    public boolean isSpeaking() {
        return mUtils.isSpeakingNow();
    }
}

8.SpeedNotifier.java

package com.tdc.jibuqi;

import java.util.Locale;



public class SpeedNotifier implements PaceNotifier.Listener, SpeakingTimer.Listener {

    public interface Listener {
        public void valueChanged(float value);
        public void passValue();
    }
    private Listener mListener;
    
    int mCounter = 0;
    float mSpeed = 0;
    
    boolean mIsMetric;
    float mStepLength;

    PedometerSettings mSettings;
    Utils mUtils;

    /** Desired speed, adjusted by the user */
    float mDesiredSpeed;
    
    /** Should we speak? */
    boolean mShouldTellFasterslower;
    boolean mShouldTellSpeed;
    
    /** When did the TTS speak last time */
    private long mSpokenAt = 0;
    
    public SpeedNotifier(Listener listener, PedometerSettings settings, Utils utils) {
        mListener = listener;
        mUtils = utils;
        mSettings = settings;
        mDesiredSpeed = mSettings.getDesiredSpeed();
        reloadSettings();
    }
    public void setSpeed(float speed) {
        mSpeed = speed;
        notifyListener();
    }
    public void reloadSettings() {
        mIsMetric = mSettings.isMetric();
        mStepLength = mSettings.getStepLength();
        mShouldTellSpeed = mSettings.shouldTellSpeed();
        mShouldTellFasterslower = 
            mSettings.shouldTellFasterslower()
            && mSettings.getMaintainOption() == PedometerSettings.M_SPEED;
        notifyListener();
    }
    public void setDesiredSpeed(float desiredSpeed) {
        mDesiredSpeed = desiredSpeed;
    }
    
    private void notifyListener() {
        mListener.valueChanged(mSpeed);
    }
    
    public void paceChanged(int value) {
        if (mIsMetric) {
            mSpeed = // kilometers / hour
                value * mStepLength // centimeters / minute
                / 100000f * 60f; // centimeters/kilometer
        }
        else {
            mSpeed = // miles / hour
                value * mStepLength // inches / minute
                / 63360f * 60f; // inches/mile 
        }
        tellFasterSlower();
        notifyListener();
    }
    
    /**
     * Say slower/faster, if needed.
     */
    private void tellFasterSlower() {
        if (mShouldTellFasterslower && mUtils.isSpeakingEnabled()) {
            long now = System.currentTimeMillis();
            if (now - mSpokenAt > 3000 && !mUtils.isSpeakingNow()) {
                float little = 0.10f;
                float normal = 0.30f;
                float much = 0.50f;
                
                boolean spoken = true;
                if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
                	if (mSpeed < mDesiredSpeed * (1 - much)) {
                        mUtils.say("您的速度离您的目标值还很远!");
                    }
                    else if (mSpeed > mDesiredSpeed * (1 + much)) {
                        mUtils.say("您的速度远远超过了目标速度!");
                    }
                    else
                    if (mSpeed < mDesiredSpeed * (1 - normal)) {
                        mUtils.say("您的速度离您的目标值还有点远!");
                    }
                    else
                    if (mSpeed > mDesiredSpeed * (1 + normal)) {
                        mUtils.say("您的速度已经超过了目标速度");
                    }
                    else
                    if (mSpeed < mDesiredSpeed * (1 - little)) {
                        mUtils.say("您的速度离您的目标值还差一点点!");
                    }
                    else
                    if (mSpeed > mDesiredSpeed * (1 + little)) {
                        mUtils.say("您的速度刚刚超过了目标速度!");
                    }
                    else {
                        spoken = false;
                    }
                }else{
                	if (mSpeed < mDesiredSpeed * (1 - much)) {
                        mUtils.say("much faster!");
                    }
                    else
                    if (mSpeed > mDesiredSpeed * (1 + much)) {
                        mUtils.say("much slower!");
                    }
                    else
                    if (mSpeed < mDesiredSpeed * (1 - normal)) {
                        mUtils.say("faster!");
                    }
                    else
                    if (mSpeed > mDesiredSpeed * (1 + normal)) {
                        mUtils.say("slower!");
                    }
                    else
                    if (mSpeed < mDesiredSpeed * (1 - little)) {
                        mUtils.say("a little faster!");
                    }
                    else
                    if (mSpeed > mDesiredSpeed * (1 + little)) {
                        mUtils.say("a little slower!");
                    }
                    else {
                        spoken = false;
                    }
                }
                
                
                if (spoken) {
                    mSpokenAt = now;
                }
            }
        }
    }
    
    public void passValue() {
        // Not used
    }

    public void speak() {
        if (mSettings.shouldTellSpeed()) {
            if (mSpeed >= .01f) {
            	 if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
            		 mUtils.say("当前速度"+("" + (mSpeed + 0.000001f)).substring(0, 4) + (mIsMetric ? "公里每小时" : "英里每小时"));
            	 }else{
            		 mUtils.say(("" + (mSpeed + 0.000001f)).substring(0, 4) + (mIsMetric ? " kilometers per hour" : " miles per hour"));
            	 }
                
            }
        }
        
    }

}

9.StepBuzzer

package com.tdc.jibuqi;

import android.content.Context;
import android.os.Vibrator;


public class StepBuzzer implements StepListener {
    
    private Context mContext;
    private Vibrator mVibrator;
    
    public StepBuzzer(Context context) {
        mContext = context;
        mVibrator = (Vibrator)mContext.getSystemService(Context.VIBRATOR_SERVICE);
    }
    
    public void onStep() {
        buzz();
    }
    
    public void passValue() {
        
    }
    
    private void buzz() {
        mVibrator.vibrate(50);
    }
}
10.StepDetector

package com.tdc.jibuqi;

import java.util.ArrayList;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;


public class StepDetector implements SensorEventListener
{
    private final static String TAG = "StepDetector";
    private float   mLimit = 10;
    private float   mLastValues[] = new float[3*2];
    private float   mScale[] = new float[2];
    private float   mYOffset;

    private float   mLastDirections[] = new float[3*2];
    private float   mLastExtremes[][] = { new float[3*2], new float[3*2] };
    private float   mLastDiff[] = new float[3*2];
    private int     mLastMatch = -1;
    private long start,end;
    
    private ArrayList<StepListener> mStepListeners = new ArrayList<StepListener>();
    
    public StepDetector() {
        int h = 480; // TODO: remove this constant
        mYOffset = h * 0.5f;
        mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
        mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
    }
    
    public void setSensitivity(float sensitivity) {
        mLimit = sensitivity; // 1.97  2.96  4.44  6.66  10.00  15.00  22.50  33.75  50.62
    }
    
    public void addStepListener(StepListener sl) {
        mStepListeners.add(sl);
    }
    
    //public void onSensorChanged(int sensor, float[] values) {
    public void onSensorChanged(SensorEvent event) {
        Sensor sensor = event.sensor; 
        synchronized (this) {
            if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
            }
            else {
                int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
                if (j == 1) {
                    float vSum = 0;
                    //System.out.println("x="+event.values[0]+",y="+event.values[1]+",z="+event.values[2]);
                    for (int i=0 ; i<3 ; i++) {
                        final float v = mYOffset + event.values[i] * mScale[j];
                        vSum += v;
                    }
                    int k = 0;
                    float v = vSum / 3;
                    
                    float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
                    //System.out.println("direction="+direction+",mLastValues[k]="+mLastValues[k]+", mLastDirections[k]="+mLastDirections[k]);
                    if (direction == - mLastDirections[k]) {
                        // Direction changed
                        int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
                        mLastExtremes[extType][k] = mLastValues[k];
                        float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
                        //System.out.println("mLimit="+ mLimit+",diff="+diff);
                        if (diff > mLimit) {
                            
                            boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
                            boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
                            boolean isNotContra = (mLastMatch != 1 - extType);
                            
                            if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
                            	end=System.currentTimeMillis();
                                //Log.i(TAG, "step");
                                if(end-start>500){
	                                for (StepListener stepListener : mStepListeners) {
	                                    stepListener.onStep();
	                                }
	                                start=end;
	                                mLastMatch = extType;
                                }
                            }
                            else {
                                mLastMatch = -1;
                            }
                        }
                        mLastDiff[k] = diff;
                    }
                    mLastDirections[k] = direction;
                    mLastValues[k] = v;
                }
            }
        }
    }
    
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub
    }

}

11.StepDisplayer 

package com.tdc.jibuqi;

import java.util.ArrayList;
import java.util.Locale;


public class StepDisplayer implements StepListener, SpeakingTimer.Listener {

    private int mCount = 0;
    PedometerSettings mSettings;
    Utils mUtils;

    public StepDisplayer(PedometerSettings settings, Utils utils) {
        mUtils = utils;
        mSettings = settings;
        notifyListener();
    }
    public void setUtils(Utils utils) {
        mUtils = utils;
    }

    public void setSteps(int steps) {
        mCount = steps;
        notifyListener();
    }
    public void onStep() {
        mCount ++;
        notifyListener();
    }
    public void reloadSettings() {
        notifyListener();
    }
    public void passValue() {
    }
    
    

    //-----------------------------------------------------
    // Listener
    
    public interface Listener {
        public void stepsChanged(int value);
        public void passValue();
    }
    private ArrayList<Listener> mListeners = new ArrayList<Listener>();

    public void addListener(Listener l) {
        mListeners.add(l);
    }
    public void notifyListener() {
        for (Listener listener : mListeners) {
            listener.stepsChanged((int)mCount);
        }
    }
    
    //-----------------------------------------------------
    // Speaking
    
    public void speak() {
        if (mSettings.shouldTellSteps()) { 
            if (mCount > 0) {
            	 if(Locale.getDefault().getLanguage().equals("zh")&&Locale.getDefault().getCountry().equals("CN")){
            		 mUtils.say("您走了" + mCount + "步");
            	 }else{
            		 mUtils.say("" + mCount + " steps");
            	 }
               
            }
        }
    }
    
    
}

12.StepListener

package com.tdc.jibuqi;


public interface StepListener {
    public void onStep();
    public void passValue();
}

13.StepService

package com.tdc.jibuqi;

import com.tdc.jibuqi.R;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

public class StepService extends Service {
	private static final String TAG = "name.bagi.levente.pedometer.StepService";
    private SharedPreferences mSettings;
    private PedometerSettings mPedometerSettings;
    private SharedPreferences mState;
    private SharedPreferences.Editor mStateEditor;
    private Utils mUtils;
    private SensorManager mSensorManager;
    private Sensor mSensor;
    private StepDetector mStepDetector;
    // private StepBuzzer mStepBuzzer; // used for debugging
    private StepDisplayer mStepDisplayer;
    private PaceNotifier mPaceNotifier;
    private DistanceNotifier mDistanceNotifier;
    private SpeedNotifier mSpeedNotifier;
    private CaloriesNotifier mCaloriesNotifier;
    private SpeakingTimer mSpeakingTimer;
    
    private PowerManager.WakeLock wakeLock;
    private NotificationManager mNM;

    private int mSteps;
    private int mPace;
    private float mDistance;
    private float mSpeed;
    private float mCalories;
    
    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class StepBinder extends Binder {
        StepService getService() {
            return StepService.this;
        }
    }
    
    @Override
    public void onCreate() {
        Log.i(TAG, "[SERVICE] onCreate");
        super.onCreate();
        
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        showNotification();
        
        // Load settings
        mSettings = PreferenceManager.getDefaultSharedPreferences(this);
        mPedometerSettings = new PedometerSettings(mSettings);
        mState = getSharedPreferences("state", 0);

        mUtils = Utils.getInstance();
        mUtils.setService(this);
        mUtils.initTTS();

        acquireWakeLock();
        
        // Start detecting
        mStepDetector = new StepDetector();
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        registerDetector();

        // Register our receiver for the ACTION_SCREEN_OFF action. This will make our receiver
        // code be called whenever the phone enters standby mode.
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mReceiver, filter);

        mStepDisplayer = new StepDisplayer(mPedometerSettings, mUtils);
        mStepDisplayer.setSteps(mSteps = mState.getInt("steps", 0));
        mStepDisplayer.addListener(mStepListener);
        mStepDetector.addStepListener(mStepDisplayer);

        mPaceNotifier     = new PaceNotifier(mPedometerSettings, mUtils);
        mPaceNotifier.setPace(mPace = mState.getInt("pace", 0));
        mPaceNotifier.addListener(mPaceListener);
        mStepDetector.addStepListener(mPaceNotifier);

        mDistanceNotifier = new DistanceNotifier(mDistanceListener, mPedometerSettings, mUtils);
        mDistanceNotifier.setDistance(mDistance = mState.getFloat("distance", 0));
        mStepDetector.addStepListener(mDistanceNotifier);
        
        mSpeedNotifier    = new SpeedNotifier(mSpeedListener,    mPedometerSettings, mUtils);
        mSpeedNotifier.setSpeed(mSpeed = mState.getFloat("speed", 0));
        mPaceNotifier.addListener(mSpeedNotifier);
        
        mCaloriesNotifier = new CaloriesNotifier(mCaloriesListener, mPedometerSettings, mUtils);
        mCaloriesNotifier.setCalories(mCalories = mState.getFloat("calories", 0));
        mStepDetector.addStepListener(mCaloriesNotifier);
        
        mSpeakingTimer = new SpeakingTimer(mPedometerSettings, mUtils);
        mSpeakingTimer.addListener(mStepDisplayer);
        mSpeakingTimer.addListener(mPaceNotifier);
        mSpeakingTimer.addListener(mDistanceNotifier);
        mSpeakingTimer.addListener(mSpeedNotifier);
        mSpeakingTimer.addListener(mCaloriesNotifier);
        mStepDetector.addStepListener(mSpeakingTimer);
        
        // Used when debugging:
        // mStepBuzzer = new StepBuzzer(this);
        // mStepDetector.addStepListener(mStepBuzzer);

        // Start voice
        reloadSettings();

        // Tell the user we started.
        Toast.makeText(this, getText(R.string.started), Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onStart(Intent intent, int startId) {
        Log.i(TAG, "[SERVICE] onStart");
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "[SERVICE] onDestroy");
        mUtils.shutdownTTS();

        // Unregister our receiver.
        unregisterReceiver(mReceiver);
        unregisterDetector();
        
        mStateEditor = mState.edit();
        mStateEditor.putInt("steps", mSteps);
        mStateEditor.putInt("pace", mPace);
        mStateEditor.putFloat("distance", mDistance);
        mStateEditor.putFloat("speed", mSpeed);
        mStateEditor.putFloat("calories", mCalories);
        mStateEditor.commit();
        
        mNM.cancel(R.string.app_name);
        	
        wakeLock.release();
        
        super.onDestroy();
        
        // Stop detecting
        mSensorManager.unregisterListener(mStepDetector);

        // Tell the user we stopped.
        Toast.makeText(this, getText(R.string.stopped), Toast.LENGTH_SHORT).show();
    }

    private void registerDetector() {
        mSensor = mSensorManager.getDefaultSensor(
            Sensor.TYPE_ACCELEROMETER /*| 
            Sensor.TYPE_MAGNETIC_FIELD | 
            Sensor.TYPE_ORIENTATION*/);
        mSensorManager.registerListener(mStepDetector,
            mSensor,
            SensorManager.SENSOR_DELAY_FASTEST);
    }

    private void unregisterDetector() {
        mSensorManager.unregisterListener(mStepDetector);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "[SERVICE] onBind");
        return mBinder;
    }

    /**
     * Receives messages from activity.
     */
    private final IBinder mBinder = new StepBinder();

    public interface ICallback {
        public void stepsChanged(int value);
        public void paceChanged(int value);
        public void distanceChanged(float value);
        public void speedChanged(float value);
        public void caloriesChanged(float value);
    }
    
    private ICallback mCallback;

    public void registerCallback(ICallback cb) {
        mCallback = cb;
        //mStepDisplayer.passValue();
        //mPaceListener.passValue();
    }
    
    private int mDesiredPace;
    private float mDesiredSpeed;
    
    /**
     * Called by activity to pass the desired pace value, 
     * whenever it is modified by the user.
     * @param desiredPace
     */
    public void setDesiredPace(int desiredPace) {
        mDesiredPace = desiredPace;
        if (mPaceNotifier != null) {
            mPaceNotifier.setDesiredPace(mDesiredPace);
        }
    }
    /**
     * Called by activity to pass the desired speed value, 
     * whenever it is modified by the user.
     * @param desiredSpeed
     */
    public void setDesiredSpeed(float desiredSpeed) {
        mDesiredSpeed = desiredSpeed;
        if (mSpeedNotifier != null) {
            mSpeedNotifier.setDesiredSpeed(mDesiredSpeed);
        }
    }
    
    public void reloadSettings() {
        mSettings = PreferenceManager.getDefaultSharedPreferences(this);
        
        if (mStepDetector != null) { 
            mStepDetector.setSensitivity(
                    Float.valueOf(mSettings.getString("sensitivity", "10"))
            );
        }
        
        if (mStepDisplayer    != null) mStepDisplayer.reloadSettings();
        if (mPaceNotifier     != null) mPaceNotifier.reloadSettings();
        if (mDistanceNotifier != null) mDistanceNotifier.reloadSettings();
        if (mSpeedNotifier    != null) mSpeedNotifier.reloadSettings();
        if (mCaloriesNotifier != null) mCaloriesNotifier.reloadSettings();
        if (mSpeakingTimer    != null) mSpeakingTimer.reloadSettings();
    }
    
    public void resetValues() {
        mStepDisplayer.setSteps(0);
        mPaceNotifier.setPace(0);
        mDistanceNotifier.setDistance(0);
        mSpeedNotifier.setSpeed(0);
        mCaloriesNotifier.setCalories(0);
    }
    
    /**
     * Forwards pace values from PaceNotifier to the activity. 
     */
    private StepDisplayer.Listener mStepListener = new StepDisplayer.Listener() {
        public void stepsChanged(int value) {
            mSteps = value;
            passValue();
        }
        public void passValue() {
            if (mCallback != null) {
                mCallback.stepsChanged(mSteps);
            }
        }
    };
    /**
     * Forwards pace values from PaceNotifier to the activity. 
     */
    private PaceNotifier.Listener mPaceListener = new PaceNotifier.Listener() {
        public void paceChanged(int value) {
            mPace = value;
            passValue();
        }
        public void passValue() {
            if (mCallback != null) {
                mCallback.paceChanged(mPace);
            }
        }
    };
    /**
     * Forwards distance values from DistanceNotifier to the activity. 
     */
    private DistanceNotifier.Listener mDistanceListener = new DistanceNotifier.Listener() {
        public void valueChanged(float value) {
            mDistance = value;
            passValue();
        }
        public void passValue() {
            if (mCallback != null) {
                mCallback.distanceChanged(mDistance);
            }
        }
    };
    /**
     * Forwards speed values from SpeedNotifier to the activity. 
     */
    private SpeedNotifier.Listener mSpeedListener = new SpeedNotifier.Listener() {
        public void valueChanged(float value) {
            mSpeed = value;
            passValue();
        }
        public void passValue() {
            if (mCallback != null) {
                mCallback.speedChanged(mSpeed);
            }
        }
    };
    /**
     * Forwards calories values from CaloriesNotifier to the activity. 
     */
    private CaloriesNotifier.Listener mCaloriesListener = new CaloriesNotifier.Listener() {
        public void valueChanged(float value) {
            mCalories = value;
            passValue();
        }
        public void passValue() {
            if (mCallback != null) {
                mCallback.caloriesChanged(mCalories);
            }
        }
    };
    
    /**
     * Show a notification while this service is running.
     */
    private void showNotification() {
        CharSequence text = getText(R.string.app_name);
        Notification notification = new Notification(R.drawable.ic_notification, null,
                System.currentTimeMillis());
        notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
        Intent pedometerIntent = new Intent();
        pedometerIntent.setComponent(new ComponentName(this, Pedometer.class));
        pedometerIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                pedometerIntent, 0);
        notification.setLatestEventInfo(this, text,
                getText(R.string.notification_subtitle), contentIntent);

        mNM.notify(R.string.app_name, notification);
    }


    // BroadcastReceiver for handling ACTION_SCREEN_OFF.
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Check action just to be on the safe side.
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                // Unregisters the listener and registers it again.
                StepService.this.unregisterDetector();
                StepService.this.registerDetector();
                if (mPedometerSettings.wakeAggressively()) {
                    wakeLock.release();
                    acquireWakeLock();
                }
            }
        }
    };

    private void acquireWakeLock() {
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        int wakeFlags;
        if (mPedometerSettings.wakeAggressively()) {
            wakeFlags = PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
        }
        else if (mPedometerSettings.keepScreenOn()) {
            wakeFlags = PowerManager.SCREEN_DIM_WAKE_LOCK;
        }
        else {
            wakeFlags = PowerManager.PARTIAL_WAKE_LOCK;
        }
        wakeLock = pm.newWakeLock(wakeFlags, TAG);
        wakeLock.acquire();
    }

}

14.Utils

package com.tdc.jibuqi;

import java.util.Locale;

import android.app.Service;
import android.speech.tts.TextToSpeech;
import android.text.format.Time;
import android.util.Log;

public class Utils implements TextToSpeech.OnInitListener {
    private static final String TAG = "Utils";
    private Service mService;

    private static Utils instance = null;

    private Utils() {
    }
     
    public static Utils getInstance() {
        if (instance == null) {
            instance = new Utils();
        }
        return instance;
    }
    
    public void setService(Service service) {
        mService = service;
    }
    
    /********** SPEAKING **********/
    
    private TextToSpeech mTts;
    private boolean mSpeak = false;
    private boolean mSpeakingEngineAvailable = false;

    public void initTTS() {
        // Initialize text-to-speech. This is an asynchronous operation.
        // The OnInitListener (second argument) is called after initialization completes.
        Log.i(TAG, "Initializing TextToSpeech...");
        mTts = new TextToSpeech(mService,this);
    }
    public void shutdownTTS() {
        Log.i(TAG, "Shutting Down TextToSpeech...");

        mSpeakingEngineAvailable = false;
        mTts.shutdown();
        Log.i(TAG, "TextToSpeech Shut Down.");

    }
    public void say(String text) {
        if (mSpeak && mSpeakingEngineAvailable) {
            mTts.speak(text,
                    TextToSpeech.QUEUE_ADD,  // Drop all pending entries in the playback queue.
                    null);
        }
    }

    // Implements TextToSpeech.OnInitListener.
    public void onInit(int status) {
        // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
        if (status == TextToSpeech.SUCCESS) {
        	int result;
            if(Locale.getDefault().getLanguage().equals("zh")&&
    				Locale.getDefault().getCountry().equals("CN")){
            	result = mTts.setLanguage(Locale.CHINESE);
    		}else{
    			result = mTts.setLanguage(Locale.US);
    		}
            if (result == TextToSpeech.LANG_MISSING_DATA ||
                result == TextToSpeech.LANG_NOT_SUPPORTED) {
               // Language data is missing or the language is not supported.
                Log.e(TAG, "Language is not available.");
            } else {
                Log.i(TAG, "TextToSpeech Initialized.");
                mSpeakingEngineAvailable = true;
            }
        } else {
            // Initialization failed.
            Log.e(TAG, "Could not initialize TextToSpeech.");
        }
    }

    public void setSpeak(boolean speak) {
        mSpeak = speak;
    }

    public boolean isSpeakingEnabled() {
        return mSpeak;
    }

    public boolean isSpeakingNow() {
        return mTts.isSpeaking();
    }

    public void ding() {
    }
    
    /********** Time **********/
    
    public static long currentTimeInMillis() {
        Time time = new Time();
        time.setToNow();
        return time.toMillis(false);
    }
}

15.com.tdc.jibuqi.preferences.BodyWeightPreference

package com.tdc.jibuqi.preferences;

import com.tdc.jibuqi.R;
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;


public class BodyWeightPreference extends EditMeasurementPreference {

	public BodyWeightPreference(Context context) {
		super(context);
	}
	public BodyWeightPreference(Context context, AttributeSet attr) {
		super(context, attr);
	}
	public BodyWeightPreference(Context context, AttributeSet attr, int defStyle) {
		super(context, attr, defStyle);
	}

	protected void initPreferenceDetails() {
		mTitleResource = R.string.body_weight_setting_title;
		mMetricUnitsResource = R.string.kilograms;
		mImperialUnitsResource = R.string.pounds;
	}
}

16.com.tdc.jibuqi.preferences.EditMeasurementPreference

package com.tdc.jibuqi.preferences;

import android.content.Context;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;


abstract public class EditMeasurementPreference extends EditTextPreference {
	boolean mIsMetric;
	
	protected int mTitleResource;
	protected int mMetricUnitsResource;
	protected int mImperialUnitsResource;
	
	public EditMeasurementPreference(Context context) {
		super(context);
		initPreferenceDetails();
	}
	public EditMeasurementPreference(Context context, AttributeSet attr) {
		super(context, attr);
		initPreferenceDetails();
	}
	public EditMeasurementPreference(Context context, AttributeSet attr, int defStyle) {
		super(context, attr, defStyle);
		initPreferenceDetails();
	}
	
	abstract protected void initPreferenceDetails();
	
	protected void showDialog(Bundle state) {
		mIsMetric = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("units", "metric").equals("metric");
		setDialogTitle(
				getContext().getString(mTitleResource) + 
				" (" + 
						getContext().getString(
								mIsMetric
								? mMetricUnitsResource 
								: mImperialUnitsResource) + 
				")"
		);
		
		try {
			Float.valueOf(getText());
		}
		catch (Exception e) {
			setText("70");
		}
		
		super.showDialog(state);
	}
	protected void onAddEditTextToDialogView (View dialogView, EditText editText) {
		editText.setRawInputType(
				InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
		super.onAddEditTextToDialogView(dialogView, editText);
	}
	public void onDialogClosed(boolean positiveResult) {
		if (positiveResult) {
			try {
				Float.valueOf(((CharSequence)(getEditText().getText())).toString());
			}
			catch (NumberFormatException e) {
				this.showDialog(null);
				return;
			}
		}
		super.onDialogClosed(positiveResult);
	}
}

17.com.tdc.jibuqi.preferences.StepLengthPreference

package com.tdc.jibuqi.preferences;

import com.tdc.jibuqi.R;
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;


public class StepLengthPreference extends EditMeasurementPreference {

	public StepLengthPreference(Context context) {
		super(context);
	}
	public StepLengthPreference(Context context, AttributeSet attr) {
		super(context, attr);
	}
	public StepLengthPreference(Context context, AttributeSet attr, int defStyle) {
		super(context, attr, defStyle);
	}

	protected void initPreferenceDetails() {
		mTitleResource = R.string.step_length_setting_title;
		mMetricUnitsResource = R.string.centimeters;
		mImperialUnitsResource = R.string.inches;
	}
}

18.layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="@dimen/margin" 
    android:background="@color/screen_background">
    
    <LinearLayout android:id="@+id/row_1"
        android:orientation="horizontal" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:paddingBottom="@dimen/row_spacing">
    
        <LinearLayout android:id="@+id/box_steps"
            android:orientation="vertical"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:paddingRight="@dimen/margin"
            android:layout_weight="1">
        
            <TextView android:id="@+id/step_value"
                android:textSize="@dimen/value"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content"
                android:gravity="center_horizontal" 
                android:background="@color/display_background" 
                android:paddingLeft="@dimen/padding" 
                android:paddingRight="@dimen/padding" 
                android:paddingTop="@dimen/padding"
                android:text=""/>
            <TextView android:id="@+id/step_units"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/units" 
                android:text="@string/steps" 
                android:background="@color/display_background" 
                android:paddingBottom="@dimen/padding"/>

        </LinearLayout>

        <LinearLayout android:id="@+id/box_distance"
            android:orientation="vertical"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_weight="1">
            
            <TextView android:id="@+id/distance_value"
                android:textSize="@dimen/value"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content"
                android:gravity="center_horizontal" 
                android:background="@color/display_background" 
                android:paddingTop="@dimen/padding" 
                android:paddingRight="@dimen/padding" 
                android:paddingLeft="@dimen/padding"
                android:text=""/>
            <TextView android:id="@+id/distance_units"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/units"
                android:text="@string/kilometers" 
                android:background="@color/display_background" 
                android:paddingBottom="@dimen/padding"/>

        </LinearLayout>
    </LinearLayout>
        
    <LinearLayout android:id="@+id/row_2"
        android:orientation="horizontal" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:paddingBottom="@dimen/row_spacing">
    
        <LinearLayout android:id="@+id/box_pace"
            android:orientation="vertical" 
            android:layout_height="wrap_content"
            android:paddingRight="@dimen/margin" 
            android:layout_width="fill_parent"
            android:layout_weight="1">
        
            <TextView android:id="@+id/pace_value"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content" 
                android:background="@color/display_background" 
                android:textSize="@dimen/small_value" 
                android:paddingLeft="@dimen/padding" 
                android:paddingRight="@dimen/padding" 
                android:paddingTop="@dimen/padding"
                android:text=""/>
            <TextView android:id="@+id/pace_units"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/units"
                android:text="@string/steps_per_minute" 
                android:paddingBottom="@dimen/padding" 
                android:background="@color/display_background"/>
                         
        </LinearLayout>

        <LinearLayout android:id="@+id/box_speed"
            android:orientation="vertical"
            android:paddingRight="@dimen/margin"  
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent"
            android:layout_weight="1">
        
            <TextView android:id="@+id/speed_value"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content" 
                android:background="@color/display_background" 
                android:textSize="@dimen/small_value" 
                android:paddingLeft="@dimen/padding" 
                android:paddingRight="@dimen/padding" 
                android:paddingTop="@dimen/padding"
                android:text=""/>
            <TextView android:id="@+id/speed_units"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/units"
                android:text="@string/kilometers_per_hour" 
                android:paddingBottom="@dimen/padding" 
                android:background="@color/display_background"/>
        </LinearLayout>

        <LinearLayout android:id="@+id/box_calories"
            android:orientation="vertical" 
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:layout_weight="1">
        
            <TextView android:id="@+id/calories_value"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content" 
                android:background="@color/display_background" 
                android:textSize="@dimen/small_value" 
                android:paddingLeft="@dimen/padding" 
                android:paddingRight="@dimen/padding" 
                android:paddingTop="@dimen/padding"
                android:text=""/>
            <TextView android:id="@+id/calories_units"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textSize="@dimen/units" 
                android:text="@string/calories_burned" 
                android:paddingBottom="@dimen/padding" 
                android:background="@color/display_background"/>
                         
        </LinearLayout>

    </LinearLayout>

    <!-- Desired pace/speed row -->
    <LinearLayout
        android:id="@+id/desired_pace_control"
        android:paddingTop="@dimen/row_spacing" 
        android:gravity="center_horizontal"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">
    
        <!-- Button "-", for decrementing desired pace/speed -->
        <Button android:id="@+id/button_desired_pace_lower"
            android:text="-"
            android:textSize="@dimen/button_sign"
            android:layout_width="@dimen/button"
            android:layout_height="@dimen/button"/>
        
        <!-- Container for desired pace/speed -->
        <LinearLayout
            android:gravity="center_horizontal"
            android:orientation="vertical"
            android:layout_width="@dimen/desired_pace_width"
            android:layout_height="wrap_content">
            
            <TextView android:id="@+id/desired_pace_label"
                android:gravity="center_horizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/desired_pace"
                android:textSize="@dimen/desired_pace_label"/>
        
            <!-- Current desired pace/speed -->
            <TextView android:id="@+id/desired_pace_value"
                android:gravity="center_horizontal"
                android:textSize="@dimen/desired_pace"
                android:layout_width="@dimen/desired_pace_width"
                android:layout_height="wrap_content"/>
        
        </LinearLayout>

        <!-- Button "+", for incrementing desired pace/speed -->
        <Button android:id="@+id/button_desired_pace_raise"
            android:text="+"
            android:textSize="@dimen/button_sign"
            android:layout_width="@dimen/button"
            android:layout_height="@dimen/button"/>

    </LinearLayout>
   
</LinearLayout>

19.arrays.xml

<resources>
    <string-array name="sensitivity_preference">
        <item>@string/extra_high</item>
        <item>@string/very_high</item>
        <item>@string/high</item>
        <item>@string/higher</item>
        <item>@string/medium</item>
        <item>@string/lower</item>
        <item>@string/low</item>
        <item>@string/very_low</item>
        <item>@string/extra_low</item>
    </string-array>

    <string-array name="sensitivity_preference_values">
        <item>1.9753</item>
        <item>2.9630</item>
        <item>4.4444</item><!-- 10 * 1.5^(-2) -->
        <item>6.6667</item><!-- 10 * 1.5^(-1) -->
        <item>10</item>
        <item>15</item><!--     10 * 1.5      -->
        <item>22.5</item><!--   10 * 1.5^2    -->
        <item>33.75</item>
        <item>50.625</item>
    </string-array>

    <string-array name="operation_level_preference">
        <item>@string/run_in_background</item>
        <item>@string/keep_screen_on</item>
        <item>@string/wake_up</item>
    </string-array>

    <string-array name="operation_level_preference_values">
        <item>run_in_background</item>
        <item>keep_screen_on</item>
        <item>wake_up</item>
    </string-array>

    <string-array name="units_preference">
        <item>@string/units_metric</item>
        <item>@string/units_imperial</item>
    </string-array>

    <string-array name="units_preference_values">
        <item>metric</item>
        <item>imperial</item>
    </string-array>

    <string-array name="exercise_type_preference">
        <item>@string/exercise_type_running</item>
        <item>@string/exercise_type_walking</item>
    </string-array>
    <string-array name="exercise_type_preference_values">
        <item>running</item>
        <item>walking</item>
    </string-array>

    <string-array name="maintain_preference">
        <item>@string/maintain_nothing</item>
        <item>@string/maintain_pace</item>
        <item>@string/maintain_speed</item>
    </string-array>
    <string-array name="maintain_preference_values">
        <item>none</item>
        <item>pace</item>
        <item>speed</item>
    </string-array>

    <string-array name="speaking_interval_preference">
        <item>@string/interval_15_seconds</item>
        <item>@string/interval_30_seconds</item>
        <item>@string/interval_1_minute</item>
        <item>@string/interval_2_minutes</item>
        <item>@string/interval_5_minutes</item>
        <item>@string/interval_10_minutes</item>
    </string-array>
    <string-array name="speaking_interval_preference_values">
        <item>0.25</item>
        <item>0.5</item>
        <item>1</item>
        <item>2</item>
        <item>5</item>
        <item>10</item>
    </string-array>


</resources>

20.colors.xml

<resources>
    <color name="screen_background">#333</color>
    <color name="display_background">#000</color>
</resources>

21.dimens.xml

<resources>
    <dimen name="large_half">240px</dimen>

    <dimen name="value">40sp</dimen>
    <dimen name="small_value">40sp</dimen>
    <!-- <dimen name="step_count">30sp</dimen> -->
    <dimen name="units">16sp</dimen>
    <dimen name="desired_pace">30sp</dimen>
    <dimen name="desired_pace_label">18sp</dimen>
    <dimen name="desired_pace_width">150sp</dimen>

    <dimen name="button">60sp</dimen>
    <dimen name="button_sign">30sp</dimen>

    <dimen name="margin">6px</dimen>
    <dimen name="padding">5px</dimen>
    <dimen name="row_spacing">6px</dimen>

</resources>

22.strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Pedometer</string>
    <string name="notification_subtitle">Counting your steps</string>

    <string name="started">Pedometer started.</string>
    <string name="stopped">Pedometer stopped.</string>

    <string name="steps">steps</string>
    <string name="kilometers">kilometers</string>
    <string name="miles">miles</string>
    <string name="steps_per_minute">steps / minute</string>
    <string name="kilometers_per_hour">kilometers / hour</string>
    <string name="miles_per_hour">miles / hour</string>
    <string name="calories_burned">calories burned</string>
    <string name="centimeters">centimeters</string>
    <string name="inches">inches</string>
    <string name="kilograms">kilograms</string>
    <string name="pounds">pounds</string>

    <string name="desired_pace">Desired pace:</string>
    <string name="desired_speed">Desired speed:</string>

    <string name="pause">Pause</string>
    <string name="resume">Resume</string>
    <string name="reset">Reset</string>
    
    <!-- Settings -->
    <string name="settings">Settings</string>
    <string name="activity_settings">Pedometer Settings</string>
    <string name="steps_settings_title">Basic Settings</string>
    <string name="sensitivity_setting">Sensitivity</string>
    <string name="sensitivity_setting_details">Calibrate the step detector</string>
    <string name="sensitivity_setting_title">Select sensitivity level</string>
    <string name="extra_high">extra high</string>
    <string name="very_high">very high</string>
    <string name="high">high</string>
    <string name="higher">higher</string>
    <string name="medium">medium</string>
    <string name="lower">lower</string>
    <string name="low">low</string>
    <string name="very_low">very low</string>
    <string name="extra_low">extra low</string>
    <string name="operation_level_setting">Operational level</string>
    <string name="operation_level_setting_details">Some OS versions prevent using sensors when the screen is off; set the level that works for you</string>
    <string name="operation_level_setting_title">Select operational level</string>
    <string name="run_in_background">Normal (just try running in background)</string>
    <string name="keep_screen_on">Screen on (keep screen dim)</string>
    <string name="wake_up">Aggressive (wake up when I turn screen off)</string>
    <string name="units_setting">Units</string>
    <string name="units_setting_details">Imperial or metric units</string>
    <string name="units_setting_title">Choose your units</string>
    <string name="units_metric">metric (kilometers)</string>
    <string name="units_imperial">imperial (miles)</string>
    <string name="step_length_setting">Step length</string>
    <string name="step_length_setting_details">For distance, speed & calorie calculation</string>
    <string name="step_length_setting_title">Enter your step length</string>
    <string name="body_weight_setting">Body weight</string>
    <string name="body_weight_setting_details">For calorie calculation</string>
    <string name="body_weight_setting_title">Enter your body weight</string>
    <string name="exercise_type_setting">Exercise type</string>
    <string name="exercise_type_setting_details">For calorie calculation</string>
    <string name="exercise_type_setting_title">Choose exercise type</string>
    <string name="exercise_type_running">running</string>
    <string name="exercise_type_walking">walking</string>
    <string name="maintain_setting">Maintain pace/speed</string>
    <string name="maintain_setting_details">Maintaining a desired a pace/speed</string>
    <string name="maintain_setting_title">Maintain:</string>
    <string name="maintain_nothing">nothing</string>
    <string name="maintain_pace">pace</string>
    <string name="maintain_speed">speed</string>
    <string name="voice_settings_title">Voice</string>
    <string name="voice_setting">Speak</string>
    <string name="voice_setting_details">Enable/disable voice notification</string>
    <string name="speaking_interval_setting">Interval</string>
    <string name="speaking_interval_setting_details">Voice notification interval</string>
    <string name="interval_15_seconds">15 seconds</string>
    <string name="interval_30_seconds">30 seconds</string>
    <string name="interval_1_minute">1 minute</string>
    <string name="interval_2_minutes">2 minutes</string>
    <string name="interval_5_minutes">5 minutes</string>
    <string name="interval_10_minutes">10 minutes</string>
    <string name="tell_what">What to tell</string>
    <string name="tell_steps_setting">Steps</string>
    <string name="tell_steps_setting_details"></string>
    <string name="tell_pace_setting">Pace</string>
    <string name="tell_pace_setting_details">steps / minute</string>
    <string name="tell_distance_setting">Distance</string>
    <string name="tell_distance_setting_details">kilometers or miles</string>
    <string name="tell_speed_setting">Speed</string>
    <string name="tell_speed_setting_details">km/h or mph</string>
    <string name="tell_calories_setting">Calories burned</string>
    <string name="tell_calories_setting_details"></string>
    <string name="tell_fasterslower_setting">Faster/slower</string>
    <string name="tell_fasterslower_setting_details">Helps you maintain your desired pace or speed (interval doesn\'t apply)</string>
    <string name="incorrect_step_length">Incorrect step length format! Go to the Settings to change it!</string>

    <string name="quit">Quit</string>

</resources>

23.styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MyStyle" parent="android:Theme.Holo">
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowNoTitle">false</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowShowWallpaper">false</item>
    </style>
</resources>

24.中文strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">计步器</string>
    <string name="notification_subtitle">正在计步中</string>

    <string name="started">计步器开始</string>
    <string name="stopped">计步器停止</string>

    <string name="steps">步数</string>
    <string name="kilometers">公里</string>
    <string name="miles">英里</string>
    <string name="steps_per_minute">步/分钟</string>
    <string name="kilometers_per_hour">公里/小时</string>
    <string name="miles_per_hour">英里/小时</string>
    <string name="calories_burned">消耗卡路里</string>
    <string name="centimeters">厘米</string>
    <string name="inches">英寸</string>
    <string name="kilograms">千克</string>
    <string name="pounds">英镑</string>

    <string name="desired_pace">设置目标步伐</string>
    <string name="desired_speed">设置目标速度</string>

    <string name="pause">暂停</string>
    <string name="resume">继续</string>
    <string name="reset">重置</string>
    
    <!-- Settings -->
    <string name="settings">设置</string>
    <string name="activity_settings">计步器设置</string>
    <string name="steps_settings_title">基本设置</string>
    <string name="sensitivity_setting">灵敏度</string>
    <string name="sensitivity_setting_details">校准步骤检测器</string>
    <string name="sensitivity_setting_title">选择敏感水平</string>
    <string name="extra_high">超高</string>
    <string name="very_high">非常高</string>
    <string name="high">很高</string>
    <string name="higher">比较高</string>
    <string name="medium">一般</string>
    <string name="lower">低</string>
    <string name="low">比较低</string>
    <string name="very_low">非常低</string>
    <string name="extra_low">超低</string>
    <string name="operation_level_setting">运行模式</string>
    <string name="operation_level_setting_details">当屏幕关闭的时候,操作系统可能会关闭一些传感器,为了程序正常运行,需要您设置合适的模式</string>
    <string name="operation_level_setting_title">选择运行模式</string>
    <string name="run_in_background">CPU保持运行,屏幕和按键背光灯关闭</string>
    <string name="keep_screen_on">CPU保持运行,屏幕变暗,按键背光灯关闭</string>
    <string name="wake_up">CPU保持运行,屏幕变暗,按键背光灯关闭,并立即生效</string>
    <string name="units_setting">单位</string>
    <string name="units_setting_details">英制或公制单位</string>
    <string name="units_setting_title">选择你的单位</string>
    <string name="units_metric">公里</string>
    <string name="units_imperial">英寸</string>
    <string name="step_length_setting">步长</string>
    <string name="step_length_setting_details">用于计算距离</string>
    <string name="step_length_setting_title">输入您的步长</string>
    <string name="body_weight_setting">体重</string>
    <string name="body_weight_setting_details">用于计算热量</string>
    <string name="body_weight_setting_title">输入您的体重</string>
    <string name="exercise_type_setting">运动方式</string>
    <string name="exercise_type_setting_details">用于计算热量</string>
    <string name="exercise_type_setting_title">选择运动方式</string>
    <string name="exercise_type_running">跑步</string>
    <string name="exercise_type_walking">走路</string>
    <string name="maintain_setting">目标步伐/速度</string>
    <string name="maintain_setting_details">设置运动时目标步伐或者目标速度</string>
    <string name="maintain_setting_title">设置</string>
    <string name="maintain_nothing">不设置</string>
    <string name="maintain_pace">步伐</string>
    <string name="maintain_speed">速度</string>
    <string name="voice_settings_title">声音</string>
    <string name="voice_setting">讲话</string>
    <string name="voice_setting_details">启用/禁用语音通知</string>
    <string name="speaking_interval_setting">间隔</string>
    <string name="speaking_interval_setting_details">语音通知间隔时间</string>
    <string name="interval_15_seconds">15秒</string>
    <string name="interval_30_seconds">30秒</string>
    <string name="interval_1_minute">1分钟</string>
    <string name="interval_2_minutes">2分钟</string>
    <string name="interval_5_minutes">5分钟</string>
    <string name="interval_10_minutes">10分钟</string>
    <string name="tell_what">说话内容</string>
    <string name="tell_steps_setting">步数</string>
    <string name="tell_steps_setting_details"></string>
    <string name="tell_pace_setting">步伐</string>
    <string name="tell_pace_setting_details">步/分钟</string>
    <string name="tell_distance_setting">距离</string>
    <string name="tell_distance_setting_details">公里或者英里</string>
    <string name="tell_speed_setting">速度</string>
    <string name="tell_speed_setting_details">公里每小时或者米每小时</string>
    <string name="tell_calories_setting">消耗卡路里</string>
    <string name="tell_calories_setting_details"></string>
    <string name="tell_fasterslower_setting">快/慢</string>
    <string name="tell_fasterslower_setting_details">有助于你保持所需的步伐或速度(间隔不适用)</string>
    <string name="incorrect_step_length">不正确的步骤长度格式,请重新设置!</string>

    <string name="quit">退出</string>

</resources>






  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值