chapter 14 感測器 - hscc homehscc.cs.nctu.edu.tw/~lincyu/android/chapter14.pdf · chapter 14...

18
Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也 讓手機上實作擴增實境變得更容易。本章將介紹應用程式如何讀取手機上的感測 器,同時也會提供範例,讓讀者瞭解方位感測器(Orientation Sensor)與加速度感 測器(Accelerometer Sensor)的應用。 14.1 讀取感測資料 首先我們先學習感測器相關類別的使用方法,請讀者引進光碟中『\範例程式 \Chapter14\SensorList』這個專案,這個專案有兩個 Activity SensorList:繼承了 ListActivity,會列出手機上所的感測器,點選個別的感 測器後,會跳至 SensorReader 讀取所選取的感測器的讀值。 SensorReader:讀取特定感測器的數值。 讓我們先來看 SensorList 這個 Activity,其內容如下所示: 1 public class SensorList extends ListActivity { 2 3 private SensorManager smgr; 4 List<Sensor> slist; 5 6 @Override 7 public void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.main); 10 11 smgr = (SensorManager)getSystemService( 12 Context.SENSOR_SERVICE); 13 slist = smgr.getSensorList(Sensor.TYPE_ALL); 14 ArrayList<String> snlist = new ArrayList<String>(); 15 16 for (int i = 0; i < slist.size(); i++) 17 snlist.add(slist.get(i).getName()); 18 19 ListAdapter adapter = new ArrayAdapter<String>(this, 20 R.layout.list_item, snlist);

Upload: hoangkiet

Post on 22-Mar-2019

238 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

Chapter 14 感測器

作者: 林致孙

手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

讓手機上實作擴增實境變得更容易。本章將介紹應用程式如何讀取手機上的感測

器,同時也會提供範例,讓讀者瞭解方位感測器(Orientation Sensor)與加速度感

測器(Accelerometer Sensor)的應用。

14.1 讀取感測資料

首先我們先學習感測器相關類別的使用方法,請讀者引進光碟中『\範例程式

\Chapter14\SensorList』這個專案,這個專案有兩個 Activity:

SensorList:繼承了 ListActivity,會列出手機上所的感測器,點選個別的感

測器後,會跳至 SensorReader讀取所選取的感測器的讀值。

SensorReader:讀取特定感測器的數值。

讓我們先來看 SensorList這個 Activity,其內容如下所示:

1 public class SensorList extends ListActivity {

2

3 private SensorManager smgr;

4 List<Sensor> slist;

5

6 @Override

7 public void onCreate(Bundle savedInstanceState) {

8 super.onCreate(savedInstanceState);

9 setContentView(R.layout.main);

10

11 smgr = (SensorManager)getSystemService(

12 Context.SENSOR_SERVICE);

13 slist = smgr.getSensorList(Sensor.TYPE_ALL);

14 ArrayList<String> snlist = new ArrayList<String>();

15

16 for (int i = 0; i < slist.size(); i++)

17 snlist.add(slist.get(i).getName());

18

19 ListAdapter adapter = new ArrayAdapter<String>(this,

20 R.layout.list_item, snlist);

Page 2: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

21 setListAdapter(adapter);

22 }

23

24 @Override

25 protected void onListItemClick(ListView l, View v,

26 int position, long id) {

27 super.onListItemClick(l, v, position, id);

28

29 Intent intent = new Intent(this, SensorReader.class);

30 intent.putExtra("KEY_TYPE", slist.get(position).getType());

31 startActivity(intent);

32 }

33 }

首先為了存取手機上的感測器資訊,程式於第 11行先呼叫 getSystemService取

得一個 SensorManager物件[1],第 13行 呼叫 SensorManager物件的 getSensorList

方法取得 Sensor物件[2],參數 Sensor. TYPE_ALL代表所有種類的感測器都要取

得,如果是 Sensor. TYPE_ACCELEROMETER代表只取得加速度感測器的 Sensor

物件(一個手機有可能擁有兩個以上的同種類測器)。第 17行呼叫 Sensor物件的

getName方法取得感測器的名稱,這名稱即要呈現於列表介面元件(ListView)的

『資料』。而當使用者點選某個感測器後,會將感測器的型別(可想成種類)夾帶

在 Intent裡傳送給 SensorReader。下圖是筆者截取實機所得到的執行畫面:

接著討論 SensorReader這個 Activity,其內容如下所示:

1 public class SensorReader extends Activity {

Page 3: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

2

3 private SensorManager smgr;

4 private TextView tv;

5 private Sensor sensor;

6

7 @Override

8 public void onCreate(Bundle savedInstanceState) {

9 super.onCreate(savedInstanceState);

10 setContentView(R.layout.reader);

11

12 tv = (TextView)findViewById(R.id.tv_sresult);

13

14 smgr = (SensorManager)getSystemService(

15 Context.SENSOR_SERVICE);

16 Intent intent = getIntent();

17 int stype = intent.getIntExtra("KEY_TYPE", -1);

18

19 sensor = smgr.getDefaultSensor(stype);

20 }

21

22 @Override

23 protected void onResume() {

24 smgr.registerListener(sListener, sensor,

25 SensorManager.SENSOR_DELAY_UI);

26 super.onResume();

27 }

28

29 @Override

30 protected void onPause() {

31 smgr.unregisterListener(sListener, sensor);

32 super.onPause();

33 }

34

35 private final SensorEventListener sListener =

36 new SensorEventListener() {

37 public void onSensorChanged (SensorEvent event) {

38 if (event.sensor != sensor) return;

39

Page 4: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

40 String str = "";

41

42 switch (sensor.getType()) {

43 case Sensor.TYPE_ACCELEROMETER:

44 str = "Accelerometer Sensor\n";

45 break;

46 case Sensor.TYPE_GYROSCOPE:

47 str = "Gyroscope Sensor\n";

48 break;

49 case Sensor.TYPE_LIGHT:

50 str = "Light Sensor\n";

51 break;

52 case Sensor.TYPE_MAGNETIC_FIELD:

53 str = "Magnetic Field Sensor\n";

54 break;

55 case Sensor.TYPE_ORIENTATION:

56 str = "Orientation Sensor\n";

57 break;

58 case Sensor.TYPE_PRESSURE:

59 str = "Pressure Sensor\n";

60 break;

61 case Sensor.TYPE_PROXIMITY:

62 str = "Proximity Sensor\n";

63 break;

64 case Sensor.TYPE_TEMPERATURE:

65 str = "Temperature Sensor\n";

66 break;

67 }

68

69 for (int i = 0; i < event.values.length; i++)

70 str = str + "values[" + i + "]: " +

71 event.values[i] + "\n";

72

73 str = str + "Accuracy: " + event.accuracy;

74

75 tv.setText(str);

76 }

77 }

Page 5: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

78 public void onAccuracyChanged (Sensor sensor, int accuracy) {

79 }

80 };

81 }

首先在第 14行,同樣使用 getSystemService方法取得 SensorManger物件,接著

利用 getDefaultSensor取得該種類的 Sensor物件,若同種類的感測器數目有兩個

以上,Intent需另外攜帶感測器的名稱,同時應該使用 getSensorList取代

getDefaultSensor。

為了讀取該感測器的資料,我們必須設計一個傾聽者給感測器,傾聽者類別需實

作 SensorEventListener介面[3],程式碼是位於 35~80行,一樣使用了匿名類別的

技巧,有兩個抽象方法需要實作:

onAccuracyChanged:當量測值的精準度改變時,這個方法會被呼叫。

onSensorChanged:當量測值改變時,這個方法會被呼叫。

我們把焦點放在 onSensorChanged方法,onSensorchanged會傳入一個 SensorEvent

物件[4],感測的值可從這個 SensorEvent物件中抓取,首先在 38行,先判斷發

生事件的感測器是否是我們所要量測的感測器,接著 42~67行,我們將感測器的

種類抓出來,並設定之後要用來顯示於 TextView上的字串,字串是告訴使用者

讀取到的感測器是哪一種感測器。

讀取感測器值的程式是寫在 69~71行,感測值會儲存在一個浮點數陣列(float []

values),這個浮點數陣列是 SensorEvent類別的成員變數,不同種類的感測器有

不同的意義[4],以方位感測器(Orientation Sensor)為例,當手機是正著直著拿在

手上時,如下圖所示,values[0]的值意義為:0代表北方、90代表東方、180代

表南方、270代表西方,values[1]是縱向旋轉角,現在一樣正著直著拿著手機,

向外旋轉,垂直向上時值為 90、面朝上平置時值為 0、垂直向下時值為 90、面

朝下平置時值為 180,values[2]是橫向旋轉角,現在一樣正著直著拿著手機,左

或向右旋轉,朝前時值為 0、往右橫放是-90、往左橫放是 90,詳細的定義可參

閱說明文件[4],若對說明文件[4]不是十分瞭解,筆者建議讀者可利用本程式自

行做一些測詴,便能體會出值是如何變化的。

Page 6: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

而以加速度感測器為例的話,values[0]代表手機的 X軸所承受的加速度減去重力

於 X軸所帶來的加速度,以上圖為例,手機的 X軸是指比較窄的那一個邊所型

成的軸,往右較大,values[1]代表手機的 Y軸所承受的加速度減去重力於 Y軸

所帶來的加速度,以上圖為例,手機的 Y軸是指比較長的那一個邊所型成的軸,

往上較大,values[2] 代表手機的 Z軸所承受的加速度減去重力於 Z軸所帶來的

加速度,手機的 Z軸代表著向外或向內,往外較大。當正著直著拿著手機時,

可發現,values[0]與 values[2]會接近於 0,而 Y軸受到了向下的重力加速度(-9.81

公尺/秒平方),因為手機穩穩的拿在手上,因此 Y軸事實上並沒有任何加速度(0

公尺/秒平方),因此 0-(-9.81)=9.81,讀者可發現 values[1]的值會接近 9.81。其它

感測器的讀值就請讀者自行閱讀說明文件。

SensorEvent物件還有一個成員變數為 accuracy(73行),

SENSOR_STATUS_ACCURACY_HIGH(值為 3)代表這個回報的值是很精準的,

SENSOR_STATUS_UNRELIABLE(值為 0)則代表回報的值的精準度是最低的,

請讀者參考說明文件[1]。此外,若在精準度發生變化時,做些處理動做的話,

就要去確實實作 78行的 onAccuracyChanged方法。

現在傾聽者已經設計完成,我們要幫感測器跟其傾聽者連結在一起,當感測器註

冊了傾聽者後,程式就會一直去讀取感測器的資料,因此我們希望只有當程式在

前景執行時才讀取感測器的資料,因此於 onResume方法(第 24行)呼叫

SensorManager類別的 registerListener方法去做註冊,registerListener方法需要三

Page 7: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

個參數,第一個參數傾聽者物件,第二個參數是感測器物件,第三個參數是設定

回報速率,亦即多久回報一次,共有四種速率可選擇:

SENSOR_DELAY_FASTEST、SENSOR_DELAY_GAME、SENSOR_DELAY_UI

與 SENSOR_DELAY_NORMAL。

程式於 onPause方法(第 31行)呼叫 unregisterListener方法取消註冊,如此當程式

進入背景或結束時就不會讀取感測器了。下圖是筆者於實機讀取方位感測器的一

個執行畫面:

14.2 方位感測器的應用

在這一節筆者將示範一個方位感測器的應用,這個應用程式的功能相當簡單,就

是出現一個箭頭指向亞洲大學行政大樓。請讀者引進光碟中『\範例程式

\Chapter14\OrientationApp』這個專案,裡面有兩個 Java原始碼檔案:

OrientationApp.java:這是一個Activity,會讀取GPS以及方位感測器的資料,

藉以判斷箭頭應該呈現的方向。

ArrowView.java:其繼承了 View類別,是一個客製化的 View,主要是用來

顯示箭頭。

先來討論 OrientationApp.java,其內容如下:

1 public class OrientationApp extends Activity {

2

3 private ArrowView av;

4 private MyLocationListener mll;

5 private MySensorListener msl;

Page 8: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

6 private LocationManager lmgr;

7 private SensorManager smgr;

8 private List<Sensor> slist;

9 private float orientation, target;

10

11 @Override

12 public void onCreate(Bundle savedInstanceState) {

13 super.onCreate(savedInstanceState);

14

15 setRequestedOrientation(

16 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

17

18 av = new ArrowView(this);

19 setContentView(av);

20

21 lmgr = (LocationManager)getSystemService(LOCATION_SERVICE);

22 mll = new MyLocationListener();

23

24 smgr = (SensorManager)getSystemService(

25 Context.SENSOR_SERVICE);

26 msl = new MySensorListener();

27

28 slist = smgr.getSensorList(Sensor.TYPE_ORIENTATION);

29 if (slist.size() == 0) {

30 Toast.makeText(this, "No orientation sensor",

31 Toast.LENGTH_SHORT).show();

32 finish();

33 }

34 orientation = (float)0.0;

35 target = (float)0.0;

36 }

37

38 @Override

39 protected void onResume() {

40 super.onResume();

41 lmgr.requestLocationUpdates(

42 LocationManager.GPS_PROVIDER, 0, 0, mll);

43 smgr.registerListener(msl, slist.get(0),

Page 9: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

44 SensorManager.SENSOR_DELAY_UI);

45 }

46

47 @Override

48 protected void onPause() {

49 super.onPause();

50 lmgr.removeUpdates(mll);

51 smgr.unregisterListener(msl, slist.get(0));

52 }

53

54 private void adjustArrow() {

55 float degree = target-orientation;

56 if (degree < 0) degree = degree + 360.0f;

57 av.setDegree(degree);

58 setContentView(av);

59 }

60

61 class MySensorListener implements SensorEventListener {

62 public void onSensorChanged (SensorEvent event) {

63 if (event.sensor == slist.get(0)) {

64 orientation = event.values[0];

65 adjustArrow();

66 }

67 }

68 public void onAccuracyChanged (Sensor sensor, int accuracy) {

69 }

70 }

71

72 class MyLocationListener implements LocationListener {

73 @Override

74 public void onLocationChanged(Location location) {

75 if (location == null)

76 return;

77

78 Location dest = new Location(location);

79 dest.setLatitude(24.045857);

80 dest.setLongitude(120.686681);

81 target = location.bearingTo(dest);

Page 10: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

82 adjustArrow();

83 }

84 @Override

85 public void onProviderDisabled(String provider) {

86 }

87 @Override

88 public void onProviderEnabled(String provider) {

89 }

90 @Override

91 public void onStatusChanged(String provider, int status,

92 Bundle extras) {

93 }

94 }

95 }

這個程式使用到的大部份類別與方法都學過了,因此筆者只告訴讀者這個程式做

了哪幾件事,讓讀者自行去閱讀細節即可,這個程式主要做了幾件事:

設計感測器的傾聽者(61~70行):當發現感測值發生變化後,程式會設定變

數 orientation的值(values[0]),藉此來判斷使用者面對的方位,並呼叫我們

自行定義的 adjustArrow方法來設定箭頭的方向。

設計 GPS的傾聽者(72~94行):當發現使用者所在位置改變時,程式會去計

算目標物(亞洲大學行政大樓)是在使用者的哪個方位,要知道目標物是在使

用者的哪個方位可利用 Location類別 bearingTo方法[5],如果目標物在使用

者的正北方,變數 target的值為 0,如果目標物在使用者的正東方,變數 target

的值為 90,以此類推。接著一樣呼叫自行定義的 adjustArrow方法來設定箭

頭的方向。此處要提醒一下,120.686681及 24.045857是亞洲大學行政大樓

的經緯度值,讀者可換成在自己附近的目標物,以方便程式的測詴。

設定箭頭方向:寫於 adjustArrow方法(54~59行),我們假設手機正上方為 0

度,右側為 90度,則箭頭應該偏轉的角度只要將 target減去 orientation即可

算出。算出偏轉角度後呼叫 ArrowView類別(程式自行定義的,稍後會解說)

的 setDegree方法將角度傳送給 ArrowView物件,並將 ArrowView顯示於畫

面上。

於 onResume方法啟動定位與感測服務(39~45行)。

於 onPause方法停止定位與感測服務(48~52行)。

在這個 OrientationApp.java的程式中,我們沒學過的應該就只有第 15行 Activity

類別的 setRequestedOrientation方法,其可用來設定畫面的呈現方式,是要直著

看(SCREEN_ORIENTATION_PORTRAIT)或是橫著看

Page 11: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

(SCREEN_ORIENTATION_LANDSCAPE),如下圖所示,其它的呈現方式可參考

ActivityInfo類別的說明[6]。

接下來可以開始來討論 ArrowView.java了,其內容如下:

1 public class ArrowView extends View {

2

3 private final float alength = (float)100.0;

4 private final float arrowd = (float)10.0;

5 private final float arroww = (float)5.0;

6

7 float startX, startY, stopX, stopY, degree;

8

9 public ArrowView(Context context) {

10 super(context);

11 startX = (float)160.0;

12 startY = (float)240.0;

13 degree = (float)0.0;

14 }

15

16 protected void setDegree(float degree) {

17 this.degree = degree;

18 }

19

20 @Override

21 protected void onDraw(Canvas canvas) {

Page 12: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

22

23 Paint paint = new Paint();

24

25 float radian = (float)(degree*Math.PI/180.0);

26 stopX = startX + (float)(alength*Math.sin(radian));

27 stopY = startY - (float)(alength*Math.cos(radian));

28 canvas.drawColor(Color.WHITE);

29 canvas.drawLine(startX, startY, stopX, stopY, paint);

30

31 float v3x, v3y, diffx, diffy, leftax, leftay, rightax, rightay;

32

33 v3x = stopX + ((startX-stopX)*arrowd)/alength;

34 v3y = stopY + ((startY-stopY)*arrowd)/alength;

35

36 diffx = (float)Math.abs((arroww*(stopY-startY))/alength);

37 diffy = (float)Math.abs((arroww*(stopX-startX))/alength);

38

39 if ((startX-stopX) < 0.0) {

40 leftay = v3y - diffy;

41 rightay = v3y + diffy;

42 } else {

43 leftay = v3y + diffy;

44 rightay = v3y - diffy;

45 }

46

47 if ((startY-stopY) < 0.0) {

48 leftax = v3x + diffx;

49 rightax = v3x - diffx;

50 } else {

51 leftax = v3x - diffx;

52 rightax = v3x + diffx;

53 }

54 canvas.drawLine(leftax, leftay, stopX, stopY, paint);

55 canvas.drawLine(rightax, rightay, stopX, stopY, paint);

56 }

57 }

ArrowView繼承了 View類別,是一個客製化的 View,我們只要覆寫 onDraw方

Page 13: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

法,便可呈現我們所設計的 View,onDraw會傳進一個畫布(Canvas)物件,我們

只要在畫布上畫出想要呈現的線條、圖形等即可設計出自己的 View,這部份請

讀者自行閱讀相關類別的說明文件[7][8],這裡不做太多的說明,然而筆者還是

附上一張圖,讓讀者能夠更容易瞭解箭頭是如何畫出來的。

最後一件要提醒讀者的事是,別忘了於 AndroidManifest.xml中聲明這個程式需

要得到精確位置資訊,亦即要讀取 GPS資訊。下面是執行畫面,然而要測詴這

個程式是否正確,還是要走出戶外:

14.3 加速度感測器的應用

在這一節筆者將示範一個加速度感測器的應用,這個應用程式的功能用來偵測手

機是否有劇烈晃動。請讀者引進光碟中『\範例程式\Chapter14\AccelerometerApp』

這個專案,裡面只有 AccelerometerApp這個 Activity,其內容如下:

1 public class AccelerometerApp extends Activity {

2

3 float max;

Page 14: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

4 TextView tv;

5 private SensorManager smgr;

6 private List<Sensor> slist;

7 boolean isStarted;

8

9 @Override

10 public void onCreate(Bundle savedInstanceState) {

11 super.onCreate(savedInstanceState);

12

13 setRequestedOrientation(

14 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

15

16 setContentView(R.layout.main);

17 tv = (TextView)findViewById(R.id.tv_max);

18 Button btn_start = (Button)findViewById(R.id.btn_start);

19 btn_start.setOnClickListener(start_l);

20 Button btn_stop = (Button)findViewById(R.id.btn_stop);

21 btn_stop.setOnClickListener(stop_l);

22

23 smgr = (SensorManager)getSystemService(

24 Context.SENSOR_SERVICE);

25

26 slist = smgr.getSensorList(Sensor.TYPE_ACCELEROMETER);

27 if (slist.size() == 0) {

28 Toast.makeText(this, "No accelerometer sensor",

29 Toast.LENGTH_SHORT).show();

30 finish();

31 }

32 isStarted = false;

33 }

34

35 private final SensorEventListener mListener = new

36 SensorEventListener() {

37 public void onSensorChanged (SensorEvent event) {

38 if (event.sensor == slist.get(0)) {

39 if (isStarted == false) return;

40

41 float totalForce = (float)0.0;

Page 15: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

42

43 totalForce += (float)Math.pow(

44 event.values[0]/SensorManager.GRAVITY_EARTH, 2.0);

45 totalForce += (float)Math.pow(

46 event.values[1]/SensorManager.GRAVITY_EARTH, 2.0);

47 totalForce += (float)Math.pow(

48 event.values[2]/SensorManager.GRAVITY_EARTH, 2.0);

49

50 totalForce = (float)Math.sqrt(totalForce);

51

52 if (totalForce > max)

53 max = totalForce;

54 }

55 }

56 public void onAccuracyChanged (Sensor sensor, int accuracy) {

57 }

58 };

59

60 OnClickListener start_l = new OnClickListener() {

61 public void onClick(View v) {

62 if (isStarted == true) return;

63 isStarted = true;

64 max = (float)0.0;

65 smgr.registerListener(mListener, slist.get(0),

66 SensorManager.SENSOR_DELAY_UI);

67 tv.setText("");

68 }

69 };

70

71 OnClickListener stop_l = new OnClickListener() {

72 public void onClick(View v) {

73 if (isStarted == false) return;

74 isStarted = false;

75 smgr.unregisterListener(mListener, slist.get(0));

76 if (max < 2.5) {

77 tv.setText("Fail! Try again!");

78 } else {

79 tv.setText("Max: " + max);

Page 16: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

80 }

81 }

82 };

83 }

這個程式有兩個按鈕:

『Start』按鈕:其傾聽者是實作於 60~69行,其主要功能是啟動感測器的讀

取,並將最大值(max)的值做初始化。

『Stop』按鈕:其傾聽者是實作於 71~82行,其主要功能是停止讀取感測器,

並檢查所測得的最大值(max)是否有大於 2.5,若小於 2.5,會告訴使用者其

沒有盡全力晃動手機,若大於 2.5,則將測得的最大值告訴使用者。

晃動值的計算是寫於感測器的傾聽者內(35~58行),其主要是運用畢氏定理算出

總值(√a2 + b2 + c2),這裡順便跟讀者點出一件事,當手機歪斜著拿著不動時,

若把三軸的加速度值利用畢氏定理算出會得出接近 9.81(重力加速度)的數才對。

讀者按下『Start』按鈕就可開始進行測詴,而按下『Stop』按鈕就可觀看結果,

唯一要注意的是不要不小心把手機甩出去,甚至砸到電視。下面分別是晃動成功

與失敗的執行結果畫面:

14.4 摘要

本章將介紹了感測器的相關應用,首先我們學會了如何獲得手機上的感測器清單,

並瞭解如何讀取感測器的感測值。接著我們分別學習了一個方位感測器

(Orientation Sensor)與一個加速度感測器(Accelerometer Sensor)的應用。手機和感

測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也讓手機上

Page 17: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

實作擴增實境變得更容易。

14.5 作業

1. 寫一個程式來判斷手機的放置方式:平放、水平立放或垂直立放,分別如下

圖所示。請使用加速度感測器。

2. 寫一個程式來判斷手機的放置方式:平放、水平立放或垂直立放。這次請改

用方位感測器。

3. 改寫 14.2的程式,選定兩個不同的目標物,程式會出現兩個箭頭分別指向

兩個目標物。

14.6 參考資料

[1] SensorManager | Android Developers,

http://developer.android.com/reference/android/hardware/SensorManager.html

[2] Sensor | Android Developers,

http://developer.android.com/reference/android/hardware/Sensor.html

[3] SensorEventListener | Android Developers,

http://developer.android.com/reference/android/hardware/SensorEventListener.html

[4] SensorEvent | Android Developers,

http://developer.android.com/reference/android/hardware/SensorEvent.html

[5] Location | Android Developers,

http://developer.android.com/reference/android/location/Location.html

[6] ActivityInfo | Android Developers,

Page 18: Chapter 14 感測器 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter14.pdf · Chapter 14 感測器 作者: 林致孙 手機和感測器的結合,讓手機產生更多的應用,除了應用於遊戲軟體,感測器也

http://developer.android.com/reference/android/content/pm/ActivityInfo.html

[7] Canvas | Android Developers,

http://developer.android.com/reference/android/graphics/Canvas.html

[8] Paint | Android Developers,

http://developer.android.com/reference/android/graphics/Paint.html