android高分段进阶攻略(2)传感器
2014-03-02 15:51
260 查看
一开始,先对昨晚在昆明市火车站遇难的同胞表示默哀,并对恶势力进行谴责,你们如果有再大的冤情也不要对平民下手,所谓冤有头债有主,该弄谁弄谁去啊,欺负百姓算是怎么回事,所以在遇到突发情况下,首先要有泰山崩于前而面不改色的镇定,其次要么能像成龙大哥那样以一抵十的身手,要么就是跑得快,第一项技能好像普通人是无法学会的,那我们只能学习第二项技能——跑得快,当然冰冻三尺非一日寒,这就需要大家平时多多锻炼,怎么记录提醒自己锻炼了,就和我们今天要说这个计步器APP有关了。
上次我已经和大家基本介绍了下各种传感器,今天就是传感器的实际应用,由于商业运作的原因,还暂时不能开源我做的app,文章末尾会有上传个pedometer计步器,供大家学习。
首先问下大家觉得计步器应该是用什么传感器了,其实就是利用方向传感器,根据上次说的Value的那个值进行判断,计步器原理就是人拿着手机走,走一步会产生振荡,从而方向传感获得参数Value,通过两次Value[1]的变化值之差来判断人是否走路,从而达到计步效果。核心代码如下:public void onSensorChanged(SensorEvent event)
{
// 当两个values[1]值之差的绝对值大于8时认为走了一步
if (Math.abs(event.values[1] - lastPoint) > 8)
{
lastPoint = event.values[1];
count++;
}
}
然后如何完整的实现这个APP了,首先我们应该构思用户界面上这个功能需要些什么,下图是我设计的主要界面:
界面看起来很复杂,其实很简单,需要一张表记录用户的记录,然后显示出来,点击开始启动service,每一分钟刷新下界面,画出一个心电图,点击结束关闭service。
首先我们来写service,第一个service从最简单刷新界面service开始,这个service很简单,当接收到广播的时候,获得相关参数进行刷新。public class StepUpdateReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();//获得Bundle
int steps = bundle.getInt("step");//读取步数
view1.stepsPerMin = steps+PerMin;//view1是读取了MainActivity里面的view,PerMin是记录每分钟走了几步
view1.stepsToday = steps+Today;//Today是记录今天走了几步
view1.isMoving = true;//表示用户走路
view1.updateView(); //刷新界面,重画界面
}
}
然后我们来写一个ManagerSerivce,用户通过点击按钮传过来广播消息,通过这个类去判断用户是进行启动还是结束,代码如下:
class ManagerReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
int result = intent.getIntExtra("result");
switch(result){
case WalkingService.CMD_STOP://停止服务
stopSelf();
break;
case WalkingService.CMD_START: //SERVICE启动
isActivityOn = true;
Intent i = new Intent();
i.setAction("MainActivity");i.putExtra("step", steps);
sendBroadcast(i);
break;
}
}
}
写完ManagerService我们开始写最关键的WalkingService:
public class WalkingService extends Service{
SensorManagerSimulator mySensorManager;
WalkingListener wl; //这里自己写了个接听类
int steps=0;
boolean isActivityOn = false; //Activity 是否运行
boolean isServiceOn = false;
NotificationManager nm;//声明NotificationManager
long timeInterval = 60*1000;
final static int CMD_STOP = 0;
final static int CMD_START = 1;
ManagerReceiver receiver; //声明BroadcastReceiver
Handler myHandler = new Handler(){//定时上传数据
public void handleMessage(Message msg) {
uploadData();
super.handleMessage(msg);
}
};
public void onCreate() {
super.onCreate();
wl = new WalkingListener(this); //创建监听器类
//初始化传感器
mySensorManager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE);
mySensorManager.connectSimulator();
//注册监听器
mySensorManager.registerListener(wl,SensorManager.SENSOR_ACCELEROMETER,SensorManager.SENSOR_DELAY_UI);
nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
isServiceOn = true;
showNotification();//添加Notification
receiver = new ManagerReceiver();
IntentFilter filter1 = new IntentFilter();
filter1.addAction("WalkingService");
registerReceiver(receiver, filter1);
//每分钟刷新一次界面
if(isServiceOn){
Message msg =myHandler.obtainMessage();
myHandler.sendMessageDelayed(msg,
timeInterval);
}
}
public void onDestroy() {
mySensorManager.unregisterListener(wl);
wl = null;
mySensorManager = null;
nm.cancel(0);
unregisterReceiver(receiver);
super.onDestroy();
}
private void showNotification() {
Intent intent = new Intent(this,WalkingActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,
0, intent, 0);
Notification myNotification = new Notification();
myNotification.icon = R.drawable.icon;
myNotification.defaults = otification.DEFAULT_ALL;
myNotification.setLatestEventInfo(this,
"计步器运行中", "点击查看", pi);
nm.notify(0,myNotification);
}
public void uploadData(){
对数据库进行操作,并发送广播给StepUpdateSerivce
}
}
这里主要有几个重点,第一在oncreate里面初始化传感器,和上一节的方法一致,第二在onstart注册接听器,第三在ondestory方法里面取消接听器,有些细节需要的解释的,什么是NotificatonMangager,这是一个公用类,用于在android通知栏显示app信息和手机状态信息,自己写了一个show方法用于,最小化APP的时候,用户可以在通知栏里面看到该app;为什么不时时刷新,太吃机子性能,用户体验性不好,只能改成每分钟刷新,因为需要画图。
最后我们在把核心代码写在WalkingListener里面就可以了。
public class WalkingListener implements SensorListener
{
WalkingService father; // WalkingService 引用
float [] preCoordinate;
double currentTime=0,lastTime=0; //记录时间
float WALKING_THRESHOLD = 20;
public WalkingListener(WalkingService father){
this.father = father;
}
public void onAccuracyChanged(int arg0, int arg1) {}
//传感器发生变化后调用该方法
public void onSensorChanged(int sensor, float[] values) {
if(sensor ==SensorManager.SENSOR_ACCELEROMETER){
analyseData(values);//调用方法分析数据
}
}
public void analyseData(float[] values){
currentTime=System.currentTimeMillis();
//每隔200MS 取加速度力和前一个进行比较
if(currentTime - lastTime >200){
if(preCoordinate == null){//还未存过数据
preCoordinate = new float[3];
for(int i=0;i<3;i++){
preCoordinate = values;
}
关于算法,因为需要精确,所以我进行的是向量夹角的判断,当夹角大于20的时候就证明用户走了一步,其实算法多样,你可以自己选择,这也是我百度到的算法,至此一个计步器就完成了。
最后希望大家能踊跃评论,大家可以说下自己想实现什么app,我先去试试,然后做成教程来写出,不然我一个人做过的app也很少,下面是网上开源的demo,我的demo等后续再上传。
源码下载
上次我已经和大家基本介绍了下各种传感器,今天就是传感器的实际应用,由于商业运作的原因,还暂时不能开源我做的app,文章末尾会有上传个pedometer计步器,供大家学习。
首先问下大家觉得计步器应该是用什么传感器了,其实就是利用方向传感器,根据上次说的Value的那个值进行判断,计步器原理就是人拿着手机走,走一步会产生振荡,从而方向传感获得参数Value,通过两次Value[1]的变化值之差来判断人是否走路,从而达到计步效果。核心代码如下:public void onSensorChanged(SensorEvent event)
{
// 当两个values[1]值之差的绝对值大于8时认为走了一步
if (Math.abs(event.values[1] - lastPoint) > 8)
{
lastPoint = event.values[1];
count++;
}
}
然后如何完整的实现这个APP了,首先我们应该构思用户界面上这个功能需要些什么,下图是我设计的主要界面:
界面看起来很复杂,其实很简单,需要一张表记录用户的记录,然后显示出来,点击开始启动service,每一分钟刷新下界面,画出一个心电图,点击结束关闭service。
首先我们来写service,第一个service从最简单刷新界面service开始,这个service很简单,当接收到广播的时候,获得相关参数进行刷新。public class StepUpdateReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();//获得Bundle
int steps = bundle.getInt("step");//读取步数
view1.stepsPerMin = steps+PerMin;//view1是读取了MainActivity里面的view,PerMin是记录每分钟走了几步
view1.stepsToday = steps+Today;//Today是记录今天走了几步
view1.isMoving = true;//表示用户走路
view1.updateView(); //刷新界面,重画界面
}
}
然后我们来写一个ManagerSerivce,用户通过点击按钮传过来广播消息,通过这个类去判断用户是进行启动还是结束,代码如下:
class ManagerReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
int result = intent.getIntExtra("result");
switch(result){
case WalkingService.CMD_STOP://停止服务
stopSelf();
break;
case WalkingService.CMD_START: //SERVICE启动
isActivityOn = true;
Intent i = new Intent();
i.setAction("MainActivity");i.putExtra("step", steps);
sendBroadcast(i);
break;
}
}
}
写完ManagerService我们开始写最关键的WalkingService:
public class WalkingService extends Service{
SensorManagerSimulator mySensorManager;
WalkingListener wl; //这里自己写了个接听类
int steps=0;
boolean isActivityOn = false; //Activity 是否运行
boolean isServiceOn = false;
NotificationManager nm;//声明NotificationManager
long timeInterval = 60*1000;
final static int CMD_STOP = 0;
final static int CMD_START = 1;
ManagerReceiver receiver; //声明BroadcastReceiver
Handler myHandler = new Handler(){//定时上传数据
public void handleMessage(Message msg) {
uploadData();
super.handleMessage(msg);
}
};
public void onCreate() {
super.onCreate();
wl = new WalkingListener(this); //创建监听器类
//初始化传感器
mySensorManager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE);
mySensorManager.connectSimulator();
//注册监听器
mySensorManager.registerListener(wl,SensorManager.SENSOR_ACCELEROMETER,SensorManager.SENSOR_DELAY_UI);
nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
isServiceOn = true;
showNotification();//添加Notification
receiver = new ManagerReceiver();
IntentFilter filter1 = new IntentFilter();
filter1.addAction("WalkingService");
registerReceiver(receiver, filter1);
//每分钟刷新一次界面
if(isServiceOn){
Message msg =myHandler.obtainMessage();
myHandler.sendMessageDelayed(msg,
timeInterval);
}
}
public void onDestroy() {
mySensorManager.unregisterListener(wl);
wl = null;
mySensorManager = null;
nm.cancel(0);
unregisterReceiver(receiver);
super.onDestroy();
}
private void showNotification() {
Intent intent = new Intent(this,WalkingActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,
0, intent, 0);
Notification myNotification = new Notification();
myNotification.icon = R.drawable.icon;
myNotification.defaults = otification.DEFAULT_ALL;
myNotification.setLatestEventInfo(this,
"计步器运行中", "点击查看", pi);
nm.notify(0,myNotification);
}
public void uploadData(){
对数据库进行操作,并发送广播给StepUpdateSerivce
}
}
这里主要有几个重点,第一在oncreate里面初始化传感器,和上一节的方法一致,第二在onstart注册接听器,第三在ondestory方法里面取消接听器,有些细节需要的解释的,什么是NotificatonMangager,这是一个公用类,用于在android通知栏显示app信息和手机状态信息,自己写了一个show方法用于,最小化APP的时候,用户可以在通知栏里面看到该app;为什么不时时刷新,太吃机子性能,用户体验性不好,只能改成每分钟刷新,因为需要画图。
最后我们在把核心代码写在WalkingListener里面就可以了。
public class WalkingListener implements SensorListener
{
WalkingService father; // WalkingService 引用
float [] preCoordinate;
double currentTime=0,lastTime=0; //记录时间
float WALKING_THRESHOLD = 20;
public WalkingListener(WalkingService father){
this.father = father;
}
public void onAccuracyChanged(int arg0, int arg1) {}
//传感器发生变化后调用该方法
public void onSensorChanged(int sensor, float[] values) {
if(sensor ==SensorManager.SENSOR_ACCELEROMETER){
analyseData(values);//调用方法分析数据
}
}
public void analyseData(float[] values){
currentTime=System.currentTimeMillis();
//每隔200MS 取加速度力和前一个进行比较
if(currentTime - lastTime >200){
if(preCoordinate == null){//还未存过数据
preCoordinate = new float[3];
for(int i=0;i<3;i++){
preCoordinate = values;
}
}
else{ //进行比较 int angle= calculateAngle(values,preCoordinate); if(angle >=WALKING_THRESHOLD){ father.steps++; //步数增加 updateData(); //更新步数,并且向walkingService发送消息 } for(int i=0;i<3;i++){ preCoordinate=values; }} lastTime = currentTime;//重新计时 } }
public void updateData(){ Intent intent = new Intent(); //创建Intent 对象
intent.setAction("MainActivity");
intent.putExtra("step", father.steps);//添加步数 father.sendBroadcast(intent); //发出广播 }
public int calculateAngle(float[] newPoints,float[] oldPoints){ int angle=0; float vectorProduct=0; //向量积 float newMold=0; //新向量的模 float oldMold=0; //旧向量的模 for(int i=0;i<3;i++){ vectorProduct +=newPoints*oldPoints; newMold += newPoints*newPoints; oldMold += oldPoints*oldPoints; } newMold = (float)Math.sqrt(newMold); oldMold = (float)Math.sqrt(oldMold); //计算夹角的余弦 float cosineAngle=(float)(vectorProduct/(newMold*oldMold)); //通过余弦值求角度 float fangle = (float) Math.toDegrees(Math.acos(cosineAngle)); angle = (int)fangle; return angle; //返回向量的夹角 }
关于算法,因为需要精确,所以我进行的是向量夹角的判断,当夹角大于20的时候就证明用户走了一步,其实算法多样,你可以自己选择,这也是我百度到的算法,至此一个计步器就完成了。
最后希望大家能踊跃评论,大家可以说下自己想实现什么app,我先去试试,然后做成教程来写出,不然我一个人做过的app也很少,下面是网上开源的demo,我的demo等后续再上传。
源码下载
相关文章推荐
- android高分段进阶攻略(1)传感器
- android高分段进阶攻略(7)音乐播放器UI设计——抽屉效果
- android高分段进阶攻略(8)音乐播放器代码实现一SlidingDrawer实现
- Android高分段进阶攻略(4)android模拟点击
- android高分段进阶攻略(4)android模拟点击
- android高分段进阶攻略(3)旋转等待UI界面设计
- android高分段进阶攻略(5)android指南针
- android高分段进阶攻略(9)——ViewPager补间动画实现京东广告Banner
- android高分段进阶攻略(6)后台线程AsyncTask
- android高分段进阶攻略(3)旋转等待UI界面设计
- Android 进阶——实现周期性任务调度的几种攻略详解
- 【Android开发进阶】Android屏幕适配全攻略(最权威的官方适配指导)
- Android进阶——Android6.0 动态权限详解及动态申请权限的完全攻略
- Android进阶——自定义View之View的绘制流程及实现onMeasure完全攻略
- 我的Android进阶之旅------>Android利用Sensor(传感器)实现水平仪功能的小例
- 【Android开发进阶】Android屏幕适配全攻略(最权威的官方适配指导)
- 【Android开发进阶】Android屏幕适配全攻略(最权威的官方适配指导)
- 我的Android进阶之旅------>Android利用温度传感器实现带动画效果的电子温度计
- 我的Android进阶之旅------>Android利用Sensor(传感器)实现指南针功能
- Android开发高级进阶——传感器