chapter 15 照相功能 - hscc homehscc.cs.nctu.edu.tw/~lincyu/android/chapter15.pdf ·...

15
Chapter 15 照相功能 作者: 林致孙 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首 先會說明如何存取相機,接著會對擴增實境做個簡介,也會提供一個簡單的程式 範例。 15.1 照相功能 讀者可能會問:手機上已經有相機程式了,為什麼還需要另外寫一個相機程式呢? 因為有時候照相可能只是您的應用程式的一部份,例如一個『旅遊心得記錄』應 用程式,使用者去某個景點觀光時,可能想寫些心得並放上景點的照片,最後並 將旅遊心得傳送至自己的部落格,如果能直接於應用程式內使用照相功能,應該 會更方便,因此這一節中我們將學習如何寫出基本的照片功能。請讀者引進光碟 中『\範例程式\Chapter15\CameraBasic』這個專案。 CameraBasic.java 的內容如下: 1 public class CameraBasic extends Activity { 2 3 private SurfaceView sv; 4 private SurfaceHolder sh; 5 private Camera camera; 6 7 private TextView tv; 8 9 private MySensorListener msl; 10 private SensorManager smgr; 11 private List<Sensor> slist; 12 13 @Override 14 public void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 17 requestWindowFeature(Window.FEATURE_NO_TITLE); 18 getWindow().setFlags(WindowManager. 19 LayoutParams.FLAG_FULLSCREEN, 20 WindowManager.LayoutParams. 21 FLAG_FULLSCREEN); 22 setRequestedOrientation(ActivityInfo.

Upload: others

Post on 15-Oct-2020

19 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

Chapter 15 照相功能

作者: 林致孙

照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

先會說明如何存取相機,接著會對擴增實境做個簡介,也會提供一個簡單的程式

範例。

15.1 照相功能

讀者可能會問:手機上已經有相機程式了,為什麼還需要另外寫一個相機程式呢?

因為有時候照相可能只是您的應用程式的一部份,例如一個『旅遊心得記錄』應

用程式,使用者去某個景點觀光時,可能想寫些心得並放上景點的照片,最後並

將旅遊心得傳送至自己的部落格,如果能直接於應用程式內使用照相功能,應該

會更方便,因此這一節中我們將學習如何寫出基本的照片功能。請讀者引進光碟

中『\範例程式\Chapter15\CameraBasic』這個專案。CameraBasic.java的內容如下:

1 public class CameraBasic extends Activity {

2

3 private SurfaceView sv;

4 private SurfaceHolder sh;

5 private Camera camera;

6

7 private TextView tv;

8

9 private MySensorListener msl;

10 private SensorManager smgr;

11 private List<Sensor> slist;

12

13 @Override

14 public void onCreate(Bundle savedInstanceState) {

15 super.onCreate(savedInstanceState);

16

17 requestWindowFeature(Window.FEATURE_NO_TITLE);

18 getWindow().setFlags(WindowManager.

19 LayoutParams.FLAG_FULLSCREEN,

20 WindowManager.LayoutParams.

21 FLAG_FULLSCREEN);

22 setRequestedOrientation(ActivityInfo.

Page 2: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

23 SCREEN_ORIENTATION_LANDSCAPE);

24

25 setContentView(R.layout.takepicture);

26

27 sv = (SurfaceView)findViewById(R.id.sv);

28 sh = sv.getHolder();

29 sh.addCallback(new MySHCallback());

30

31 sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

32

33 smgr = (SensorManager)getSystemService(

34 Context.SENSOR_SERVICE);

35 msl = new MySensorListener();

36

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

38

39 tv = new TextView(this);

40 tv.setTextSize(30);

41 tv.setText("相機是正的");

42

43 LayoutParams lp = new LayoutParams(

44 LayoutParams.FILL_PARENT,

45 LayoutParams.WRAP_CONTENT);

46

47 this.addContentView(tv, lp);

48 }

49

50

51 public boolean onKeyDown (int keyCode, KeyEvent event) {

52 if (keyCode != KeyEvent.KEYCODE_DPAD_CENTER) {

53 return super.onKeyDown(keyCode, event);

54 }

55 if (camera != null) {

56 camera.takePicture(null, null, jpeg);

57 }

58 return true;

59 }

60

Page 3: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

61 private PictureCallback jpeg = new PictureCallback() {

62 public void onPictureTaken(byte[] data, Camera camera) {

63 Bitmap bm = BitmapFactory.

64 decodeByteArray(data, 0, data.length);

65

66 FileOutputStream fos = null;

67 try {

68 File file = new File("/sdcard/picture.jpg");

69 fos = new FileOutputStream(file);

70 BufferedOutputStream bos = new

71 BufferedOutputStream(fos);

72 bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);

73 bos.flush();

74 bos.close();

75 Toast.makeText(CameraBasic.this, "照片已存檔",

76 Toast.LENGTH_SHORT).show();

77 camera.startPreview();

78 }catch (Exception e) {

79 Toast.makeText(CameraBasic.this, e.toString(),

80 Toast.LENGTH_SHORT).show();

81 }

82 }

83 };

84

85 @Override

86 protected void onResume() {

87 super.onResume();

88 if (slist.size() != 0)

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

90 SensorManager.SENSOR_DELAY_UI);

91 }

92

93 @Override

94 protected void onPause() {

95 super.onPause();

96 if (slist.size() != 0)

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

98 }

Page 4: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

99

100 class MySHCallback implements SurfaceHolder.Callback {

101 public void surfaceCreated(SurfaceHolder holder) {

102 camera = Camera.open();

103

104 if (camera == null) {

105 Toast.makeText(CameraBasic.this, "camera is null",

106 Toast.LENGTH_SHORT).show();

107 finish();

108 }

109

110 Camera.Parameters params = camera.getParameters();

111 params.setPictureFormat(PixelFormat.JPEG);

112 params.setPictureSize(480, 320);

113 camera.setParameters(params);

114

115 try {

116 camera.setPreviewDisplay(sh);

117 } catch (Exception e) {

118 Toast.makeText(CameraBasic.this, e.toString(),

119 Toast.LENGTH_SHORT).show();

120 finish();

121 }

122 }

123 public void surfaceDestroyed(SurfaceHolder surfaceholder) {

124 camera.stopPreview();

125 camera.release();

126 }

127 public void surfaceChanged(SurfaceHolder surfaceholder,

128 int format , int w, int h) {

129 camera.startPreview();

130 }

131 }

132

133 class MySensorListener implements SensorEventListener {

134 public void onSensorChanged (SensorEvent event) {

135 if (event.sensor != slist.get(0)) return;

136 if (event.values[0] > 9.3 || event.values[1] > 9.3) {

Page 5: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

137 tv.setText("相機是正的");

138 } else {

139 tv.setText("相機拿歪了喔");

140 }

141 }

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

143 }

144 }

145 }

首先在 17~23行,設定程式會以全螢幕且橫向的方式執行。這個應用程式的版面

設計描述檔內只有一個 SurfaceView,因此這個 SurfaceView會佔滿了整個螢幕,

SurfaceView在第八章有做過介紹了,SurfaceView介面元件可以想成是一塊畫布,

程式開發者可以在上面畫上任何東西,在這個程式中 SurfaceView是用來顯示從

相機取得的畫面。SurfaceView的存取要透過 SurfaceHolder物件,而 SurfaceHolde

類別的 addCallback方法能讓我們設定當 SurfaceView建立、改變與銷毀時該做

的事,因此我們可於 SurfaceView建立時打開相機、啟動預覽功能,而於銷毀時

關掉相機,相關的程式碼請讀者參閱 27~31行及 100~131行,相關的類別則有

Camera [1], SurfaceView [2], SurfaceHolder [3]等。

上述即為照相預覽功能的運作原理,接下來要說明程式的拍攝功能,程式中是設

定按下手機的軌跡球中心會做拍攝的動作,這部份可透過覆寫 Activity類別的

onKeyDown方法來完成[4],程式碼是位於 51~59行,當手機有按鍵被按下時,

這個方法會被呼叫,透過按鍵代碼(KeyCode)可以知道是哪一個鍵被按下(完整的

按鍵代碼可參考 KeyEvent類別的說明文件[5]),我們要處理的是按下軌跡球中心

(KEYCODE_DPAD_CENTER)的事件,所以若按鍵代碼不是

KEYCODE_DPAD_CENTER記得呼叫父類別的 onKeyDown方法來處理那些按

鍵按下的動作(程式第 53行),否則會發現其它按鍵等都無法使用了,而若按下

的是軌跡球中心,會呼叫 Camera類別的 takePicture方法[1]來做拍攝的動作,

takPicture方法有多重定義,程式採用了下面這個定義:

public final void takePicture (Camera.ShutterCallback shutter,

Camera.PictureCallback raw, Camera.PictureCallback jpeg)

第一個參數 shutter可以讓我們設定快門聲,如果我們實作了

Camera.ShutterCallback介面的 onShutter方法,並產生對應的物件填入第一個參

數,則使用者按下拍攝功能後,onShutter方法內的程式碼會被執行,如果我們

不需要快門聲,可以直接填 null。第二個參數 raw可以讓我們設定當原始圖檔準

備好時該做什麼事,如果我們實作了 Camera.PictureCallback介面的

onPictureTaken方法,並產生對應的物件填入第二個參數,則當按下拍攝功能,

Page 6: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

且原始圖檔資料已準備好讀取時,onPictureTaken方法內的程式碼會被執行。第

三個參數 jpeg可以讓我們設定當壓縮圖檔準備好時該做什麼事,如果我們實作

了 Camera.PictureCallback介面的 onPictureTaken方法,並產生對應的物件填入第

三個參數,則當按下拍攝功能,且壓縮圖檔的資料已準備好讀取時,

onPictureTaken方法內的程式碼會被執行,程式在 61~83行利用匿名類別的技巧

產生了一個實作 Camera.PictureCallback介面的匿名類別的物件,並將該物件填

入 takePicture方法當第三個參數,因此當壓縮圖檔可讀取時,62~82行的程式碼

就會被執行,接下來便要對對此段程式碼做解說。首先,利用 BitmapFactor類別

的 decodeByteArray方法產生一個 Bitmap物件,再利用 Bitmap類別的 compress

方法產生檔案,筆者是建議讀者可先利用模仿的技巧修改範例程式,不必要求自

己一開始就要完全瞭解整個程式流程。最後要提醒讀者的是,takePicture方法會

停止預覽功能,因此程式在第 77行重新呼叫 Camera類別的 startPreview方法來

啟動預覽功能。

此程式除了基本的照相功能還附加了一個小功能:檢查手機是否有拿正,判斷方

法是利用加速度感測器,當使用者以直立的方式拿著手機時,Y軸的重力加速度

會接近9.8,而當使用者以橫向的方式拿著手機時,X軸的重力加速度會接近9.8,

程式是於 134~141行的地方做是否有偏斜的判斷。由於感測器不是本章的重點,

筆者就不再對感測器相關的程式碼做討論。然而相關的程式碼中有一個

addContentView方法是我們第一次看到的方法(第 47行),這是 Activity類別的方

法,是在不移除原來的 View的情況下,增加一個 View在上面,先前已經提過

我們利用了 SurfaceView來顯示鏡頭所拍攝到的畫面,我們希望當相機拿歪時,

能夠利用一個 TextView來提醒使用者使否拿歪了,可是又希望 SurfaceView依然

能呈現出來,此時就可利用 addContentView方法將 TextView加到 SurfaceView

上面,執行結果如下圖所示:

Page 7: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

最後要提醒讀者的是,若要使用相機功能,必須於AndroidManifestmxl中做聲明,

如下所示:

<uses-permission android:name="android.permission.CAMERA" />

15.2 擴增實境初探

擴增實境簡單地說是於現實的環境中增加一些虛擬的資訊,例如一個汽車導航系

統可於道路上畫出虛擬的箭頭告訴使用者前進的方向,又或者一個山岳導覽系統

可以在使用者正在觀望的山岳旁告訴使用者該山岳的相關資訊。在早期的擴增實

境系統中頭戴式顯示(Head-mounted Display, HMD)裝置是需要的,此裝置具有外

部影像擷取、定位等功能,並能和電腦所產生的虛擬影像以畫面重疊的方式做結

合。然而隨著手持裝置的普及,利用手持裝置實作擴增實境也開始被人們所討論

[6]。而目前的智慧型手機大都提供了相機及定位功能,因此能讓我們做影像的

擷取及定位,剛好都是實作擴增實境需要的基本功能,本節將示範一個簡單的擴

增實境程式。

請讀者引進光碟中『\範例程式\Chapter15\AsiaAR』這個專案。這個專案是針對

亞洲大學的幾個場所(Spot)做介紹,手機的畫面分成兩個主要部份:

SurfaceView:用來顯示相機鏡頭所拍攝到的畫面。

TextView:用來告知使用者其所面對的是哪一棟建築物,例如當使用者的手

機的鏡頭面對行政大樓時,TextView就會告知使用者這裡是行政大樓。

下圖是一個範例:

這個程式會需要利用到 GPS與方位感測器(Orientation Sensor),原理如下,首先

建築物的經緯度是事先儲存於程式內的,假設行政大樓的經緯度為(XT, YT),接

著透過 GPS,程式可以知道使用者目前的所在經緯度,假設為(XU, YU),透過這

兩個座標,我們就能夠知道行政大樓位於使用者的哪一個方位,因此再透過方位

感測器就可以知道使用者是否正面對著行政大樓,例如行政大樓位於使用者的東

方,且使用者正好面對著東方,那麼程式就會於 TextView顯示『行政大樓』四

Page 8: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

個字。上面的敘述可使用下面的圖來表示,使用者應能更容易理解:

在上圖中,(XT1, YT1)、(XT2, YT2)與(XT3, YT3)是程式預先輸入的,透過 GPS我們

可以獲得(XU, YU),因此便能計算出角度的值,而透過方位感測器,我們可以

得知的值,若與的差小於某一個門檻,程式就會認定使用者是面對著 Target

1。

現在我們可以開始深入程式碼來討論了。AsiaAR.java的內容如下:

1 public class AsiaAR extends Activity {

2

3 private SurfaceView sv;

4 private SurfaceHolder sh;

5 private TextView tv;

6

7 private MyLocationListener mll;

8 private MySensorListener msl;

9 private LocationManager lmgr;

10 private SensorManager smgr;

11 private List<Sensor> slist;

12 private float orientation;

13 private Location user;

Page 9: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

14

15 private Camera camera;

16

17 @Override

18 public void onCreate(Bundle savedInstanceState) {

19 super.onCreate(savedInstanceState);

20

21 requestWindowFeature(Window.FEATURE_NO_TITLE);

22 setRequestedOrientation(

23 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

24

25 setContentView(R.layout.main);

26

27 AsiaSpot.init();

28

29 sv = (SurfaceView)findViewById(R.id.sv);

30 sh = sv.getHolder();

31 sh.addCallback(new MySHCallback());

32

33 sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

34

35 tv = (TextView)findViewById(R.id.tv);

36

37 lmgr = (LocationManager)getSystemService(LOCATION_SERVICE);

38 mll = new MyLocationListener();

39

40 smgr =(SensorManager)

41 getSystemService(Context.SENSOR_SERVICE);

42 msl = new MySensorListener();

43

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

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

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

47 Toast.LENGTH_SHORT).show();

48 finish();

49 }

50 orientation = (float)0.0;

51 }

Page 10: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

52

53 class MySHCallback implements SurfaceHolder.Callback {

54 public void surfaceCreated(SurfaceHolder holder) {

55 camera = Camera.open();

56

57 if (camera == null) {

58 Toast.makeText(AsiaAR.this, "camera is null",

59 Toast.LENGTH_SHORT).show();

60 finish();

61 }

62

63 try {

64 camera.setPreviewDisplay(sh);

65 } catch (Exception e) {

66 Toast.makeText(AsiaAR.this, e.toString(),

67 Toast.LENGTH_SHORT).show();

68 finish();

69 }

70 }

71 public void surfaceDestroyed(SurfaceHolder surfaceholder) {

72 camera.stopPreview();

73 camera.release();

74 }

75 public void surfaceChanged(SurfaceHolder surfaceholder,

76 int format , int w, int h) {

77 camera.startPreview();

78 }

79 }

80

81 @Override

82 protected void onResume() {

83 super.onResume();

84 lmgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,

85 0, 0, mll);

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

87 SensorManager.SENSOR_DELAY_UI);

88 }

89

Page 11: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

90 @Override

91 protected void onPause() {

92 super.onPause();

93 lmgr.removeUpdates(mll);

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

95 }

96

97 private void adjustSpot() {

98 if (user == null) return;

99 Spot spot = AsiaSpot.getFrontSpot(orientation, user);

100 if (spot != null)

101 tv.setText(spot.name);

102 }

103

104 class MySensorListener implements SensorEventListener {

105 public void onSensorChanged (SensorEvent event) {

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

107 orientation = event.values[0]+event.values[2];

108 if (orientation >= 360.0)

109 orientation = orientation - 360.0f;

110 adjustSpot();

111 }

112 }

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

114 }

115 }

116

117 class MyLocationListener implements LocationListener {

118 @Override

119 public void onLocationChanged(Location location) {

120 if (location == null) return;

121

122 user = location;

123 adjustSpot();

124 }

125 @Override

126 public void onProviderDisabled(String provider) {

127 }

Page 12: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

128 @Override

129 public void onProviderEnabled(String provider) {

130 }

131 @Override

132 public void onStatusChanged(String provider, int status,

133 Bundle extras) {

134 }

135 }

136 }

137

138 class AsiaSpot {

139 static ArrayList<Spot> spotlist;

140

141 static void init() {

142 spotlist = new ArrayList<Spot>();

143

144 spotlist.add(new Spot(24.045857, 120.686601,

145 new String("行政大樓")));

146 spotlist.add(new Spot(24.046838, 120.686460,

147 new String("管理大樓")));

148 spotlist.add(new Spot(24.045829, 120.686053,

149 new String("資訊大樓")));

150 spotlist.add(new Spot(24.046429, 120.685561,

151 new String("健康大樓")));

152 spotlist.add(new Spot(24.048395, 120.687341,

153 new String("體育館")));

154 }

155

156 static Spot getFrontSpot(float orientation, Location user) {

157 Location dest = new Location(user);

158 float target;

159

160 float mindist = Float.MAX_VALUE;

161 int spotI = -1;

162

163 for (int i = 0; i < spotlist.size(); i++) {

164 dest.setLatitude(spotlist.get(i).latitude);

165 dest.setLongitude(spotlist.get(i).longitude);

Page 13: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

166 target = user.bearingTo(dest);

167

168 float degree = target-orientation;

169 if (degree < 0.0) degree = degree + 360.0f;

170 if (degree > 180.0) degree = 360.0f - degree;

171

172 if (degree < 10.0) {

173 float dist = user.distanceTo(dest);

174 if (dist < mindist) {

175 mindist = dist;

176 spotI = i;

177 }

178 }

179 }

180

181 if (spotI == -1) return null;

182 return spotlist.get(spotI);

183 }

184 }

185

186 class Spot {

187

188 Spot(double latitude, double longitude, String name) {

189 this.latitude = latitude;

190 this.longitude = longitude;

191 this.name = name;

192 }

193

194 double latitude;

195 double longitude;

196 String name;

197 }

這個 java檔內有三個主要類別:

AsiaAR:這是一個 Activity,其可以說是第十四章『OrientationApp』專案與

前一節『CameraBasic』專案的結合,使用到『CameraBasic』專案的部份,

就是利用預覽功能將鏡頭所拍攝的影像於 SurfaceView上播放。其餘的程式

碼則很類似『OrientationApp』專案,在『OrientationApp』專案中若使用者

Page 14: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

的位置或者方位感測器的值發生變化,我們呼叫自訂的 adjustArrow去調整

箭頭方向,此處則呼叫 adjustSpot去設定 TextView應該顯示的景點名稱,,

adjustSpot方法是實作於 97~102行,程式相當簡單,首先呼叫 getFrontSpot

方法取得使用者前方的最近景點(後面會討論此方法的細節),接著把景點名

稱顯示於 TextView上,getFrontSpot會需要兩個參數,第一個參數 orientation

的值代表使用者面對的方位,會在每次方位感測器的值發生變化時做更新,

第二個參數 user的值代表使用者的位置,會在每次 GPS的值發生變化時做

更新。

Spot:程式碼位於 186~197行,一個 Spot類別的物件就代表一個場所,一

個場所會擁有經緯度的值及一個名稱,188~192行設計了一個建構子,能讓

我們在產生物件時,直接設定場所的經緯度與名稱。

AsiaSpot:程式碼位於 138~184行,這個類別會維護一個 Spot物件的動態陣

列,同時這個類別有兩個方法(Methods):

init方法:初始動態陣列。

getFrontSpot方法:其會傳回使用者正前方的 Spot物件。首先有兩個參

數會被傳入,第一個參數 orientation是藉由方位感測器所獲得的,即前

面示意圖中的值,第二個參數是使用者的位置。程式碼在 163~179會

去一一檢查所有景點,以便得知哪一個景點最接近使用者的正前方,變

數 user代表使用者的位置,變數 dest代表景點的位置,第 166行,程

式利用 Location類別的 bearingTo方法來獲得的值[7],而第 168行,

變數 degree即代表與的差,程式會收集所有 degree小於 10的景點,

再從那些景點中選出一個離使用者最近的景點。如果找不到符合的景點,

程式會回傳 null。

以上即為本程式的主要運作原理,最後還是要提醒讀者記得於應用程式描述檔

(AndroidManifest.xml)中聲明本程式需要精確的位置(亦即要使用 GPS)且需使用

相機。

15.3 摘要

本章我們介紹了 Android平台上相機功能的實作方法,首先介紹了基本的照相功

能,包含了預覽功能與拍照功能。在某些應用程式中,拍照可能只是其中一個必

須的小功能,因此讀者所開發的應用程式中若要使用拍照功能,便可參考此節的

程式。此外,本章也對擴增實境做了一個簡單的介紹,並提供一個簡單的範例告

訴讀者如何於 Android平台上實作出簡易的擴增實境應用。

15.4 作業

Page 15: Chapter 15 照相功能 - HSCC HOMEhscc.cs.nctu.edu.tw/~lincyu/Android/Chapter15.pdf · 照相功能已成為手機的基本功能,智慧型手機當然也一定有照相的功能,本章首

1. 修改『CameraBasic』這個專案,試著加入自己的快門聲。

2. 修改『AsiaAR』這個專案,將景點修改成自己所在附近的景點,並用實機

做測試。

15.5 參考資料

[1] Camera | Android Developers,

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

[2] SurfaceView | Android Developers,

http://developer.android.com/reference/android/view/SurfaceView.html

[3] SurfaceHolder | Android Developers,

http://developer.android.com/reference/android/view/SurfaceHolder.html

[4] Activity | Android Developers,

http://developer.android.com/reference/android/app/Activity.html

[5] KeyEvent | Android Developers,

http://developer.android.com/reference/android/view/KeyEvent.html

[6] Daniel Wagner, Thomas Pintaric, Florian Ledermann, and Dieter Schmalstieg,

“Towards Massively Multi-user Augmented Reality on Handheld Devices”, in proc.

of the third international conference on pervasive computing, 2005.

[7] Location | Android Developers,

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