AndroidでGoogle Maps APIを使って地図をヘディングアップ表示する方法.電子コンパスに合わせて地図が回転するというものです.(android sdk 1.5)
MainAct.java
import
java.util.List;
import
com.google.android.maps.MapActivity;
import
android.content.Context;
import
android.content.res.Configuration;
import
android.hardware.Sensor;
import
android.hardware.SensorEvent;
import
android.hardware.SensorEventListener;
import
android.hardware.SensorManager;
import
android.os.Bundle;
import
android.os.Handler;
import
android.os.Message;
public
class
MainAct extends
MapActivity {
public
float
[] mValues;
private
SensorManager mSensorManager;
private
SensorEventListener mSensorEventListener;
private
ViewUpdateHandler mViewUpdateHandler;
private
GoogleMapView gmapView;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mSensorEventListener = new
SensorEventListener() {
public
void
onSensorChanged(SensorEvent event) {
int
ori = getResources().getConfiguration().orientation;
if
(ori == Configuration.ORIENTATION_LANDSCAPE) {
// 横置きの場合の角度補正
event.values[0] += 90;
if
(event.values[0] >= 360) {
event.values[0] -= 360;
}
}
mValues = event.values;
}
public
void
onAccuracyChanged(Sensor sensor, int
accuracy) {
}
};
gmapView = new
GoogleMapView(this
, null
);
setContentView(gmapView);
}
@Override
protected
void
onResume(){
super
.onResume();
List<Sensor> sl = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
mSensorManager.registerListener(mSensorEventListener, sl.get(0), SensorManager.SENSOR_DELAY_NORMAL);
mViewUpdateHandler = new
ViewUpdateHandler();
mViewUpdateHandler.sleep(0);
}
@Override
protected
void
onPause(){
super
.onPause();
mSensorManager.unregisterListener(mSensorEventListener);
}
@Override
protected
boolean
isRouteDisplayed() {
return
false
;
}
/**
* Google Mapを定期的に再描画するためのハンドラ
*/
public
class
ViewUpdateHandler extends
Handler {
@Override
public
void
handleMessage(Message msg) {
gmapView.invalidate();
if
(mViewUpdateHandler != null
) {
mViewUpdateHandler.sleep(100);
}
}
public
void
sleep(long
delayMillis) {
removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
}
GoogleMapView.java
import
android.content.Context;
import
android.graphics.Canvas;
import
android.util.AttributeSet;
import
android.util.FloatMath;
import
android.view.MotionEvent;
import
com.google.android.maps.GeoPoint;
import
com.google.android.maps.MapController;
import
com.google.android.maps.MapView;
public
class
GoogleMapView extends
MapView {
private
MainAct mainAct;
private
int
centerX;
private
int
centerY;
private
boolean
curDown;
private
int
lastdownX;
private
int
lastdownY;
private
static
final
String API_KEY = "[自分のAPIキー]"
;
public
GoogleMapView(Context context, AttributeSet attrs) {
super
(context, API_KEY);
}
@Override
protected
void
onAttachedToWindow() {
mainAct = (MainAct)getContext();
setBuiltInZoomControls(true
);
setSatellite(false
);
MapController mc = getController();
mc.setZoom(17);
mc.setCenter(new
GeoPoint((int
)(35.6655 * 1E6), (int
)(139.7596 * 1E6)));
setClickable(true
);
setFocusable(true
);
setFocusableInTouchMode(true
);
requestFocus();
}
@Override
protected
void
onSizeChanged(int
w, int
h, int
oldw, int
oldh) {
centerX = w / 2;
centerY = h / 2;
super
.onSizeChanged(w, h, oldw, oldh);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
int
action = event.getAction();
int
curX = (int
) event.getX();
int
curY = (int
) event.getY();
if
(action == MotionEvent.ACTION_DOWN) {
lastdownX = curX;
lastdownY = curY;
curDown = true
;
} else
if
(action == MotionEvent.ACTION_UP) {
curDown = false
;
} else
if
(curDown && action == MotionEvent.ACTION_MOVE) {
int
dx = lastdownX - curX;
int
dy = lastdownY - curY;
lastdownX = curX;
lastdownY = curY;
scroll(dx, dy);
}
return
true
;
}
@Override
public
boolean
onTrackballEvent(MotionEvent event) {
int
action = event.getAction();
float
curX = event.getX();
float
curY = event.getY();
if
(action == MotionEvent.ACTION_MOVE) {
int
dx = (int
)(curX * 50); // 50は移動速度
int
dy = (int
)(curY * 50);
scroll(dx, dy);
}
return
true
;
}
@Override
public
void
draw(Canvas canvas) {
if
(mainAct.mValues != null
) {
float
r = mainAct.mValues[0];
canvas.rotate(-r, centerX, centerY);
}
super
.draw(canvas);
}
private
void
scroll(int
dx, int
dy) {
if
(dx != 0 || dy != 0) {
// 要求された移動ベクトル
float
distance = FloatMath.sqrt(dx*dx + dy*dy);
float
rad = (float
)Math.atan2(dy, dx);
// 地図の回転角に合わせて,移動ベクトルを回転する
rad = rad - (float
)Math.toRadians(- mainAct.mValues[0]);
// 回転後のベクトルをX,Yに変換する
dx = (int
)(distance * FloatMath.cos(rad));
dy = (int
)(distance * FloatMath.sin(rad));
}
getController().scrollBy(dx, dy);
}
}
地図ロイドの回転プログラムもほとんどこれと同じですが,さらに磁北偏差の補正処理を入れたりしています.
GoogleMapを回転させる方法(MapViewのdrawをオーバーライドするという方法)は,以下のページがとても参考になりました.