您的位置:首页 > 移动开发 > Android开发

作业——在线学习Android课程之第十周(传感器与LBS)

2016-05-09 01:21 645 查看

一、什么是传感器:

所谓传感器能够探测如光、热、温度、重力、方向 等等的功能!


二、Android中提供传感器有哪些:

google提供了11种传感器供应用层使用。

1、define SENSOR_TYPE_ACCELEROMETER        1 //加速度
2、define SENSOR_TYPE_MAGNETIC_FIELD       2 //磁力
3、define SENSOR_TYPE_ORIENTATION          3 //方向
4、define SENSOR_TYPE_GYROSCOPE            4 //陀螺仪
5、define SENSOR_TYPE_LIGHT                5 //光线感应
6、define SENSOR_TYPE_PRESSURE             6 //压力
7、define SENSOR_TYPE_TEMPERATURE          7 //温度
8、define SENSOR_TYPE_PROXIMITY            8 //接近
9、define SENSOR_TYPE_GRAVITY              9 //重力
10、define SENSOR_TYPE_LINEAR_ACCELERATION  10//线性加速度
11、define SENSOR_TYPE_ROTATION_VECTOR      11//旋转矢量


1 、加速度传感器

加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。
该数值包含地心引力的影响,单位是m/s^2。
将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81。
将手机朝下放在桌面上,z轴为-9.81。
将手机向左倾斜,x轴为正值。
将手机向右倾斜,x轴为负值。
将手机向上倾斜,y轴为负值。
将手机向下倾斜,y轴为正值。

加速度传感器可能是最为成熟的一种mems产品,市场上的加速度传感器种类很多。
手机中常用的加速度传感器有BOSCH(博世)的BMA系列,AMK的897X系列,ST的LIS3X系列等。
这些传感器一般提供±2G至±16G的加速度测量范围,采用I2C或SPI接口和MCU相连,数据精度小于16bit。


2 、磁力传感器

磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。
该数值的单位是微特斯拉(micro-Tesla),用uT表示。
单位也可以是高斯(Gauss),1Tesla=10000Gauss。
硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。
电子罗盘传感器同时提供下文的方向传感器数据。


3 、方向传感器

方向传感器简称为O-sensor,返回三轴的角度数据,方向数据的单位是角度。
为了得到精确的角度数据,E-compass需要获取G-sensor的数据,
经过计算生产O-sensor数据,否则只能获取水平方向的角度。
方向传感器提供三个数据,分别为azimuth、pitch和roll。
azimuth:方位,返回水平时磁北极和Y轴的夹角,范围为0°至360°。
0°=北,90°=东,180°=南,270°=西。
pitch:x轴和水平面的夹角,范围为-180°至180°。
当z轴向y轴转动时,角度为正值。
roll:y轴和水平面的夹角,由于历史原因,范围为-90°至90°。
当x轴向z轴移动时,角度为正值。
电子罗盘在获取正确的数据前需要进行校准,通常可用8字校准法。
8字校准法要求用户使用需要校准的设备在空中做8字晃动,
原则上尽量多的让设备法线方向指向空间的所有8个象限。

手机中使用的电子罗盘芯片有AKM公司的897X系列,ST公司的LSM系列以及雅马哈公司等等。
由于需要读取G-sensor数据并计算出M-sensor和O-sensor数据,
因此厂商一般会提供一个后台daemon来完成工作,电子罗盘算法一般是公司私有产权。


4、陀螺仪传感器

陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。
角加速度的单位是radians/second。
根据Nexus S手机实测:
水平逆时针旋转,Z轴为正。
水平逆时针旋转,z轴为负。
向左旋转,y轴为负。
向右旋转,y轴为正。
向上旋转,x轴为负。
向下旋转,x轴为正。

ST的L3G系列的陀螺仪传感器比较流行,iphone4和google的nexus s中使用该种传感器。


5 、光线感应传感器

光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。
光线感应传感器主要用于Android系统的LCD自动亮度功能。
可以根据采样到的光强数值实时调整LCD的亮度。


6、 压力传感器

压力传感器返回当前的压强,单位是百帕斯卡hectopascal(hPa)。


7 、温度传感器

温度传感器返回当前的温度。


8 、接近传感器

接近传感器检测物体与手机的距离,单位是厘米。
一些接近传感器只能返回远和近两个状态,
因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。
接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。
一些芯片集成了接近传感器和光线传感器两者功能。

下面三个传感器是Android2新提出的传感器类型,目前还不太清楚有哪些应用程序使用。


9 、重力传感器

重力传感器简称GV-sensor,输出重力数据。
在地球上,重力数值为9.8,单位是m/s^2。
坐标系统与加速度传感器相同。
当设备复位时,重力传感器的输出与加速度传感器相同。


10、 线性加速度传感器

线性加速度传感器简称LA-sensor。
线性加速度传感器是加速度传感器减去重力影响获取的数据。
单位是m/s^2,坐标系统与加速度传感器相同。
加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
加速度 = 重力 + 线性加速度


11 、旋转矢量传感器

旋转矢量传感器简称RV-sensor。
旋转矢量代表设备的方向,是一个将坐标轴和角度混合计算得到的数据。
RV-sensor输出三个数据:
x*sin(theta/2)
y*sin(theta/2)
z*sin(theta/2)
sin(theta/2)是RV的数量级。
RV的方向与轴旋转的方向相同。
RV的三个数值,与cos(theta/2)组成一个四元组。
RV的数据没有单位,使用的坐标系与加速度相同。

举例:
1、sensors_event_t.data[0] = x*sin(theta/2)
2、sensors_event_t.data[1] = y*sin(theta/2)
3、sensors_event_t.data[2] = z*sin(theta/2)
4、sensors_event_t.data[3] =   cos(theta/2)
GV、LA和RV的数值没有物理传感器可以直接给出,

需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。
算法一般是传感器公司的私有产权。


三、加速度传感器应用于重力躲避游戏的实例

public class SurfaceViewAcitvity extends Activity {

private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
new AlertDialog.Builder(SurfaceViewAcitvity.this).setTitle("Game Over")//设置对话框标题
.setMessage("重新开始游戏?")//设置显示的内容
.setPositiveButton("确定", new DialogInterface.OnClickListener() {//添加确定按钮
@Override
public void onClick(DialogInterface dialog, int which) {//确定按钮的响应事件
//                                        mCoordinates.clear();
//                                        mTime = 0;
//                                        mIsRunning = true;
//                                    finish();
mAnimView = new MyView(SurfaceViewAcitvity.this);
setContentView(mAnimView);
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {//添加返回按钮
@Override
public void onClick(DialogInterface dialog, int which) {//响应事件
finish();
}
}).show();//在按键响应事件中显示此对话框
break;
}
}
};

MyView mAnimView = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 全屏显示窗口
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//强制竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //LANDSCAPE);

// 显示自定义的游戏View
mAnimView = new MyView(this);
setContentView(mAnimView);
}

public class MyView extends SurfaceView implements Callback, Runnable, SensorEventListener {

/** 每50毫秒刷新一次屏幕 **/
public static final int TIME_IN_FRAME = 50;

final int mRadius = 10;
int mSpeed = 5;

public class Coordinate {
private float x;
private float y;

public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}

public void setX(float x) {
this.x = x;
}

public void setY(float y) {
this.y = y;
}
}

List<Coordinate> mCoordinates = new ArrayList<>();
int mTime = 0;

/** 游戏画笔 **/
Paint mPaint = null;
SurfaceHolder mSurfaceHolder = null;

/** 游戏画布 **/
Canvas mCanvas = null;

/** 控制游戏循环 **/
boolean mIsRunning = false;

/** SensorManager管理器 **/
private SensorManager mSensorMgr = null;
Sensor mSensor = null;

/** 手机屏幕宽高 **/
int mScreenWidth = 0;
int mScreenHeight = 0;

/** 小球资源文件越界区域 **/
private int mScreenBallWidth = 0;
private int mScreenBallHeight = 0;

/** 小球的坐标位置 **/
private float mPosX = 200;
private float mPosY = 0;

/** 重力感应X轴 Y轴 Z轴的重力值 **/
private float mGX = 0;
private float mGY = 0;
private float mGZ = 0;

public MyView(Context context) {
super(context);
/** 设置当前View拥有控制焦点 **/
this.setFocusable(true);
/** 设置当前View拥有触摸事件 **/
this.setFocusableInTouchMode(true);
/** 拿到SurfaceHolder对象 **/
mSurfaceHolder = this.getHolder();
/** 将mSurfaceHolder添加到Callback回调函数中 **/
mSurfaceHolder.addCallback(this);
/** 创建画布 **/
mCanvas = new Canvas();
/** 创建曲线画笔 **/
mPaint = new Paint();
mPaint.setColor(Color.WHITE);

/**得到SensorManager对象**/
mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// 注册listener,第三个参数是检测的精确度
//SENSOR_DELAY_FASTEST 最灵敏 因为太快了没必要使用
//SENSOR_DELAY_GAME    游戏开发中使用
//SENSOR_DELAY_NORMAL  正常速度
//SENSOR_DELAY_UI          最慢的速度
mSensorMgr.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_GAME);
}

private void Draw() {

/**绘制游戏背景**/
mCanvas.drawColor(Color.BLACK);
/**绘制小球**/
mPaint.setColor(Color.BLUE);
mCanvas.drawCircle(mPosX, mPosY, mRadius, mPaint);

mPaint.setColor(Color.RED);
Coordinate coordinate;
for (int i = 0; i < mCoordinates.size(); i++) {
coordinate = mCoordinates.get(i);
mCanvas.drawCircle(coordinate.getX(), coordinate.getY(), mRadius, mPaint);
}
/**X轴 Y轴 Z轴的重力值**/
//            mPaint.setColor(Color.WHITE);
//            mCanvas.drawText("X轴重力值 :" + mGX, 0, 20, mPaint);
//            mCanvas.drawText("Y轴重力值 :" + mGY, 0, 40, mPaint);
//            mCanvas.drawText("Z轴重力值 :" + mGZ, 0, 60, mPaint);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
/**开始游戏主循环线程**/
mIsRunning = true;
new Thread(this).start();
/**得到当前屏幕宽高**/
mScreenWidth = this.getWidth();
mScreenHeight = this.getHeight();

mPosX = mScreenWidth / 2;
mPosY = mScreenHeight / 2;

/**得到小球越界区域**/
mScreenBallWidth = mScreenWidth - mRadius * 2;
mScreenBallHeight = mScreenHeight - mRadius * 2;
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsRunning = false;
}

@Override
public void run() {
while (mIsRunning) {

/** 取得更新游戏之前的时间 **/
long startTime = System.currentTimeMillis();

/** 在这里加上线程安全锁 **/
synchronized (mSurfaceHolder) {
/** 拿到当前画布 然后锁定 **/
mCanvas = mSurfaceHolder.lockCanvas();
Coordinate coor;
double disx, disy, dis;
for (int i = 0; i < mCoordinates.size(); i++) {
coor = mCoordinates.get(i);
disx = (coor.getX() - mPosX);
disy = (coor.getY() - mPosY);
dis = Math.sqrt(Math.pow(disx, 2) + Math.pow(disy, 2));
if (dis < mRadius * 2){
mHandler.sendEmptyMessage(0);
mIsRunning = false;
} else {
coor.setX((float)(coor.getX() - mSpeed * disx / dis));
coor.setY((float)(coor.getY() - mSpeed * disy / dis));
}
}

addredpoint();
Draw();
/** 绘制结束后解锁显示在屏幕上 **/
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}

/** 取得更新游戏结束的时间 **/
long endTime = System.currentTimeMillis();

/** 计算出游戏一次更新的毫秒数 **/
int diffTime = (int) (endTime - startTime);

/** 确保每次更新时间为50帧 **/
while (diffTime <= TIME_IN_FRAME) {
diffTime = (int) (System.currentTimeMillis() - startTime);
/** 线程等待 **/
Thread.yield();
}
}
}

private void addredpoint() {
if (mTime > 20){
Random random = new Random();
double dis;
Coordinate coordinate;
do {
coordinate = new Coordinate(random.nextInt(mScreenBallWidth) + mRadius, random.nextInt(mScreenBallHeight) + mRadius);
dis = Math.pow((coordinate.getX() - mPosX), 2) + Math.pow((coordinate.getY() - mPosY), 2);
}while (dis < 400);
mCoordinates.add(coordinate);
mTime = 0;
} else {
mTime++;
}
}

@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {
mGX = event.values[SensorManager.DATA_X];
mGY = event.values[SensorManager.DATA_Y];
mGZ = event.values[SensorManager.DATA_Z];

//这里乘以2是为了让小球移动的更快
mPosX -= mGX * 2;
mPosY += mGY * 2;

//检测小球是否超出边界
if (mPosX < 0) {
mPosX = 0;
} else if (mPosX > mScreenBallWidth) {
mPosX = mScreenBallWidth;
}
if (mPosY < 0) {
mPosY = 0;
} else if (mPosY > mScreenBallHeight) {
mPosY = mScreenBallHeight;
}
}
}
}


四、LBS的使用

1、到百度地图申请新版本的key,老版本的也可以使用。



http://developer.baidu.com/map/geosdk-android-key.htm

2、在manifes中添加权限,具体参考

< !-- 使用定位所需权限 -->
< permission Android:name="android.permission.BAIDU_LOCATION_SERVICE" >
< /permission>

< uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
< uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
< uses-permission android:name="android.permission.READ_LOGS" />
< uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

在manifest中添加定位所需要的service

<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>

在application标签中添加你锁申请的key

<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="15xihyx7BjNPAuvrAgade2Wo" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: