Android传感器应用_指南针(《第一行代码》教程)

1、检测你的手机里有哪些传感器

CheckSensor.java代码架构

1、使用一个ScrollView包裹的TextView把所有的传感器厂家、设备名称、版本、类型编号等打印出来

2、其中为了得到传感器名字,使用了一个静态内部类,这个静态内部类的作用是把(int)Sensor.getType()转化成对应的传感器名字

  这个内部类唯一的方法,getSensorTypeName(int type)就是为了起到这个作用

package com.example.checksensor;

import java.util.List;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textViewOfShowSensorList = (TextView)findViewById(R.id.show_sensor);
SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
StringBuilder sb = new StringBuilder();
sb.append("该手机总共有传感器: "+sensorList.size()+"个\n");
String typeName = "";
for (Sensor i:sensorList) {
Log.d("", String.format("类型编号: %d\n", i.getType()));
}
for (Sensor i:sensorList) {
typeName = SensorTypeName.getSensorTypeName(i.getType());
sb.append(String.format("传感器名字:%s\n", typeName));
sb.append(String.format("设备名称: %s\n", i.getName()));
sb.append(String.format("设备版本: %s\n", i.getVersion()));
sb.append(String.format("设备供应商: %s\n\n", i.getVendor()));
}
textViewOfShowSensorList.setText(sb.toString());
}
//为什么子类才能被形容为static类型,
//新建一个类存储各种传感器类型,这样的好处是,每次新建前面的类,不必花费大量的代价
//存储这些无关紧要的东西
static class SensorTypeName {
static private String []typeName;
//为什么在static里面还要使用关键字,应该已经是static了啊
static {
typeName = new String[20];
typeName[Sensor.TYPE_GRAVITY] = "重力传感器";
typeName[Sensor.TYPE_LIGHT] = "光线传感器";
typeName[Sensor.TYPE_PRESSURE] = "压力传感器";
typeName[Sensor.TYPE_RELATIVE_HUMIDITY] = "TYPE_RELATIVE_HUMIDITY";
typeName[Sensor.TYPE_AMBIENT_TEMPERATURE] = "TYPE_AMBIENT_TEMPERATURE";
typeName[Sensor.TYPE_GYROSCOPE] = "陀螺仪";
typeName[0] = "未知";
typeName[Sensor.TYPE_ACCELEROMETER] = "加速度";
typeName[Sensor.TYPE_MAGNETIC_FIELD] = "磁力";
typeName[Sensor.TYPE_ORIENTATION] = "方向";
typeName[Sensor.TYPE_TEMPERATURE] = "温度";
typeName[Sensor.TYPE_PROXIMITY] = "接近,距离传感器";
typeName[Sensor.TYPE_LINEAR_ACCELERATION] = "线性加速度";
typeName[Sensor.TYPE_ROTATION_VECTOR] = "旋转矢量";
//itsNames[Sensor.TYPE_GAME_ROTATION_VECTOR] = "TYPE_GAME_ROTATION_VECTOR";
typeName[14] = "TYPE_MAGNETIC_FIELD_UNCALIBRATED";
}
public static String getSensorTypeName(int type) {
if (type > 0 && type < typeName.length) {
return typeName[type];
}
return null;
}
}
}

xml文件:

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<TextView android:id="@+id/show_sensor"
android:layout_width="match_parent"
android:layout_height="match_parent">
</TextView>

</LinearLayout>
</ScrollView>

得到结果如下:

2、新建一个指南针实例

StudyCompass.java架构

新建一个SensorManager类以及MagneticSensor、AccelerometerSensor.

通过使用sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_NORMAL);

新建一个SensorEventListener对象listener。重写其中的onSensorChanged(SensorEvent sensorEvent)。

注意点:

其中使用动画效果的时候,需要使用clone()。不然会指向同一个引用。

rotateAnimation.setFillAfter(true);
compassImg.startAnimation(rotateAnimation);

package com.example.studycompass;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;

public class MainActivity extends Activity {

private ImageView compassImg;
private ImageView arrowImg;
private SensorManager sensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
compassImg = (ImageView)findViewById(R.id.compass_img);
arrowImg = (ImageView)findViewById(R.id.arrow_img);
sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
Sensor magneticSensor = (Sensor)sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
Sensor accelerometerSensor = (Sensor)sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onDestroy() {
super.onDestroy();
if (sensorManager != null) {
sensorManager.unregisterListener(listener);
}
}
private SensorEventListener listener = new SensorEventListener() {
float[] magneticArray = new float[3];
float[] accelerometerArray = new float[3];
private float lastRotateDegree;
private float rotateDegree;
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
// TODO Auto-generated method stub
if (sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
/**
* 这里必须使用clone方法不然的话,会指向同一个引用
*/
magneticArray = sensorEvent.values.clone();
} else if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accelerometerArray = sensorEvent.values.clone();
}

float[] rotation = new float[9];
float[] orientation = new float[3];
SensorManager.getRotationMatrix(rotation, null, accelerometerArray, magneticArray);
SensorManager.getOrientation(rotation, orientation);
rotateDegree = -(float)Math.toDegrees(orientation[0]);
if (Math.abs(lastRotateDegree - rotateDegree) > 1) {
RotateAnimation rotateAnimation = new RotateAnimation(lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//使得动画保持在终止结果
rotateAnimation.setFillAfter(true);
compassImg.startAnimation(rotateAnimation);
lastRotateDegree = rotateDegree;
}
}

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

}

};
}

首先使用叠加的两个图片,一个作为指针,另一个作为背景四个方向l

xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ImageView
android:id="@+id/compass_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/compass"/>

<ImageView
android:id="@+id/arrow_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/arrow"/>

</RelativeLayout>

得到结果:

时间: 2024-11-08 20:08:00

Android传感器应用_指南针(《第一行代码》教程)的相关文章

《第一行代码——Android》

<第一行代码--Android>是Android初学者的最佳入门书.全书由浅入深.系统全面地讲解了Android软件开发的方方面面. 第1章带领你搭建Android开发环境,完成你的第一个Android程序. 第2章至第13章完整地讲解了Android开发中的各种基本知识和关键技术,包括四大组件.UI.碎片.广播机制.数据存储.服务.多媒体.网络.定位服务.传感器,以及分布式版本控制系统Git的使用等等.在部分章节会穿插相关技术的高级使用技巧. 第14章和第15章则将带领你编写一个完整的项目,

跟刷 《 Android Studio 单刷第一行代码》 记录坑

跟刷系列   Android Studio 单刷第一行代码 原帖地址http://www.cnblogs.com/DebugLife/p/4355687.html 记录自己的失误,也算是个督促自己了. 1. 坑--去除标题栏 在 Activity 的 onCreate()方法中添加 requestWindowFeature(Window.FEATURE_NO_TITLE);

第一行代码----android篇1.0:活动

   做.NET有4年了,最近由于个人兴趣开始学习Android,网上看了下,郭霖老师的”第一行代码“不错,就以此为教程,写个博客,希望共勉吧!   1:活动是什么及其基本用法    活动是什么,英文名称是“Activity”,专业定义是“一种可以包含用户界面的组件,主要用于和用户进行交互”.在我看来就是.net中的aspx页面,但又不完全是.    如何建立?    如上图所示,点击上图Browse       点击ok,建立活动.活动建立显示的初始页面如下. 到此,建立活动,其实就是一个类,

《第一行代码——Android》封面诞生记

<第一行代码——Android>已经上市快一个月了,目前销售情况还算良好,也是特别感谢众多朋友的支持.其实一本书如果想要卖的好,除了内容必 须要给力之外,封面的设计也是至关重要的,而本书的封面无疑是在充实的内容之外又披上了一层华丽的外衣.作为作者,其实我的任务就是将内容写好而已,其它 所有相关工作都不是由我负责的.本书封面设计的所有细节都是由陈冰先生一手抓起的,之后他在图灵社区上记录了本书封面的诞生过程.在经过他同意的情况下, 我将这篇文章转到我的博客上,也是让感兴趣的朋友们了解一些不为人知的

Android Studio:Unable to add window [email&#160;protected] -- permission denied for this window 第一行代码

学习<第一行代码>的时候,出现的错误. java.lang.RuntimeException: Unable to start receiver com.example.sevenun.littledemo.receiver.ForceOfflineReceiver: android.view.WindowManager$BadTokenException: Unable to add window [email protected] -- permission denied for this

《第一行代码:Android》学习笔记:Activity生命周期

<第一行代码:Android> 郭霖(著) Activity所在的栈为后进先出(Last In First Out)结构. Activity状态 运行状态(S1): 该Activity处于与User交互的状态,即是位于栈顶的Activity. 系统一般不考虑回收该处内存. 暂停状态(S2): Activity不再处于栈顶(Another activity comes in front of the activity),但仍然是可见的. 系统只有在内存极低时才考虑回收内存. 停止状态(S3):

《第一行代码:Android》学习笔记:Activity &amp; Intent

<第一行代码:Android> 郭霖(著) 2.2 Activity的基本用法 隐藏标题栏 在AndroidManifest.xml中配置,作为全局配置,在所有Activity范围内生效 android:theme="@android:style/Theme.NoTitleBar" 在代码中配置,必须在setContentView()前调用该方法,只在当前Activity生效 requestWindowFeature(Window.FEATURE_NO_TITLE); 在s

历时一年,我的著作《第一行代码——Android》火爆预售!

前言 其实我当初决定开始写博客的想法挺简单的,觉得自己搞技术这么多年了,总应该要留下点什么.既然没能写出什么出色的应用,那至少也要留下点文字分享给大家,以指引在我后面的开发者们,毕竟我也从前辈们的博客那里受惠了很多. 受邀 下定决心之后我就开始了我的博客之旅,令我没想到的是,我写的文章竟然非常受大家的欢迎,短时间内就聚集了大量的人气.更令我没想到的事,在我开始写博客不久之后,人民邮电出版社图灵公司的副总编辑陈冰先生就联系上了我,希望我可以写一本关于Android开发技术的书籍! 陈冰,第一次听到

《Android第一行代码》笔记

学习Android开发差不多有两年时间了,期间也做了大大小小的一些项目.近来抽出闲暇想把Android基础强化一下,之前在网上看到了郭霖郭大神的几篇博客,从中受益不少.于是花了近一周时间看完了郭神的一本Android教材--<Android第一行代码>.这本书相比其他教材个人感觉更为基础,内容很实用.看完之后我也有一些收获,学到了一些可以很好的运用到实际中的Android小技巧,下面从中选出我认为很有价值的地方做个记录.同时欢迎各位指正补充~~ 1.查看当前界面处于哪个Activity. 很多