端末でのデバッグ
Androidの実機(Nexus 5)が届いたのでUSBで接続してアプリのインストールをしてみようと思う。
パソコンとAndroid端末の接続をして、Androidの設定から開発者向けオプション、またはアプリケーション→開発という項目がある、と書籍にはあるが、僕の端末にはない。ググると、バージョン4.2以降は、開発者向けオプションを表示させるのに一手間あるようだ。Nexus 5の場合は、設定→端末情報で表示されるビルド番号を7回タップする。
表示された開発者向けオプションから、USBデバッグをチェックして、端末とPCをUSBで接続してみる。デバイスを微妙に認識していないようだったので、「Google USB Driver | Android Developers」からドライバをダウンロードする。解凍したフォルダをドライバを手動で指定してインストール。
コマンドプロンプトからadb devices
で端末情報を表示させようとしたところ、そもそもパスが通ってなかったようでユーザー変数(変数名をANDROID_PATHとしていた)のPATHに追加したら通った。
ソフトウェア・アップデートかけて、Eclipseのプロジェクトファイルからデバックの構成で、逐次デバックの端末を選ぶように設定して、デバッグを実行すると、端末側で表示された。Nexus 5解像度高い。昨日書いたタイリングするコードを表示させてみた。実機でデバッグできるとだいぶモチベーション高まる。
イベントの利用
キーイベント
package com.example.keyex;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class KeyEx extends Activity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new KeyExView(this));
}
}
package com.example.keyex;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.KeyEvent;
import android.view.View;
public class KeyExView extends View {
private int keyCode = -999;
public KeyExView(Context context) {
super(context);
setBackgroundColor(Color.rgb(255, 255, 255));
// フォーカスの指定
setFocusable(true);
setFocusableInTouchMode(true);
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(24);
String str = "";
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_UP:
str = "DPAD_UP";
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
str = "DPAD_DOWN";
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
str = "DPAD_LEFT";
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
str = "DPAD_RIGHT";
break;
case KeyEvent.KEYCODE_BACK:
str = "DPAD_BACK";
break;
case KeyEvent.KEYCODE_MENU:
str = "DPAD_MENU";
break;
default:
System.out.println("Other");
}
canvas.drawText("KeyCode > "+keyCode + " : " + str, 0, 40, paint);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
this.keyCode = keyCode;
invalidate();
return true;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
this.keyCode = keyCode;
invalidate();
return true;
}
}
ボタンを押下すると、対応したキーコードが表示される。正直地味。
タッチイベント
package org.cenkhor.touchex;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class TouchEx extends Activity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new TouchExView(this));
}
}
package org.cenkhor.touchex;
import java.util.HashMap;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.View;
public class TouchExView extends View {
private HashMap<String, PointF> points = new HashMap<String, PointF>();
public TouchExView(Context context) {
super(context);
setBackgroundColor(Color.rgb(255, 255, 255));
setFocusable(true);
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(32);
canvas.drawText("TouchEx > ", 0, 40, paint);
// オブジェクト型の配列に、ポイントF(ポイントをX,Yで持つ)のフロート型)のキーを配列で取得
Object[] keys = points.keySet().toArray();
for (int i = 0; i < keys.length; i++) {
// pointsからキーで値(個々のポイント)を取得
PointF point = (PointF) points.get(keys[i]);
canvas.drawText("[ " + i + " ] Point X : " + (int) point.x + " Y : "
+ (int) point.y, 0, 80 + 40 * i, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// アクション種別と、タッチ数を取得
int action = event.getAction();
int count = event.getPointerCount();
// アクションインデックスとポインタIDの取得
int index = event.getActionIndex();
int pointerID = event.getPointerId(index);
// タッチ位置の取得
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
points.put(" " + pointerID, new PointF(event.getX(), event.getY()));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
points.remove(" " + pointerID);
break;
case MotionEvent.ACTION_MOVE:
for (int i = 0; i < count; i++) {
PointF point = points.get(" " + event.getPointerId(i));
point.x = event.getX(i);
point.y = event.getY(i);
}
break;
}
// 再描画
invalidate();
return true;
}
}
マルチタッチでポイントの座標が取得できる。HashMapを実例で使ったのが初めてだったので結構新鮮だった。
ジェスチャーイベント
package org.cenkhor.gestureex;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class GestureEx extends Activity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GestureExView(this));
}
}
package org.cenkhor.gestureex;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class GestureExView extends View implements
GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
private ArrayList<String> info;
private GestureDetector gestureDetector;
public GestureExView(Context context) {
super(context);
setBackgroundColor(Color.rgb(122, 122, 122));
setFocusable(true);
info = new ArrayList<String>();
info.add("GestureEx : ");
gestureDetector = new GestureDetector(context, this);
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(32);
for (int i = 0; i < info.size(); i++) {
canvas.drawText((String) info.get(i), 0, 32 * i + 32, paint);
}
}
private void addInfo(String str) {
info.add(0, str);
while (info.size() > (int)(getHeight()/32))
info.remove(info.size() - 1);
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
addInfo("SingleTap");
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
addInfo("DoubleTap");
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
addInfo("DoubleTapEvent");
return false;
}
@Override
public boolean onDown(MotionEvent e) {
addInfo("Down");
return false;
}
@Override
public void onShowPress(MotionEvent e) {
addInfo("ShowPress");
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
addInfo("Up");
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
addInfo("Scroll (" + (int) distanceX + " , " + (int) distanceY + ")");
return false;
}
@Override
public void onLongPress(MotionEvent e) {
addInfo("LongPress");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
addInfo("Fling (" + (int) velocityX + " , " + (int) velocityY + ")");
return false;
}
}
GestureExViewクラスは、GestureDetector.OnGestureListenerとGestureDetector.OnDoubleTapListenerインターフェイスを実装してる(からメソッドがたくさんある)。こういうのIDEなかったら死ぬ気がする。ArrayListにデータをどんどん詰めていってDrawTextで表示させつつ、画面から溢れたら、リストの長さ以上のものはリムーブするというのは実装手法として使いそうだなーと思った。size,get,removeなどメソッド名にはなかなか慣れなくて、毎回補完のリスト眺めてる。
サーフェイスビューの利用まで進めたけど、きりがいいのでここまで。
Android Nexus 5 Wi-Fiのセットアップ
家のWi-Fiに接続しようとしたら、繋がらない。無線LAN親機側で、チャンネルの設定が必要みたいだ。これは出かける時間になってしまったので、帰宅して検証する。出先でテザリングしてソフトウェアアップデートかけた。