Androidアプリ
2010 年 8 月 16 日
Androidアプリを作ってみました。
Androidアプリも相当数出そろってきましたね。
なので、今更なのですが。。。夏休みの工作です。
サントリーオールド空瓶の謎のボトル人形みたいなもんです。
Java経験少ない僕でも数時間で出来たのでJavaをずっとやっている方や、詳しい方は
あっという間でしょう。
せっかくなので携帯端末の位置情報センサーを使って
「コンパス(方位磁石)」作ってみました。
Sensor.TYPE_ORIENTATION・・・傾きセンサーを使います。
・・・ですが、「Sensor.TYPE_ORIENTATION」は何時からか「非推奨定数」となっていました。
Android2.2からはgetOrientationメソッドが推奨ということです。
画像を用意してクルクルさせるのも良かったのですが、
それじゃあんまりなので、もっとプログラミングっぽく。
コンパスの針も計算して描画させましょう。
Eclipseのエミュレータではセンサーイベントが取れないのか期待した動作をしませんので
実機で試しましょう。
因みに実機はHTC Desire X06HTで動かしてみました。
少しだけ解説。
・用意するクラスは2個だけ(CompassActivity.java、MainView.java)
・Activityを継承しているクラスにinterface、SensorEventListenerを実装。
・センサーチェンジイベント(onSensorChanged)が発生する毎に描画(MainView)に行きます。
・MainViewはViewを継承しましょう。
・傾きセンサーで取得された角度を基に座標を求め、針を描画(onDraw)します。
・針を描画では三角関数を使う。三角関数はJavaのMath.cos、Math.sinがあるのでそこにラジアンを渡してあげましょう。
あまり作りこんでいませんが、Androidアプリ作り始めに丁度良かったです。
参考サイト
Android開発の基本、公式サイト この辺読めばだいたい解ります。後はググれば情報満載です。
・Android
アイコンデザインガイドなど
・Icon Design Guidelines
ソースコード(CompassActivity.java)
package net.studiofun.Compass;
import java.util.List;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
public class CompassActivity extends Activity implements SensorEventListener {
/** Called when the activity is first created. */
private SensorManager manager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
manager = (SensorManager) getSystemService(SENSOR_SERVICE);
List sensors = manager.getSensorList(Sensor.TYPE_ORIENTATION);
if (sensors.size() > 0) {
Sensor sensor = sensors.get(0);
manager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_FASTEST);
}
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
@Override
public void onSensorChanged(SensorEvent event) {
setContentView(new MainView(getApplication(), event.values[0]));
}
@Override
protected void onPause() {
// TODO 自動生成されたメソッド・スタブ
super.onPause();
// センサーマネージャのリスナ登録破棄
manager.unregisterListener(this);
}
/**
* オプションメニューをCreateする
*/
/** メニューID */
private final int MENU_ID1 = Menu.FIRST;
private final int MENU_ID2 = Menu.FIRST + 1;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// メニューアイテムを追加
MenuItem item0 = menu.add(0, MENU_ID1, 0, R.string.menu_end);
// 追加したメニューアイテムのアイコンを設定
item0.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
return true;
}
/**
* オプションメニューがクリックされたときの動作
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ID1:
// 各ボタンが押されたときの処理を記述
Toast toast = Toast
.makeText(this, "Compass終了", Toast.LENGTH_SHORT);
toast.show();
finish();
return true;
}
return true;
}
}
ソースコード(MainView.java)
package net.studiofun.Compass;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class MainView extends View {
private float position;
// 画面中心の位置のxy座標
private int centerX = 0;
private int centerY = 0;
public MainView(Context context,float posival) {
super(context);
// TODO 自動生成されたコンストラクター・スタブ
position=posival;
}
public MainView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO 自動生成されたコンストラクター・スタブ
}
public MainView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO 自動生成されたコンストラクター・スタブ
}
/**
* 描画処理 針の描画
*/
protected void onDraw(Canvas canvas) {
//センター
float x0=centerX;
float y0=centerY;
// 背景色を設定
canvas.drawColor(Color.argb(255, 100, 100, 100));
//Compass台 円描画
Paint paint = new Paint();
paint.setColor(Color.argb(200, 87, 87, 87));
paint.setAntiAlias(true);
canvas.drawCircle(x0, y0, 120, paint);
//線描画色設定(北用赤線)
paint.setColor(Color.argb(255, 214, 10, 10));
//π
Double pai=3.141516;
// 1度 = (π/180) ラジアン「度数 x π / 180」
double rad = (90 - position) / 180 * pai;//0が上(北)なので90をマイナス
float needlesize =100;
float x1 =(float) Math.cos(rad) * needlesize ;
float y1 =(float)Math.sin(rad) * needlesize ;
//北向き線
canvas.drawLine(x0, y0, x0-x1, y0-y1, paint);
canvas.drawText("N", x0-x1, y0-y1, paint);
//南向き線
paint.setColor(Color.argb(255, 255, 255, 255));
canvas.drawLine(x0, y0, x0+x1, y0+y1, paint);
canvas.drawText("S", x0+x1, y0+y1, paint);
//東向き線
rad = (position) / 180 * pai;//東なので+なし
x1 =(float) Math.cos(rad) * needlesize ;
y1 =(float)Math.sin(rad) * needlesize ;
paint.setColor(Color.argb(255, 255, 255, 255));
canvas.drawLine(x0, y0, x0+x1, y0-y1, paint);
canvas.drawText("E", x0+x1, y0-y1, paint);
//西向き線
paint.setColor(Color.argb(255, 255, 255, 255));
canvas.drawLine(x0, y0, x0-x1, y0+y1, paint);
canvas.drawText("W", x0-x1, y0+y1, paint);
//現時点値描画
String str=String.valueOf(position);
canvas.drawText(str, centerX-10, centerY-133, paint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 画面の幅の中央のxy座標取得。
centerX = w / 2;
centerY = h / 2;
}
}

