package com.apicloud.MobileSportService;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager.WakeLock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.apicloud.MobileSportService.pojo.StepData;
import com.apicloud.MobileSportService.utils.DbUtils;
//service负责后台的需要长期运行的任务
// 计步器服务
// 运行在后台的服务程序,完成了界面部分的开发后
// 就可以开发后台的服务类StepService
// 注册或注销传感器监听器,在手机屏幕状态栏显示通知,与StepActivity进行通信,走过的步数记到哪里了???
@SuppressLint("SimpleDateFormat")
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public class StepCounterService extends Service {
public static Boolean FLAG = false;// 服务运行标志
private SensorManager mSensorManager;// 传感器服务
private StepDetector detector;// 传感器监听对象
private Thread thread; // 定义线程对象
private WakeLock mWakeLock;// 屏幕灯
private NotificationManager nm;
private NotificationCompat.Builder builder;
private long startTimer = 0;// 开始时间
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
/**
* 更新通知
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void updateNotification() {
builder = new NotificationCompat.Builder(this);
builder.setPriority(Notification.PRIORITY_MIN);
Notification notification = builder.build();
startForeground(0, notification);
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(R.string.app_name, notification);
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
FLAG = true;// 标记为服务正在运行
// 创建监听器类,实例化监听对象
detector = new StepDetector(this);
// 获取传感器的服务,初始化传感器
mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
// 注册传感器,注册监听器
mSensorManager.registerListener(detector, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
updateNotification();
DbUtils.createDb(getApplicationContext(), "mobile_sport");
saveDB();
}
/**
* 每次调用startService(Intent)的时候,
* 都会调用该Service对象的onStartCommand(Intent,int,int)方法,
* 然后在onStartCommand方法中做一些处理。
*/
@SuppressLint("NewApi")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("TrafficService", "startCommand");
/*
* START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。
* 随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
* START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
* START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
* START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
* */
flags = START_REDELIVER_INTENT;//如果服务被异常kill掉,系统会自动重启该服务
return super.onStartCommand(intent, flags, startId);
}
@TargetApi(Build.VERSION_CODES.ECLAIR)
@Override
public void onDestroy() {
super.onDestroy();
FLAG = false;// 服务停止
nm.cancelAll();
//取消前台进程
stopForeground(true);
if (detector != null) {
mSensorManager.unregisterListener(detector);
}
if (mWakeLock != null) {
mWakeLock.release();
}
}
private void saveDB() {
if (thread == null) {
thread = new Thread() {// 子线程用于监听当前步数的变化
@Override
public void run() {
super.run();
int tempStep = 0;
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (StepCounterService.FLAG) {
tempStep = StepDetector.CURRENT_SETP;
StepDetector.CURRENT_SETP = 0;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(tempStep>0){
startTimer = System.currentTimeMillis()/1000;
List<StepData> list = DbUtils.getQueryByWhere(StepData.class, "timstamp", new String[]{startTimer+""});
if (list.size() == 0 || list.isEmpty()) {
StepData data = new StepData();
data.setStepCount(tempStep + "");
data.setTimes((df.format(new Date())));
data.setTimstamp(startTimer);
DbUtils.insert(data);
} else if (list.size() == 1) {
StepData data = list.get(0);
data.setStepCount(tempStep + "");
DbUtils.update(data);
}
}
tempStep = 0;
}
}
}
};
thread.start();
}
}
}
package com.apicloud.MobileSportService;
import android.annotation.TargetApi;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.util.Log;
//走步检测器,用于检测走步并计数
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public class StepDetector implements SensorEventListener {
public static int CURRENT_SETP = 0;
public static float SENSITIVITY = 3; //SENSITIVITY灵敏度
private float mLastValues[] = new float[3 * 2];
private float mScale[] = new float[2];
private float mYOffset;
private static long end = 0;
private static long start = 0;
/**
* 最后加速度方向
*/
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;
/**
* 传入上下文的构造函数
*
* @param context
*/
public StepDetector(Context context) {
// TODO Auto-generated constructor stub
super();
int h = 480;
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)));
}
@SuppressWarnings("deprecation")
@Override
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;
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));
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]);
//Log.i("StepDetector", "diff:=====================>> " + diff);
if (diff > SENSITIVITY) {
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();
if (end - start > 800) {// 此时判断为走了一步
Log.i("StepDetector", "CURRENT_SETP:" + CURRENT_SETP);
CURRENT_SETP++;
mLastMatch = extType;
start = end;
}
} else {
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
OnSensorChangeListener onSensorChangeListener;
public interface OnSensorChangeListener {
void onChange();
}
public OnSensorChangeListener getOnSensorChangeListener() {
return onSensorChangeListener;
}
public void setOnSensorChangeListener(
OnSensorChangeListener onSensorChangeListener) {
this.onSensorChangeListener = onSensorChangeListener;
}
}