Android アプリ開発 「MATRIX」

Androidアプリの開発に役立つサンプル集



端末で利用できるセンサーの一覧と詳細を取得してスクロール表示する方法

今回は、端末で利用できるセンサーの一覧を取得して表示してみたいと思います。

スマートフォンに内蔵されているセンサー数は10種類前後と多く、詳細を含めて表示すると画面からはみ出してしまいますので、TextViewをスクロールさせる必要があります。

サンプルコード(MainActivity) 

端末に内蔵されているセンサーの一覧はセンサーマネージャー(SensorManager)が持っていますので、そこからList形式で取り出しレイアウトファイルに配置してあるテキストビュー(TextView)で表示します。 

import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private SensorManager sensorManager;
private TextView list;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//表示に使用するレイアウトをセット
setContentView(R.layout.activity_main);

//センサー一覧表示用のテキストボックスを取得
list = (TextView)findViewById(R.id.sensorlist);

//センサー情報にアクセスするためにセンサーマネージャーを取得
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);

//センサーマネージャーから端末のすべてのセンサー情報をList形式で取得しsensorListに格納
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);

//表示用のString変数strを用意
String str = "";

//センサーリストからセンサーと詳細をすべて取り出してstr変数に格納
for(Sensor s : sensorList) {
str += "センサー名:" + s.getName() + "\n";
str += "メーカー:" + s.getVendor() + "\n";
str += "バージョン:" + s.getVersion() + "\n";
str += "消費電力:" + s.getPower() + "mA\n";
str += "最大レンジ:" + s.getMaximumRange() + "\n";
str += "最小遅延:" + s.getMinDelay() + "μs\n";
str += "最大遅延:" + s.getMaxDelay() + "μs\n";
str += "----------------------------------------" + "\n"; //区切り線
}

//最後にテキストボックスに文字列strをセットして表示
list.setText(str);
}

 

レイアウトコードサンプル(activity_main.xml) 

ポイントはセンサーの一覧を表示するテキストビュー(TextView)をスクロールビューの中に入れることです。こうすることで、テキストビューからはみ出た部分もスクロールして確認することができます。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="sample.sensorlist.MainActivity">

<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/sensorlist"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>

</RelativeLayout

 

実行した結果

端末で利用できるセンサーの一覧が表示されました。画面からはみ出た部分もスクロールすることで確認できます。

f:id:vw-dsg:20171212102616p:plain

 

END

画面の「タッチ中」を検出する方法

今回は画面がタッチされている状態を検出する方法です。

ユーザーの画面操作を検出するには「onTouchEvent」メソッドを利用し、この onTouchEvent が受け取る MotionEvent の種類で処理を振り分けます。

 

サンプルコード①(MainActivity.java

MotionEvent の 「ACTION_DOWN(画面にタッチ)」で、メッセージを「タッチ中!」に変更して、「ACTION_UP(タッチが終わった)」で、メッセージを元に戻しています。 

public class MainActivity extends AppCompatActivity {

private TextView textView1;

//最初に実行されるメソッド
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//レイアウトファイルにあるテキストビューを取得して操作可能にする
textView1 = (TextView)findViewById(R.id.textview1);
//テキストビューに任意の文字を設定
textView1.setText("タッチしてません!");
}

//画面の操作を取得するメソッド
@Override
public boolean onTouchEvent(MotionEvent event) {

//イベントの種類によって処理を振り分ける
switch (event.getAction()) {

//画面にタッチした時の処理
case MotionEvent.ACTION_DOWN: {
textView1.setText("タッチ中!");
break;
}
//画面のタッチが終わった時の処理
case MotionEvent.ACTION_UP: {
textView1.setText("タッチしてません!");
break;
}
}

//returnは最後に書かないとエラーになる
return super.onTouchEvent(event);
}
}

 

サンプルコード②(activity_main.xml

レイアウトは画面の上下左右の中央に「textview1」というIDの TextView を配置しているだけです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.tanronsan.myapplication.MainActivity">

<TextView
android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@android:color/holo_red_dark"
android:padding="10dp"
android:text="textview1"
android:textColor="@android:color/background_light" />
</RelativeLayout>

 

<実行結果> 

画面にタッチしていない時は画面中央のTextViewに「タッチしてません!」を表示。

f:id:vw-dsg:20171201082249p:plain

 

タイトルやOSのメッセージ領域を除いた白い領域をタッチすると「タッチ中!」に変わります。

f:id:vw-dsg:20171201082322p:plain

 

画面のタッチを終えるとメッセージが再び「タッチしてません!」に戻ります。

f:id:vw-dsg:20171201082249p:plain

ユーザーの画面操作はクリックの検出とは違って、リスナーを登録する必要がないので実装が簡単ですね。

END

 

TextToSpeech の speak で音声読み上げに失敗する原因と対処方法

原因は音声データの未インストール

TextToSpeech の speak で音声読み上げに失敗する原因はいろいろあると思いますが、自分がハマったのは、端末に「音声データ」をインストールしていなかったために、ネットワークを無効(オフライン)にしてしまうと音声データがダウンロードできず、音声の読み上げがエラーではなく「無言」になってしまうというトラブル。

てっきり端末に日本語の「音声データ」くらいはインストールされているとばかり思っていたので、この初歩的なミスに何時間もハマってしまった。

もし、アプリを作っていてオフラインで音声読み上げができない場合は、コードのバグはもちろんですが「音声データ」がインストールされているのかを一度確認した方が良いでしょうね。

設定・音声データのインストール方法

1.設定から「システム」を選択。

f:id:vw-dsg:20171116223013j:plain

 

2.「言語と入力」を選択。

f:id:vw-dsg:20171116223045j:plain

 

3.一番下の「詳細設定」を選択。

f:id:vw-dsg:20171116223154j:plain

 

4.一番下の「テキスト読み上げの出力」を選択。

f:id:vw-dsg:20171116223300j:plain

 

5.「優先するエンジン」の右の「ギヤマーク」を選択。

f:id:vw-dsg:20171116223347j:plain

 

6.一番上の「音声データをインストール」を選択。

f:id:vw-dsg:20171116223447j:plain

 

7.言語の一覧から必要なものを選択。

※テスト端末には、日本語(日本)が既にインストールされているので、サンプルとして「広東語(香港)」を選択しています。

f:id:vw-dsg:20171116223535j:plain

 

8.右のダウンロードマークを選択。

f:id:vw-dsg:20171116223739j:plain

 

9.ダウンロードとインストールが終わると「ダウンロードマーク」が「ゴミ箱マーク」に変わる。不要になった場合はこの「ゴミ箱マーク」を選択すれば音声言語データは削除されます。

f:id:vw-dsg:20171116223819j:plain

以上です。

何度確認してもコードは間違っていないのに音声読み上げが実行されない・・・という場合は、一度端末にインストールされている「音声データ」を確認してみると良いかもしれません。

 

END

Android Studio 3.0 にアップデートしてレイアウトXMLのプレビューに不具合がでた場合の対処方法

問題の内容

Android Studio のバージョンを「3.0」にアップデートしたところ、レイアウトXMLファイルのプレビューがグレーだけになってしまい、プレビューしながらの編集できなくなってしまった。※ちなみに、テキスト表示による編集は可能。

f:id:vw-dsg:20171030154740j:plain
プレビューがグレーに塗りつぶされ、中央に「android...ActionBarOverlayLayout」というメッセージがある。

対処方法

調べたところ「styles.xml」を少し変更することでプレビュー表示が復旧することが判明。それで対処して無事レイアウトXMLファイルのプレビュー表示が復活できた。

f:id:vw-dsg:20171030155213j:plain

「styles.xml」ファイルの <style> タグの中を以下のように変更する。具体的には「Theme.AppCompat.Light.DarkActionBar」の頭に「Base.」を付け加える

<変更前>

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

              ↓↓↓↓↓↓↓↓↓

<変更後>

<style name="AppTheme" parent="Base.Theme.AppCompat.Light.DarkActionBar">

以上

f:id:vw-dsg:20171030155838j:plain

もう一度レイアウトファイルを確認してみると、無事レイアウトXMLファイルのプレビューが復活していました。

END

apkファイルが見つからず実行エラーが出る場合の対処方法

開発環境が変わると面倒なことに・・・

アンドロイドアプリを開発するPCが変わったり、プロジェクトが入ったHDDドライブ名が変わったり、プロジェクトを移動したり、Android Studioを再インストールしたりすると、エラーが出てせっかく開発したアプリのRun(テスト実行)ができなくなったりすることがあります。

Android Studioでアプリがテストできなくなる原因

エラーの原因は開発したアプリに新しい開発環境が合っていないからで、不足しているSDKなどがあればそれをダウンロードし、適用してあげさえすれば大抵は復活して、また実行(Run)できるようになるのだが、中には何をどうやっても繰り返し「xxx.apkが見つかりません・・・」といった意味のエラーが出てまったくテスト実行(Run)ができない不良プロジェクトがあったりします。

あきらめる前にこれを実行

そんな時はどうすれば良いのかというと「Build」メニューの中に「Clean Project」「Rebuild Project」という処理があるので、それをダメもとで試してみると良い。

具体的な方法は、最初に「Clean Project」を実行しRun。それでも、apkエラーが出る場合は「Rebuild Project」を実行して、再度Runを実行する。

f:id:vw-dsg:20170827211100g:plain

この2つの処理を試してもダメな場合はひとまずあきらめて、新しい環境で同じプロジェクトをコピー&ペーストで再構築するしかないでしょう。

 

END

タイマーを使ってテキストビューの文字サイズを連続変更してみよう

今回は、タイマーを使ってテキストビューの文字サイズを連続変更する方法です。

画面のレイアウトは「activity_main.xmlに、制御プログラムは「MainActivity.javaに書かれています。 タイマー処理は別スレッドになるためタイマー処理の内部からメインUIスレッドにアクセスるには「Handler」が必要になります。

「Handler」を通さずにテキストビューなどにアクセスるとエラーでプログラムが停止してしまうので注意してください。

サンプルコード(MainActivity.java

public class MainActivity extends Activity {

private Timer timer;
private Tasks tasks;
private Handler handler = new Handler();
private TextView textView;
private int x;
private Button button;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//レイアウトファイルのテキストビューと連結
textView = (TextView)findViewById(R.id.textView);
//レイアウトファイルのボタンと連結
button = (Button)findViewById(R.id.button);

//ボタンにクリックリスナーをセット
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

//テキストサイズを「0」に設定
x = 0;
//テキストビューにテキストサイズをセット
textView.setTextSize(x);
//タイマーを準備
timer = new Timer();
//タイマー処理を準備
tasks = new Tasks();
//スケジュールを設定してタイマーを作動
timer.schedule(tasks, 1000, 10);
}
});
}

//タイマー作動時の処理
public class Tasks extends TimerTask {

@Override
public void run() {
//ハンドラーを経由してメインUIスレッドにアクセスする
handler.post(new Runnable() {
@Override
public void run() {
//テキストサイズに+1
x += 1;
//テキストビューにテキストサイズをセット
textView.setTextSize(x);
//テキストサイズが55を超えたらタイマーを停止
if(x > 55){
timer.cancel();
}
}
});
}
}
}

レイアウトファイル(activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.myhandler.MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="Hello World!"
android:textAllCaps="false"
android:textColor="@color/colorAccent"
android:textSize="0sp"
android:textStyle="bold|italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="スタート"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

結果

「スタート」ボタンを押すと・・・

f:id:vw-dsg:20170607212624p:plain

 

画面の中央から「Hello World!」がズームインで表示されます。

f:id:vw-dsg:20170607212639p:plain

 

END

簡単にタッチパネルのイベントを検出する方法

今回は簡単にタッチパネルのイベントを検出する方法です。タッチイベントの検出はとても簡単で、プログラムの中で「onTouchEvent」メソッドをオーバーライドするだけです。 

サンプルコード(MainActivity.java

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
public boolean onTouchEvent(MotionEvent event) {

//タッチイベントを検出してトーストを表示
Toast.makeText(getBaseContext(), "タッチ検出", Toast.LENGTH_SHORT).show();

return super.onTouchEvent(event);
}
}

 

結果

タッチパネルに触れるとトーストで「タッチ検出」というメッセージが表示されます。

f:id:vw-dsg:20170606210449p:plain

おまけコーナー

MainActivity の extendsを「AppCompatActivity」を「Activity」に変えるとタイトルバーが表示されなくなります。

END