加速度計の製作

簡単なアプリの製作を体験しましょう。このアプリは、ユーザインタフェースの基本形(テキスト出力+ボタン)しか持たないので、これだけでは面白くありませんが、ロボットやゲームのコントロールなどに使えるモーションセンサの他、いろいろな使い道があります。

*プロジェクトの作成

  1. Android Studio を起動し、Welcome 画面で、"Start a new Android Studio project"を選択
  2. Choose your project 画面で、Empty Activity が選ばれていることを確認して、Nextボタンをクリック
    各種のActivityの雛型が用意されているが、ここでは、Empty Activityという空の画面から作りこむことにする。Activityについては、後で説明。

    Create New Prohect 1

  3. Configure your prohect 画面で、次の図のように設定して、Finishボタンをクリック

    Create New Project 2

  4. しばらく待っていると、MainActivityのViewまたはMainActivityのclass宣言が表示される(初回は、少し時間がかかる)
[参考] アクティビティという言葉がよく出てきますが、Androidのアプリケーションの動作は、アクティビティの状態遷移によって記述されています。アプリの画面を1枚を作るためには、アクティビティクラスを継承したクラス(処理内容や変数のセットと理解しておきましょう)とXMLファイル(画面構成や変数の内容と理解しておきましょう)を用意します。Androidのアプリケーションは、アクティビティの状態遷移(表示、開始、実行、一時停止、再表示など)を繰り返しながら動作しています。そして、各状態に遷移したときの処理と、タップなどのイベント(アプリの操作など)が起こったときの処理を記述するようにプログラムを書いていきます。アクティビティの具体的な状態遷移(またはライフサイクルという)については、WEB等で調べてみてください。後で示すJavaコードの例との対応関係が分かると思います。

*ユーザインタフェースの作成

文字出力とコマンドボタンからなるシンプルなユーザインタフェースを作成します。画面要素をWidgets (またはViewオブジェクト)、画面要素を配置するコンテナをLayout (またはViewGroupオブジェクト)と呼びます。

  1. 左側のProject欄で、app/res/layout/activity_main.xml を探してダブルクリック
    app/res/の下には、画面構成に必要なリソースや文字定数などが保存されます。
  2. View欄上部の-/+ボタンで、表示サイズを見やすい大きさに設定
  3. 中央に小さくHello Worldが表示されているので、マウスで選択し、DELキーで削除
  4. View欄上部のツールバーの青四角アイコンで、表示モードを Design に設定
  5. View欄上側のツールバーの目玉アイコンで、Show Layout Decorations に設定
  6. 動作テストに使用する機種の画面サイズとテーマ(配色など)を設定する
    ここでは、機種 = Nexus6P(5.7インチ), テーマ = Holo.Light を使用しています。(注:この設定は、Android Studioの表示設定であり、アプリの表示には関係ありません。)

    Layout 1

  7. ウィジェットの作成
    1. Component Tree欄で、ConstraintLayoutのみが表示されていることを確認
      この状態で、ConstraintLayoutのレイアウトが画面全体に配置されているはず。ConstraintLayout内では、親レイアウトや同じレイアウト内のウィジェット間の相対位置でウィジェット表示場所を定義することができるので、階層的なレイアウト構造を作成せずに簡単に配置ができます。
    2. Parette欄から TextView を View画面上にドラッグして4個配置
    3. さらに、Button をView画面上にドラッグして1個配置

      View

  8. ウィジェットのレイアウト設定
    1. 配置したTextViewとButtonを、それぞれクリックし、Attributes欄で id, Layout, layout_width を下記の図のように設定する。
      ただし、Buttonは、layout_width = match_constraint を選んでください。各idは、プログラムから参照する際に使用するので、分かりやすい名称に変更しておきます。また、位置の設定のため、水色+マークをクリックして、値を入力します。位置の設定をやり直すときは、グレーの丸の部分をクリックします。

      左上TextView右上TextView
      LayoutLayout
      左中TextView右中TextView
      LayoutLayout
      下段Button
      Layout

  9. ウィジェットの属性設定
    1. 配置したTextViewなどの5つのWidgetsに対して、Attributes欄のCommon AttributesまたはAll Attributesの値を、それぞれ次のように設定する
      (注)onClick は、ボタンをクリックしたときに実行されるメソッド名を指定しています。ただし、Attributes欄でonClickを設定すると、プログラムのコードが読みにくくなるので、コード中で、onClickに対するイベントハンドラーを設定するのが普通です。

      左上TextView右上TextView左中TextView右中TextView下段Button
      idtextPeaktextPAcceltextCurrenttextCAccelReset
      textPeak Acceleration (m/s2) X:\nY:\nZ:0.0\n0.0\n0.0Current Acceleration (m/s2) X:\nY:\nZ:0.0\n0.0\n0.0RESET
      textSize18sp18sp18sp18sp18sp
      textStyle変更なしBold変更なしBold変更なし
      onClick変更なし変更なし変更なし変更なしpeakReset
      gravityrightrightrightright変更なし
      textColor変更なし#ff00ffff変更なし#ff00ffff変更なし
      background変更なし#ff000000変更なし#ff000000変更なし

      View

    2. Component Tree欄下のTextタブをクリックすると、View画面に対応するXML(Extensible Markup Language)のコードが表示される。XMLに慣れている人は、こちらのほうが編集しやすいかもしれない。ViewのProperties設定により、View画面上に表示されなくなったボタンやテキストも、XMLのほうで編集することができる。

*コードの記述

Javaの書き方は、プログラミングの演習科目で学ぶことにして、とりあえず下記の内容をコピペして作成しましょう。基本的には、アクティビティの変化、ユーザの操作、デバイスの状態変化といったイベントごとに、実行させる処理内容(メソッド)を記述していきます。

  1. 左側のProject欄で、app/java/jp.merl.accel/MainActiviry をダブルクリックすると、ソースコードが表示される
  2. 表示されたJavaのコードを全て消して、下記のリストをコピペする。
    package jp.merl.accel;
    
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.TextView;
    
    import java.text.DecimalFormat;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity implements SensorEventListener {
    
        private SensorManager mSensorManager;
        private Sensor mAccelerometer;
        private float[] cValues = new float[3];
        private float[] pValues = new float[3];
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
            List list = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
            if (list.size()>0) {
                mAccelerometer = (Sensor) list.get(0);
            }
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
    
        @Override
        public void onResume() {
            super.onResume();
            if (mAccelerometer != null) {
                mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
            }
        }
    
        public void onStop() {
            super.onStop();
            mSensorManager.unregisterListener(this);
        }
    
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
    
        }
    
        public void onSensorChanged(SensorEvent event) {
            if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
                return;
            }
    
            cValues[0] = event.values[0];
            cValues[1] = event.values[1];
            cValues[2] = event.values[2];
    
            for (int i=0; i<3; i++) {
                if(pValues[i] < cValues[i]) {
                    pValues[i] = cValues[i];
                }
            }
    
            DecimalFormat df = new DecimalFormat("###.####");
    
            TextView textCAccel = findViewById(R.id.textCAccel);
            TextView textPAccel = findViewById(R.id.textPAccel);
            StringBuffer cBuf;
            StringBuffer pBuf;
            cBuf = new StringBuffer();
            pBuf = new StringBuffer();
    
            cBuf.append(df.format(cValues[0])).append("\n").append(df.format(cValues[1])).append("\n").append(df.format(cValues[2]));
            pBuf.append(df.format(pValues[0])).append("\n").append(df.format(pValues[1])).append("\n").append(df.format(pValues[2]));
    
            textCAccel.setText(cBuf.toString());
            textPAccel.setText(pBuf.toString());
        }
    
        public void peakReset(View view) {
            TextView textPAccel;
            textPAccel = findViewById(R.id.textPAccel);
            textPAccel.setText("0.0\n0.0\n0.0");
            pValues[0] = 0;
            pValues[1] = 0;
            pValues[2] = 0;
        }
    
    }
    
以下に、上記Javaコードの内容を、おおまかに解説しておきますので、プログラムの流れと雰囲気を掴んでください。

ここでは、全部コピペをしましたが、自分でコードを編集する際に便利な補完機能を紹介します。
  1. CTRL + SPACEキーによりコードの補完ができる
  2. 文法エラーがあると、エディタの右端に褐色の短いラインが表示される
  3. エラーとなっている行の赤文字ににカーソルを置き、ALT + Enterキーを押すと、必要なクラスがインポートされエラーが消えることが多い
    クラスの機能を使用するためには、パッケージ(クラスのカテゴリ)とクラス名を指定する必要がありますが、いちいち調べて書くのは面倒なので、使用するパッケージとクラスの名前を最初に import 文で指定しておきます。import文の左に表示されている+マークをクリックして展開して、現在何がインポートされているか確認できます。今回は、全部まとめてコピペしてしまいました。

*ADB(Android Debug Bridge)による動作確認とデバッグ

PCにテスト用のスマートフォン実機をUSB接続します。実機を持っていない場合は、エミュ(Emulator = PC上でスマホの動作を模擬する機能)を使用することもできますが、非常に動作が重く、通常は、センサや通信等の機能が使えないので、実機の使用をお勧めします。まず、実機を使ってデバッグを行うために、実機の開発者向けオプション設定を行います。

  1. Androidの設定メニューから、 [端末情報] - [ソフトウエア情報] (または、[システム])を選び、「ビルド番号」を7回タップすると、[開発者向けオプション]というメニューが、設定画面に追加される
    Androidのバージョンによっては、最初から[開発者向けオプション]がメニューに出ているので、上記の操作は必要ない。
    Androidによっては、「ビルド番号」が表示される階層が異なることがある。
  2. 設定画面から、[開発者向けオプション]に入り、USBデバッグ = ON に設定する
  3. 設定画面から、[セキュリティ]に入り、提供元不明のアプリ = ON に設定する
  4. USBケーブルでPCに接続するとPCにUSBドライバがインストールされる
    実機端末が、USBデバッグを許可するか聞いてきた場合はOKする。
    ドライバがインストールされると、PCのデバイスマネージャーに、AndroidデバイスまたはADB Interfaceが表示される。「不明なデバイス」となった場合は、Android Studioユーザガイドなどで適切なドライバーを検索して、インストールを行う。
Android Studioで作成したアプリケーションを走らせ、実機上で動作確認を行います。
  1. ツールバーの Run 'app' ボタン(下図のStart)をクリック
  2. Select Development Targetウインドウが表示されるので、使用するAndroid端末を選んでを選んで、OKボタンをクリック
  3. アプリにエラーがなければ、実機にアプリケーションが転送され、実機上でアプリケーションが起動するので、動作が正しいか確認する
    うまく動作した場合は、実機端末に転送されたアプリケーションを、アプリ一覧から直接起動できる。

    Run 'app'

  4. うまく動作しない場合は、activity_main.xmlとMainActivity.java に文法エラーがないかよく確認する
  5. エラーが見つからない場合は、Android Studioの一番下の方にある Android Monitorボタンをクリックして、下の方に現れる logcat 画面で実行時ログを調べる
    ログ(変数値などの観察)やブレークポイント(プログラムの一旦停止)の設定方法は、3年生の自主課題研究などを参考にしてください。

    LogCat

*スマホへのインストール

実は、ADBを実行する際に、アプリがスマホにインストールされています。アプリ一覧画面でAccelを探してみてください。まだ、アイコンを設定していないので、デフォルトのBugdroid(ドロイド君)アイコンになっているはずです。

Test on Nexus7
写真は、Nexus7上で動作確認中。強く振ると、Peak Accelerationの値が大きくなりますが、あまり強く振って、スマホが飛んでいったりしないよう注意。


環境設定[1/2]

お問い合わせはこちらまで: kitagawa@is.t.kanazawa-u.ac.jp

© Kanazawa Univ., 2013