paint.ascent()和paint.descent()

mikel阅读(941)

1.基准点是baseline

2.ascent:是baseline之上至字符最高处的距离

3.descent:是baseline之下至字符最低处的距离

4.leading:是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离

5.top:是指的是最高字符到baseline的值,即ascent的最大值

6.bottom:是指最低字符到baseline的值,即descent的最大值

[转载]Android显示GIF动画完整示例 - 新一 - 博客园

mikel阅读(867)

来源: [转载]Android显示GIF动画完整示例(一) – 新一 – 博客园

MainActivity如下:

<pre class="java">package cc.testgif;

import com.ant.liao.GifView;
import com.ant.liao.GifView.GifImageType;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.app.Activity;
/**
 * Demo描述:
 * 利用第三方控件显示GIF动画
 * 
 * 参考资料:
 * http://blog.csdn.net/leilu2008/article/details/6822517#
 * http://code.google.com/p/gifview/source/checkout
 * Thank you very much
 */
public class MainActivity extends Activity {
    private GifView mGifView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		init();
	}

	private void init(){
		mGifView = (GifView) findViewById(R.id.gifView);
		mGifView.setGifImage(R.drawable.gif);
		mGifView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				System.out.println(" Click ");
			}
		});
		mGifView.setShowDimension(300, 300);
		//加载方式
		mGifView.setGifImageType(GifImageType.COVER);
	}

}

main.xml如下:

</pre>
<pre class="html">&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    &gt;

    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:layout_centerHorizontal="true" /&gt;
    
    &lt;com.ant.liao.GifView
        android:id="@+id/gifView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:enabled="false"
        android:layout_centerInParent="true" /&gt;

&lt;/RelativeLayout&gt;

MainActivity如下:

</pre>
<pre class="java">package cc.testgif2;

import android.os.Bundle;
import android.app.Activity;
/**
 * Demo描述:
 * 利用自定义View控件显示GIF动画
 * 详细代码参见GIFView
 * 
 * 参考资料:
 * http://blog.csdn.net/dawanganban/article/details/9816083
 * Thank you very much
 */
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}
}

GIFView如下:

</pre>
<pre class="java">package cc.testgif2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.view.View;

public class GIFView extends View {
    private Movie mMovie;
    private long startTime;
    private  int gifDuration;
    private boolean isBeginPlay=true;
	public GIFView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public GIFView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public GIFView(Context context) {
		super(context);
		init();
	}
	
	private void init(){
		mMovie = Movie.decodeStream(getResources().openRawResource(R.drawable.gif));
		gifDuration= mMovie.duration();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 从开机到现在的毫秒(不包括手机睡眠的时间在内)
		long currrentTime = android.os.SystemClock.uptimeMillis();
		// 第一次播放
		if (isBeginPlay) {
			startTime = currrentTime;
			isBeginPlay = false;
		}

		int playTime = (int) ((currrentTime - startTime) % gifDuration);
		mMovie.setTime(playTime);
		mMovie.draw(canvas, 0, 0);
		// 重绘
		invalidate();
	}

}

main.xml如下:

</pre>
<pre class="html">&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  &gt;

    &lt;TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" 
        android:layout_centerHorizontal="true"/&gt;
    
    &lt;cc.testgif2.GIFView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
    /&gt;

&lt;/RelativeLayout&gt;

Android笔记:invalidate()和postInvalidate() 的区别及使用

mikel阅读(837)

Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。

invalidate() 是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。 invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。 一个Android 程序默认情况下也只有一个进程,但一个进程下却可以有许多个线程。

在这么多线程当中,把主要是负责控制UI界面的显示、更新和控件交互的线程称为UI线程,由于onCreate()方法是由UI线程执行的,所以也可以把UI线程理解为主线程。其余的线程可以理解为工作者线程。

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。

而postInvalidate()在工作者线程中被调用

 

 

利用invalidate()刷新界面

实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。


// 在onCreate()中开启线程

new Thread(new GameThread()).start();、

// 实例化一个handler

Handler myHandler = new Handler() {
// 接收到消息后处理
public void handleMessage(Message msg) {
switch (msg.what) {
case Activity01.REFRESH:
mGameView.invalidate(); // 刷新界面
break;
}

super.handleMessage(msg);
}
};

class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = Activity01.REFRESH;
// 发送消息
Activity01.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}

使用postInvalidate()刷新界面

使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。


class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

// 使用postInvalidate可以直接在线程中更新界面
mGameView.postInvalidate();
}
}
}

 

[转载]DoNet 开源项目-基于 jQuery EasyUI 的后台管理系统 | 石佳劼的博客

mikel阅读(809)

来源: [转载]DoNet 开源项目-基于 jQuery EasyUI 的后台管理系统 | 石佳劼的博客

博主在业余时间开发了一个简单的后台管理系统,其中用到了 JQuery EasyUI 框架,上次分享过系统布局,参考文章:jQuery EasyUI 后台管理系统布局分享,目前已完成系统的整体框架的搭建,再次分享给大家。

基础功能介绍:

  • 菜单管理、用户管理、组别管理、角色管理、权限管理、错误日志

特色功能介绍:

  • 独创的EntitySQL语法,极大的简化了SQL操作。
  • 灵活的权限设计,任意页面、任意按钮的权限都可随意控制。
  • 高效的代码生成器,指定任意数据表,便可生成CRUD基础代码。

系统部署方法:

  • 网站部署在IIS下。
  • 附加 stonefw.Database 目录下的数据库。
  • 修改 stonefw.Web 目录下 web.config 中的数据库链接字符串。

系统演示截图:


1.除非注明,本博文章均为原创,转载请以链接形式标明本文地址。
2.本博文章只代表博主当时的观点或结论,与博主公司没有任何关系。

Android传感器介绍

mikel阅读(940)

Android传感器介绍

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

1 加速度传感器 TYPE_ACCELEROMETER

加速度传感器又叫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 磁力传感器 TYPE_MAGNETIC_FLELD

磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。

该数值的单位是微特斯拉(micro-Tesla),用uT表示。

单位也可以是高斯(Gauss),1Tesla=10000Gauss。

硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。

电子罗盘传感器同时提供下文的方向传感器数据。

 

3 方向传感器 TYPE_ORIENTATION

方向传感器简称为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 陀螺仪传感器 TYPE_GYROSCOPE

陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。

角加速度的单位是radians/second。

根据Nexus S手机实测:

水平逆时针旋转,Z轴为正。

水平逆时针旋转,z轴为负。

向左旋转,y轴为负。

向右旋转,y轴为正。

向上旋转,x轴为负。

向下旋转,x轴为正。

 

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

 

5 光线感应传感器 TYPE_LIGHT

光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。

光线感应传感器主要用于Android系统的LCD自动亮度功能。

可以根据采样到的光强数值实时调整LCD的亮度。

 

6 压力传感器

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

 

7 温度传感器 TYPE_TEMPERATURE

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

 

8 距离传感器 TYPE_PROXIMITY

接近传感器检测物体与手机的距离,单位是厘米。

一些接近传感器只能返回远和近两个状态,

因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。

接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。

一些芯片集成了接近传感器和光线传感器两者功能。

 

 

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

9 重力传感器 TYPE_ACCELEROMETER

重力传感器简称GV-sensor,输出重力数据。

在地球上,重力数值为9.8,单位是m/s^2。

坐标系统与加速度传感器相同。

当设备复位时,重力传感器的输出与加速度传感器相同。

 

10 线性加速度传感器 

SENSOR_TYPE_LINEAR_ACCELERATION


线性加速度传感器简称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的数据没有单位,使用的坐标系与加速度相同。

举例:


&lt;%%KEEPWHITESPACE%%&gt;    sensors_event_t.data[0] = x*sin(theta/2)
&lt;%%KEEPWHITESPACE%%&gt;    sensors_event_t.data[1] = y*sin(theta/2)
&lt;%%KEEPWHITESPACE%%&gt;    sensors_event_t.data[2] = z*sin(theta/2)
&lt;%%KEEPWHITESPACE%%&gt;    sensors_event_t.data[3] =   cos(theta/2)

GV、LA和RV的数值没有物理传感器可以直接给出,

需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。
转自:
http://blog.csdn.net/dlutbrucezhang/article/details/9003106

[转载]Android传感器概述(七) - FireOfStar的专栏 - 博客频道 - CSDN.NET

mikel阅读(632)

来源: [转载]Android传感器概述(七) – FireOfStar的专栏 – 博客频道 – CSDN.NET

处理不同的传感器器配置

Android不给设备 指定标准的传感器配置,这就意味着制造商能够把任何他们想要的传感器配置包含到他们的Android设备中。因此,设备能够包含配置广泛的各种传感器。例 如,摩托罗拉的Xoom有一个压力传感器,但是三星的Nexus S却没有。同样Xoom和Nexus S都有陀螺仪,但是HTC的Nexus One却没有。如果你的应用程序依赖特殊类型的传感器,就必须确保传感器存在于设备上,以保证你的应用程序能够成功的运行。有两种方法来确定给定的传感器 是否存在于设备上:

1. 在运行时检测传感器,并根据检测结果来启用或禁用应用程序相关的功能;

2. 使用Google Play来过滤目标设备上是否有指定的传感器配置。

在运行时检测传感器

如果你的应用程序使用的 是一种特殊的传感器类型,但是不想依赖它,你能够使用传感器框架在运行时来检测该传感器,然后决定禁止或启用应用程序对应的功能。例如,一个导航应用程序 可能要使用温度传感器、压力传感器、GPS传感器和地磁场传感器来显示温度、气压、位置和罗盘方位。如果设备没有压力传感器,你能够使用传感器框架在运行 时来检测压力传感器的存在性,然后禁用显示压力的应用程序的UI部分。例如,下列代码用来检查设备上是否有压力传感器:

private SensorManager mSensorManager;

  …

  mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

  if (mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){

  // Success! There’s a pressure sensor.

  }

  else {

  // Failure! No pressure sensor.

  }

使用Google Play来过滤目标指定的传感器配置

如果你要把应用程序发布 到Google Play上,那么在你的应用程序清单文件中能够使用<uses-feature>元素来过滤那些没有相应传感器配置的设 备。<uses-feature>元素有几个硬件描述符,它们会让你基于指定传感器的存在性来过滤应用程序。你能够列出的传感器包括:加速度 度、气压、罗盘(地磁场)、陀螺仪、亮度以及距离。下例应用程序清单,会阻止应用程序安装到没有加速度传感器的设备上:

<uses-feature android:name=”android.hardware.sensor.accelerometer”

              android:required=”true” />

如果你把这个元素添加到应用程序的清单中,在Google Play上,用户只会在有加速度传感器的设备看到你的应用程序。

如果你的应用程序完全依赖一种特定的传感器,那么就应该把描述设置成:android:required=”true”。 如果你的应用程序只有某些功能使用该传感器,而在没有传感器时还要依然运行,你应该在<uses-feature>元素中列出该传感器,但要 把描述符设置为:android:required=”false”。这样有助于即使在没有指定传感器的设备上也能安装你的应用程序。这也是项目管理的最 佳实践,它有助于你跟踪应用程序功能的使用情况。要记住,如果你的应用程序使用一种特殊的传感器,但在没有传感器时还要依然运行,那么应该在运行时检测传 感器,并根据检测的结果来禁止或启用应用程序相应的功能。

[转载]Android传感器---Motion Sensor(三) - FireOfStar的专栏 - 博客频道 - CSDN.NET

mikel阅读(699)

来源: [转载]Android传感器—Motion Sensor(三) – FireOfStar的专栏 – 博客频道 – CSDN.NET

使用重力传感器

重力传感器提供了三个维度的矢量,用来指示重力的方向和重量。下列代码显示了如何获取一个默认的重力传感器的实例:

private SensorManager mSensorManager;

private Sensor mSensor;

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

单位与加速度传感器所使用的单位(m/s2)相同,并且坐标系统也与加速度传感器所使用的坐标系相同。

注意:当设备处于静止状态时,重力传感器的输出应该与加速度传感器的输出相同。

使用陀螺仪

陀螺仪以rad/s(弧度/每秒)为单位围绕设备的X、Y、Z轴来测量速率或旋转角度。下列代码显示了如何获取一个默认的陀螺仪的实例:

private SensorManager mSensorManager;

private Sensor mSensor;

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

该传感器的坐标系统与加速度传感器所使用的坐标系统是相同的。逆时针方向旋转是正值,也就是说,如果设备是逆时针旋转,那么观察者就会看到一些有关以设备原点为中心的正向的X、Y、Z轴的位置。这是标准的正向旋转的数学定义,并且与方向传感器所使用的用于滚动的定义不同。

通常,陀螺仪的输出会被集成到时间上,以便计算在一定时间不长之上旋转角度的变化。例如:

<pre>// Create a constant to convert nanoseconds to seconds.</pre>
<pre>privatestaticfinalfloat NS2S =1.0f/1000000000.0f;</pre>
<pre>privatefinalfloat[] deltaRotationVector =newfloat[4]();</pre>
<pre>privatefloat timestamp;</pre>
<pre></pre>
<pre>publicvoid onSensorChanged(SensorEventevent){</pre>
<pre>  // This timestep's delta rotation to be multiplied by the current rotation</pre>
<pre>  // after computing it from the gyro sample data.</pre>
<pre>  if(timestamp !=0){</pre>
<pre>    finalfloat dT =(event.timestamp - timestamp)* NS2S;</pre>
<pre>    // Axis of the rotation sample, not normalized yet.</pre>
<pre>    float axisX =event.values[0];</pre>
<pre>    float axisY =event.values[1];</pre>
<pre>    float axisZ =event.values[2];</pre>
<pre></pre>
<pre>    // Calculate the angular speed of the sample</pre>
<pre>    float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);</pre>
<pre></pre>
<pre>    // Normalize the rotation vector if it's big enough to get the axis</pre>
<pre>    // (that is, EPSILON should represent your maximum allowable margin of error)</pre>
<pre>    if(omegaMagnitude &gt; EPSILON){</pre>
<pre>      axisX /= omegaMagnitude;</pre>
<pre>      axisY /= omegaMagnitude;</pre>
<pre>      axisZ /= omegaMagnitude;</pre>
<pre>    }</pre>
<pre></pre>
<pre>    // Integrate around this axis with the angular speed by the timestep</pre>
<pre>    // in order to get a delta rotation from this sample over the timestep</pre>
<pre>    // We will convert this axis-angle representation of the delta rotation</pre>
<pre>    // into a quaternion before turning it into the rotation matrix.</pre>
<pre>    float thetaOverTwo = omegaMagnitude * dT /2.0f;</pre>
<pre>    float sinThetaOverTwo = sin(thetaOverTwo);</pre>
<pre>    float cosThetaOverTwo = cos(thetaOverTwo);</pre>
<pre>    deltaRotationVector[0]= sinThetaOverTwo * axisX;</pre>
<pre>    deltaRotationVector[1]= sinThetaOverTwo * axisY;</pre>
<pre>    deltaRotationVector[2]= sinThetaOverTwo * axisZ;</pre>
<pre>    deltaRotationVector[3]= cosThetaOverTwo;</pre>
<pre>  }</pre>
<pre>  timestamp =event.timestamp;</pre>
<pre>  float[] deltaRotationMatrix =newfloat[9];</pre>
<pre>  SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);</pre>
<pre>    // User code should concatenate the delta rotation we computed with the current rotation</pre>
<pre>    // in order to get the updated rotation.</pre>
<pre>    // rotationCurrent = rotationCurrent * deltaRotationMatrix;</pre>
<pre>   }</pre>
<pre>}

标准的陀螺仪提供了原始的旋转数据,并不带有任何过滤或噪音和漂移(偏心)的校正。在实践中,陀螺仪的噪音和漂移会引入错误,因此需要对此进行抵消处理。通常通过监视其他传感器,如重力传感器或加速度传感器来判断漂移(偏心)和噪音。

[转载]Android传感器---Motion Sensor(二) - FireOfStar的专栏 - 博客频道 - CSDN.NET

mikel阅读(695)

来源: [转载]Android传感器—Motion Sensor(二) – FireOfStar的专栏 – 博客频道 – CSDN.NET

Android开源项目的传感器

Android开源项目 (AOSP)提供了三个基于软件的移动传感器:重力传感器、线性加速度传感器和旋转矢量传感器。这三个传感器在Android4.0中被更新,并且都使用 陀螺仪(其它传感器除外)来改善稳定性和性能。如果你想尝试这些传感器,可以通过使用getVendor()方法和getVersion()方法来识别它 们(供应商是:Google Inc;版本号是:3)。通过供应商和版本号来识别这些传感器是必须的,因为Android系统认为这些传感器是第二传感器。例如,如果设备制造商提供了 他们自己的重力传感器,那么AOSP的重力传感器会作为第二重力传感器。这三个传感器都依赖陀螺仪:如果设备上没有陀螺仪,这些传感器不会显示,并不可使 用。

使用加速度传感器

加速度传感器测量作用于设备的加速度,包括重力作用。下列代码显示了如何获得默认的加速度传感器的一个实例:

private SensorManager mSensorManager;

private Sensor mSensor;

  …

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

从概念上,加速度传感器通过测试作用于传感器本身的作用力(Fs),并使用下列公式来判断作用于设备的(Ad)加速度:

Ad = - ∑Fs / mass

但是,重力作用始终会影响下列公式的测量结果:

Ad = -g - ∑F / mass

由于这个原因,当设备位于桌面(并没有加速度)时,加速度传感器的读取结果时g = 9.81 m/s2。同样,当设备自由落体运动时,因为快速向下的加速度是:9.81 m/s2,所以加速度传感器读取的结果是:g = 0 m/s2。因此要测量设备的实际加速度,重力作用的影响必须要从加速度传感器数据中删除。这种问题可以通过高通滤波来实现。相反,低通滤波能够被用来隔离重力作用。下面的示例演示了如何做这件事情:

public void onSensorChanged(SensorEvent event){

  // In this example, alpha is calculated as t / (t + dT),

  // where t is the low-pass filter’s time-constant and

  // dT is the event delivery rate.

  final float alpha = 0.8;

  // Isolate the force of gravity with the low-pass filter.

  gravity[0] = alpha * gravity[0] + (1 – alpha) * event.values[0];

  gravity[1] = alpha * gravity[1] + (1 – alpha) * event.values[1];

  gravity[2] = alpha * gravity[2] + (1 – alpha) * event.values[2];

  // Remove the gravity contribution with the high-pass filter.

  linear_acceleration[0] = event.values[0] – gravity[0];

  linear_acceleration[1] = event.values[1] – gravity[1];

  linear_acceleration[2] = event.values[2] – gravity[2];

}

注意:你能够使用不同的技术来过滤传感器数据。上述的代码示例使用了一个简单的过滤器常量(alpha)来创建一个低通滤波器。该滤波器常量源自时间常量(t),它粗略的表述了过滤器添加给传感器事件的延迟和传感器事件发送频率(dt)。为了演示,示例代码使用一个0.8的alpha值。如果你要使用这种滤波方法,你需要根据实际情况选择不同的alpha值。

加速度传感器使用标准的传感器器坐标系统。在实践中,当设备以它自然的方向被平方在桌面时,下列条件是适用的:

1. 如果在左边推动设备(让它向右移动),那么X轴的加速度值就是正值;

2. 如果在底部推动设备(让它向上移动),那么Y轴的加速度值就是正值;

3. 如果向着天空,用A m/s2 的加速度来推动设备,那么Z轴的加速度值就是A+9.81,它对应了设备的加速度(+A m/s2)减去重力作用(-9.81 m/s2)。

4. 静止的设备的有一个+9.81的加速度值,它对应设备的加速度(0 m/s2减去重力作用,也就是-9.81 m/s2)。

通常,加速度传感器是一种用于监视设备移动的比较好的传感器。几乎每种Android手持设备和平板电脑都有加速度传感器,而且它的能耗要比其他的移动传感器要低10倍。唯一的缺点是,你要实现低通和高通滤波来消除重力作用和减少噪音的影响。

Android SDK提供了一个如何使用加速度传感器的示例程序(Accelerometer Play)

[转载]Android传感器---Motion Sensor(一) - FireOfStar的专栏 - 博客频道 - CSDN.NET

mikel阅读(755)

来源: [转载]Android传感器—Motion Sensor(一) – FireOfStar的专栏 – 博客频道 – CSDN.NET

本文译自:http://developer.android.com/guide/topics/sensors/sensors_motion.html

Android平台提供 了几个能够监视设备移动的传感器。其中的两个是基于硬件的(加速度传感器和陀螺仪),有三个传感器既可以是基于硬件的,也可以是基于软件的(重力传感器、 线性加速度传感器和旋转矢量传感器)。例如,在某些基于软件传感器的设备上会从加速度传感器和磁力仪中提取它们的数据,但是在其他的设备上,它们也可以使 用陀螺仪来提取数据。大多数Android设备都有加速度传感器和陀螺仪。基于软件的传感器的有效性是可变的,因为它们要依赖一个或多个硬件传感器来提取 对应的数据。

运动传感器用于监视设备 的移动,如:倾斜、振动、旋转或摆动。移动通常是直接的用户输入的反映(如,用户在游戏中操作汽车或控制一个球),但也能够是设备所处的物理环境的反映 (如,驾驶汽车时的位置移动)。在第一种场景中,你要相对于设备的参照系或应用程序的参照系来监视设备的移动,在第二种场景中,你要相对于全球参照系来监 视设备的移动。

通常,移动传感器本身并不用于监视设备的位置,但它们能够跟其他传感器一起来使用,例如跟地磁传感器一起来判断设备相对于全球参照系统的的位置(更多信息,请看位置传感器)。

所有的移动传感器的每个 SensorEvent都会返回传感器值的多维数组。例如,一个加速度传感器的传感器事件会返回三个坐标轴方向的加速度力,陀螺仪会返回三个坐标轴方向旋 转速率。这些数据是以float数组的形式跟SensorEvent参数一起被返回的。表1概要介绍了Android平台上可用的移动传感器。

表1.Android平台所支持的移动传感器

传感器

传感器数据

描述

测量单位

TYPE_ACCELEROMETER SensorEvent.values[0] X轴方向的加速力(包括重力) m/s2
SensorEvent.values[1] Y轴方向的加速力(包括重力)
SensorEvent.values[2] Z轴方向的加速力(包括重力)
TYPE_GRAVITY SensorEvent.values[0] X轴方向的重力 m/s2
SensorEvent.values[1] Y轴方向的重力
SensorEvent.values[2] Z轴方向的重力
TYPE_GYROSCOPE SensorEvent.values[0] 绕着X轴的旋转率 rad/s
SensorEvent.values[1]

绕着Y轴的旋转率

SensorEvent.values[2] 绕着Z轴的旋转率
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] X轴方向的加速力(不含重力 m/s2
SensorEvent.values[1] Y轴方向的加速力(不含重力
SensorEvent.values[2] Z轴方向的加速力(不含重力
TYPE_ROTATION_VECTOR SensorEvent.values[0] 沿着X轴的旋转矢量(x* sin(θ/2)). 无单位
SensorEvent.values[1] 沿着Y轴的旋转矢量(y* sin(θ/2)).
SensorEvent.values[2] 沿着Z轴的旋转矢量(z* sin(θ/2)).
SensorEvent.values[3] 旋转矢量的标量部分((cos(θ/2)).1

1标量部分是一个可选值。

对于移动检测和监视,旋 转矢量传感器和重力传感器是使用频率最高的传感器。旋转矢量传感器尤其灵活,可广泛的应用于移动相关的任务,如,检测手势、监视角度变化、监视相对的方向 变化等。例如:如果你正在开发一款使用2维或3维罗盘来增强现实感游戏,或增强相机的稳定性的应用程序,那么旋转矢量传感器是非常理想的选择。在大多场景 中,使用这些传感器比使用加速度传感器和地磁传感器或方向传感器要好。

Android传感器概述(八)

mikel阅读(816)

传感器的坐标系统

通常情况,传感器框架使 用标准的3轴坐标系统来表达数据值。对于大多数传感器,坐标系统是相对与设备被保持在默认方向时的设备的屏幕来定义的(如图1)。当设备被保持在默认方向 时,X轴是水平向右、Y轴是垂直向上、Z轴是指向屏幕面板的外部。在这个系统中,背对着屏幕的Z轴坐标是负值。该坐标系统被下列传感器使用:

1.加速度传感器

2.重力传感器

3.陀螺仪

4.线性加速传感器

5.磁力仪

图1.传感器API使用的坐标系统。

要理解的最重要的一点是,在设备屏幕的方向发生变化时,坐标系统的各坐标轴不会发生变化,也就是说传感器的坐标系统不会因设备的移动而改变。这种行为与OpenGL坐标系统的行为相同。

另外要理解的一点是,应用程序不要假设设备的自然(默认)方向是纵向的。对于很多平板设备的自然方向是横向的。传感器坐标系统总基于设备的自然方向。

最后,如果你的应用程序 要把传感器的数据跟屏幕上的显示相匹配,那么就要使用getRotation()方法来判断屏幕的旋转性,然后使用 remapCoordinateSystem()方法把传感器坐标映射到屏幕的坐标上。即使在你的清单中指定了只是纵向显示,你也要这么做。

注意:有些传感器和方法使用的坐标系统是相对与全球参照系(不是设备参照系)。这些传感器和方法返回的数据是相对与地球的设备运动或设备位置。

 

访问和使用传感器的最佳实践

在你设计你的传感器实现时,要确保遵循以下讨论指南。这些指南是被推荐的使用传感器框架访问传感器和获取传感器数据的最佳实践。

注销传感器监听器

在使用完成传感器或传感器的Activity被挂起时,要确保注销传感器的监听器。如果被注册的传感器监听器和它的Activity被挂起,那么传感器还会继续获取数据,并消耗电池资源直到注销传感器。下列代码显示如何使用onPause()方法来注销监听器:

private SensorManager mSensorManager;

  …

@Override

protected void onPause() {

  super.onPause();

  mSensorManager.unregisterListener(this);

}

不要在模拟器上测试

因为模拟器不能够模拟传感器,所以目前还不能在模拟器上测试传感器代码。你必须在物理设备上测试你的传感器代码。但是传感器模拟器能够模拟传感器的输出。

不要阻塞onSensorChanged()方法

传感器数据能够高频率的 变化,这意味着系统会非常频繁的调用onSensorChanged(SensorEvent)方法。作为最佳实践,在 onSensorChanged(SensorEvent)方法中应该尽可能的少做事,以便不阻塞这个方法。如果应用程序需要进行数据过滤或减少传感器数 据,应该在onSensorChanged(SensorEvent)方法外来执行。

避免使用废弃的方法或传感器类型

有几个方法和常量已经被 废弃,尤其是TYPE_ORIENTATION传感器类型已经被废弃。应该使用getOrientation()方法来获取方向数据。同 样,TYPE_TEMPERATURE传感器类型也已经被废弃了。在运行Android4.0的设备上应用使用 TYPE_AMBIENT_TEMPERATURE传感器类型来替代。

在使用之前要确认传感器

在尝试从传感器上获取数据之前,要始终确认你所使用的传感器在设备上是否存在。不能因为是经常使用的传感器就简单的假设传感器是存在的。不要求设备制造商在他们的设备上提供任何特定的传感器。

仔细选择传感器的延迟

用registerListener()方法注册传感器时,一定要选择一个适应应用程序或应用场景的发送频率。传感器能够以很高的频率来提供数据。允许系统在不浪费系统资源和不使用电池供电的情况下发送额外的数据。