Android センサープログラミング入門
概要
本書は、Android端末に搭載されたセンサーを活用したアプリケーション開発について解説する。現代のAndroid開発環境であるAndroid Studioと、推奨されるAPIであるCameraX、FusedLocationProviderClient、SensorManagerを用いて、カメラ、GPS、加速度センサーを活用した実践的なアプリケーション開発を学ぶ。
前提知識: Kotlinプログラミングの基礎、Android開発の基本概念
第1章 Android開発環境
1.1 Android Studio
Android Studioは、Googleが提供するAndroidアプリ開発の公式統合開発環境(IDE)である。IntelliJ IDEAをベースに構築されており、Androidアプリ開発に必要なすべてのツールを統合している。
主な特徴
| 機能 | 説明 |
|---|---|
| コード編集支援 | Kotlin、Java、C++に対応したコード補完と構文チェック |
| ビジュアルレイアウトエディタ | ドラッグ&ドロップでUI設計が可能 |
| Android Emulator | 実機がなくても仮想デバイスでテスト可能 |
| Gradle | ビルド自動化システム |
| Gemini統合 | AIによるコード生成・修正支援(最新版) |
1.2 Android SDK
Android SDK(Software Development Kit)は、Androidアプリ開発に必要なライブラリ、ツール、APIを提供する。
主な構成物
| 構成物 | 説明 |
|---|---|
| Android API | 各バージョンのAndroid向けライブラリ |
| Android Virtual Device (AVD) | エミュレータ。プログラムのテスト時に使用 |
| ADB (Android Debug Bridge) | Android機器との通信・ファイル転送ツール |
| SDK Platform-Tools | デバッグ用ツール群 |
1.3 開発環境のセットアップ
Android Studioのインストール手順は以下の通りである。
- Android Studio のダウンロード: developer.android.com/studio から最新版をダウンロード
- インストールの実行: ウィザードに従いインストール(SDK、エミュレータも同時にインストール可能)
- 初期設定: 初回起動時にSDKコンポーネントが自動的にダウンロードされる
- エミュレータの作成: AVD Managerから仮想デバイスを作成
第2章 Androidプロジェクトの基礎
2.1 プロジェクト構成
Androidプロジェクトは、以下のディレクトリ構造で構成される。
| ディレクトリ・ファイル | 役割 |
|---|---|
app/src/main/java/ または kotlin/ | Kotlinソースコード |
app/src/main/res/layout/ | 画面レイアウトのXMLファイル |
app/src/main/AndroidManifest.xml | アプリの設定、権限の宣言 |
app/build.gradle.kts | 依存関係とビルド設定 |
2.2 アクティビティ
アクティビティ(Activity) とは、Androidアプリの画面を構成する基本要素である。ユーザーインターフェースを提供し、ユーザーとの対話を処理する。各アクティビティはライフサイクルを持ち、onCreate()、onResume()、onPause()などのコールバックメソッドで状態遷移を管理する。
2.3 権限の設定
センサーやカメラなどのハードウェア機能を使用するには、AndroidManifest.xmlに権限を宣言する必要がある。Android 6.0以降では、危険な権限(カメラ、位置情報など)は実行時にユーザーの許可を求める必要がある。
<!-- カメラ使用権限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 位置情報使用権限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
第3章 Android端末のセンサー
3.1 センサーの種類
Android端末には、様々なセンサーが搭載されている。
モーションセンサー
| センサー | 測定内容 | 用途 |
|---|---|---|
| 加速度センサー | X、Y、Z軸方向の加速度 | 端末の動き、傾き、シェイク検出 |
| ジャイロセンサー | X、Y、Z軸周りの回転速度 | 端末の向き、回転運動の検出 |
| 重力センサー | 重力加速度の方向と大きさ | 端末の傾き検出 |
位置センサー
| センサー | 測定内容 | 用途 |
|---|---|---|
| 磁気センサー | 地磁気の強さと方向 | コンパス、方位検出 |
| GPSレシーバ | GPS衛星からの信号 | 現在位置の測位 |
環境センサー
| センサー | 測定内容 | 用途 |
|---|---|---|
| 照度センサー | 周囲の明るさ | 画面輝度の自動調整 |
| 気圧センサー | 大気圧 | 高度測定、天気予測 |
3.2 センサーへのアクセス
Androidでセンサーにアクセスするには、SensorManagerクラスを使用する。
// SensorManagerの取得
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
// 加速度センサーの取得
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
3.3 端末の局所座標系
センサーの計測値は、端末の局所座標系で表される。座標系は端末のデフォルトの向き(多くのスマートフォンでは縦向き)を基準に定義される。
- X軸: 端末の短辺方向(右向きが正)
- Y軸: 端末の長辺方向(上向きが正)
- Z軸: 端末の画面に垂直な方向(画面から手前向きが正)
重要: 画面の向きが変わっても、センサーの座標系は変化しない。これはOpenGLの座標系と同じ振る舞いである。
端末を机の上に水平に置いた場合、重力加速度(約9.8 m/s²)はZ軸方向に作用する。端末を縦に立てると、重力加速度はY軸方向に作用する。
第4章 カメラアプリの開発(CameraX)
4.1 CameraXの概要
CameraXは、Androidでカメラ機能を実装するための推奨ライブラリである。Jetpackの一部として提供され、以下の特徴を持つ。
- ライフサイクル対応: カメラの開始・停止を自動管理
- デバイス互換性: 様々なAndroid端末で一貫した動作
- 簡潔なAPI: 少ないコードでカメラ機能を実装可能
- Android 5.0(API 21)以降に対応
注意: 旧Camera API(android.hardware.Camera)は非推奨である。新規開発ではCameraXまたはCamera2を使用すること。
4.2 依存関係の追加
build.gradle.ktsに以下の依存関係を追加する。
val cameraxVersion = "1.5.0"
implementation("androidx.camera:camera-camera2:$cameraxVersion")
implementation("androidx.camera:camera-lifecycle:$cameraxVersion")
implementation("androidx.camera:camera-view:$cameraxVersion")
4.3 権限の設定
AndroidManifest.xmlにカメラ権限を追加する。
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
android.hardware.camera.anyを指定すると、前面カメラまたは背面カメラのいずれかが搭載されている端末でアプリが動作する。
4.4 カメラプレビューの実装
CameraXでは、ProcessCameraProviderを使用してカメラをライフサイクルにバインドする。
class MainActivity : AppCompatActivity() {
private lateinit var previewView: PreviewView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
previewView = findViewById(R.id.previewView)
startCamera()
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
// プレビューの設定
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
// 使用するカメラの選択(背面カメラ)
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// カメラをライフサイクルにバインド
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, cameraSelector, preview)
}, ContextCompat.getMainExecutor(this))
}
}
前面カメラを使用する場合は、CameraSelector.DEFAULT_FRONT_CAMERAを指定する。
4.5 CameraXのユースケース
CameraXは以下の4つのユースケースを提供する。
| ユースケース | 説明 |
|---|---|
| Preview | カメラ映像のリアルタイム表示 |
| ImageCapture | 静止画の撮影と保存 |
| VideoCapture | 動画の録画 |
| ImageAnalysis | フレームごとの画像解析(機械学習など) |
第5章 位置情報アプリの開発
5.1 Fused Location Providerの概要
Fused Location Provider(FLP)は、Google Play Servicesが提供する位置情報取得APIである。GPS、Wi-Fi、モバイルネットワークを組み合わせて、効率的かつ正確な位置情報を提供する。
FusedLocationProviderClientは、位置情報にアクセスするためのメインエントリーポイントである。
5.2 依存関係の追加
build.gradle.ktsに以下の依存関係を追加する。
implementation("com.google.android.gms:play-services-location:21.3.0")
5.3 権限の設定
AndroidManifest.xmlに位置情報権限を追加する。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
| 権限 | 精度 | 説明 |
|---|---|---|
| ACCESS_FINE_LOCATION | 高精度 | GPS、Wi-Fi、モバイルネットワークを使用 |
| ACCESS_COARSE_LOCATION | 低精度 | Wi-Fi、モバイルネットワークのみ使用(都市レベル) |
5.4 位置情報の取得
class MainActivity : AppCompatActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
}
private fun requestLocationUpdates() {
val locationRequest = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY,
2000L // 更新間隔(ミリ秒)
).build()
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations) {
val latitude = location.latitude // 緯度
val longitude = location.longitude // 経度
// 位置情報を使用した処理
}
}
}
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
}
5.5 取得できるデータ
| プロパティ | 説明 |
|---|---|
latitude | 緯度(度) |
longitude | 経度(度) |
altitude | 高度(メートル) |
accuracy | 精度(メートル) |
time | 測位時刻(1970年1月1日からのミリ秒) |
第6章 加速度センサーによるデータ計測
6.1 加速度センサーの実装
加速度センサーのデータを取得するには、SensorEventListenerインターフェースを実装する。
class MainActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private var accelerometer: Sensor? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
override fun onResume() {
super.onResume()
accelerometer?.let {
sensorManager.registerListener(
this,
it,
SensorManager.SENSOR_DELAY_NORMAL
)
}
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val x = event.values[0] // X軸加速度 [m/s²]
val y = event.values[1] // Y軸加速度 [m/s²]
val z = event.values[2] // Z軸加速度 [m/s²]
// センサーデータを使用した処理
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
// 精度変更時の処理
}
}
6.2 サンプリングレート
registerListenerの第3引数でサンプリングレートを指定する。
| 定数 | 説明 | 用途 |
|---|---|---|
| SENSOR_DELAY_NORMAL | 通常速度(約200ms) | 画面回転検出 |
| SENSOR_DELAY_UI | UI向け(約60ms) | ゲームUI |
| SENSOR_DELAY_GAME | ゲーム向け(約20ms) | ゲーム |
| SENSOR_DELAY_FASTEST | 最速 | 高精度計測 |
6.3 計測結果の解釈
端末を水平に置いた場合
Z軸方向に約9.8 m/s²(1G)の加速度が検出される。これは重力加速度がZ軸方向に作用しているためである。
端末を縦に立てた場合
Y軸方向に約9.8 m/s²の加速度が検出される。重力加速度の方向が変化したことを反映している。
6.4 歩行データの計測実験
加速度センサーを用いた歩行データ計測の実験例を示す。
実験条件
| 項目 | 内容 |
|---|---|
| 使用機材 | Android端末の加速度センサー |
| サンプリング周期 | 200回/秒 |
実験手順(3通り)
| 条件 | 計測時間 |
|---|---|
| 左後ポケットに入れて歩行 | 約460秒 |
| 右手に持って歩行 | 約100秒 |
| 左手に持って歩行 | 約100秒 |
計測データの形式
| 列 | 内容 |
|---|---|
| A列 | 機体番号(例: 015d49021) |
| B列 | タイムスタンプ |
| C列 | X軸加速度 |
| D列 | Y軸加速度 |
| E列 | Z軸加速度 |
加速度センサーを用いて歩行データを計測すると、周期的な加速度変化が観測される。計測条件(端末の保持位置など)によってデータの特徴が異なる。
| 保持位置 | データの特徴 |
|---|---|
| 手に持って歩行 | 腕の振りによる周期的な変動 |
| ポケットに入れて歩行 | 体の上下動による変動パターン |
6.5 3次元グラフによる可視化
3次元グラフ(X、Y、Z軸をプロット)で可視化すると、歩行パターンの特徴を把握できる。計測データの単位はm/s²である。グラフを回転させることで、様々な角度から分布の形状を確認できる。
左手に持った場合と右手に持った場合で、データ点の分布パターンに違いが見られる。これは、歩行時の腕の振りや端末の姿勢の違いを反映している。
第7章 センサー情報の技術仕様
7.1 一般的なセンサーチップの例
Android端末に搭載されるセンサーチップは、複数のセンサー機能を1チップに統合していることが多い。例えば、3軸ジャイロセンサーと3軸加速度センサーを1チップで実現する製品がある。
一般的な仕様例(モーションセンサー)
| 項目 | 仕様 |
|---|---|
| 大きさ | 3〜5mm角程度 |
| ジャイロセンサー計測範囲 | ±250〜±2000°/sec(設定可能) |
| 加速度センサー計測範囲 | ±2g〜±16g(設定可能) |
7.2 GPSレシーバ
GPSレシーバは、GPS衛星からの信号を受信し、現在位置の測位を行う。現代のスマートフォンでは、GPS、GLONASS、Galileo、BeiDouなど複数の衛星測位システムに対応していることが多い。
まとめ
本書では、Android Studioを用いた現代のAndroid開発環境で、カメラ、GPS、加速度センサーを活用したアプリケーション開発を解説した。
重要なポイント
- 開発環境: Android Studioが公式IDEであり、必要なツールがすべて統合されている
- カメラAPI: CameraXが推奨ライブラリであり、旧Camera APIは非推奨
- 位置情報API: FusedLocationProviderClientがGPSとネットワークを統合した効率的な位置情報を提供
- センサーAPI: SensorManagerを通じて各種センサーにアクセス可能
- 権限管理: センサーやカメラの使用には適切な権限の宣言と実行時許可が必要
- 座標系: X軸は右向きが正、Y軸は上向きが正、Z軸は画面から手前向きが正
Android端末には多様なセンサーが搭載されており、これらを活用することで位置情報の取得、動作の検出、カメラを用いた画像処理など、様々なアプリケーションを開発できる。
付録:歴史的背景
本書の内容は、2012年頃にGoogle Nexus 7タブレットとEclipse IDEを用いて作成された教材を基に、現代のAndroid開発環境に合わせて全面的に改訂したものである。
当時の開発環境と現在の比較は以下の通りである。
| 項目 | 2012年頃 | 現在(2024年以降) |
|---|---|---|
| IDE | Eclipse + ADT | Android Studio |
| 言語 | Java | Kotlin(推奨)/ Java |
| カメラAPI | Camera API | CameraX / Camera2 |
| 位置情報API | LocationManager | FusedLocationProviderClient |
| ビルドシステム | Ant | Gradle |
センサーの基本原理(座標系、加速度の計測など)は変わっていないが、APIとツールは大きく進化している。