アプリは沢山のクラス、xmlなどから構成されています。
長くなるので、サンプルプログラムをそのまま使ったものについては、ソースコードを省略します。また、全文はとっても長いので3回に分けることにしました。
なお、開発環境は、AndroidStudioのVer3.4でパソコンのOSはwindows10です。実端末はXperiaZ4でAndroidのバージョンは6.0です。また、AQUOS SENSE PLUS (Android Version 8.0)でも動くことは確認しています。
クラスは大きく次の3種類からなります。
- サンプルプログラムと同じもの
- サンプルプログラムを少し変えたもの
- 自分で作ったもの
自分で作ったものは次回に書くことにし、それ以外について書きます。
それでもめちゃ長くなりますが。なお、すべてのソースでimportの部分は省略しています。AndroidStudioでは勝手に書き込んでくれますので。
サンプルプログラムと同じもの
- DefaultTheme
- MapScaleBarImpl
- MapScarlBarView
- Utils
- Stting(2020/3/15追記、もう一つあるのを忘れていました)
これらは、サンプルプログラムのソースコードをそのまま使っています。
ここからコピーして使いました。
mapsforge/mapsforge-samples-android/src/main/java/org/mapsforge/samples/android at master · mapsforge/mapsforge · GitHub
サンプルプログラムを少し変えたもの
- OvarlayMapViewer
- RotateMapViewer
- SamplesApplication
- SamplesBaseActivity
- SimplestMapViewew
OvarlayMapViewerは大幅改変です。サンプルプログラムを土台にしているので、ゴミがいっぱい残っています。そのうちに整理するつもりですが、機能に影響ないのでそのままにしています。このままだとベルリン市街にいろいろなマークが表示されます。マップにいろいろなものをオーバーレイで表示するためのクラスです。GPXファイルを読み込んでルートを表示したり、POIファイルを読み込んでマークを表示する機能を追加しています。
public class OverlayMapViewer extends DefaultTheme implements LocationListener {
private final static int PERMISSION_GPS_CODE = 1001;
private LocationManager locationManager;
private SamplesApplication setGPS;
private MyLocationOverlay myLocationOverlay;
private double Latitude;
private double Longitude;
protected LatLong latLong1 = new LatLong(52.5, 13.4);
protected LatLong latLong2 = new LatLong(52.499, 13.402);
protected LatLong latLong3 = new LatLong(52.503, 13.399);
protected LatLong latLong4 = new LatLong(52.51, 13.401);
protected LatLong latLong5 = new LatLong(52.508, 13.408);
protected LatLong latLong6 = new LatLong(52.515, 13.420);
protected LatLong latLong7 = new LatLong(52.51, 13.41);
protected LatLong latLong8 = new LatLong(52.51, 13.42);
protected LatLong latLong9 = new LatLong(52.52, 13.43);
protected LatLong latLong10 = new LatLong(52.514, 13.413);
protected LatLong latLong11 = new LatLong(52.514, 13.423);
protected LatLong latLong12 = new LatLong(52.524, 13.433);
protected LatLong latLong13 = new LatLong(52.516, 13.4145);
protected LatLong latLong14 = new LatLong(52.516, 13.4245);
protected LatLong latLong15 = new LatLong(52.526, 13.4345);
protected LatLong latLongX = new LatLong( 34.859881, 135.577572);
protected LatLong latLongY = new LatLong( 34.859158, 135.581306);
private static String GPX_FILE = "";
private static String POI_FILE = "";
private static String Path ="";
String sdPath = Environment.getExternalStorageDirectory().getPath();
private String AtName;
private String AtValue;
private String XPname;
private String POIname;
private double lati = 0;
private double longi = 0;
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected void addOverlayLayers(Layers layers) {
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
GPX_FILE = preferences.getString("gpx", "null.gpx");
POI_FILE = preferences.getString("poi", "null.poi");
Path = preferences.getString("path", sdPath);
//File file = new File(Path, GPX_FILE);
Polyline polyline = new Polyline(Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.BLUE),
(int) (4 * mapView.getModel().displayModel.getScaleFactor()),
Style.STROKE), AndroidGraphicFactory.INSTANCE);
List<LatLong> latLongs = new ArrayList<>();
FileInputStream is = null;
ArrayList<Marker> markers = new ArrayList<Marker>();
//GPXファイルの解析
try {
String listXmlPath = Path + "/"+ GPX_FILE;
is = new FileInputStream(new File(listXmlPath));
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
//String content = new Scanner(
// new File(listXmlPath)).useDelimiter("\\z").next();
//XMLファイルをまとめて読み込み
XmlPullParser xpp = Xml.newPullParser();
xpp.setInput(reader);
//解析するXMLファイルの中身を渡す
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
Log.i("MainActivity", "ドキュメント開始");
break;
case XmlPullParser.START_TAG:
XPname = xpp.getName();
Log.i("MainActivity", XPname + "要素開始");
int attrCount = xpp.getAttributeCount();
for (int i = 0; i < attrCount; ++i) {
AtName = xpp.getAttributeName(i);
AtValue = xpp.getAttributeValue(i);
Log.i("MainActivity", " " +
i + "番目の属性 = " + xpp.getAttributeName(i));
Log.i("MainActivity"," " +
i + "番目の値 = " + xpp.getAttributeValue(i));
if(AtName.equals("lat")){
lati = parseDouble(AtValue);
}
if( AtName.equals("lon")) {
longi = parseDouble(AtValue);
LatLong latLong = new LatLong(lati, longi);
latLongs.add(latLong);
}
}
break;
case XmlPullParser.TEXT:
Log.i("MainActivity", "テキスト = " + xpp.getText());
break;
case XmlPullParser.END_TAG:
Log.i("MainActivity", xpp.getName() + "要素終了");
break;
}
eventType = xpp.next();
//次のトークンに進む
}
Log.i("MainActivity", "ドキュメント終了");
} catch (XmlPullParserException e) {
Log.e("MainActivity", "XMLの解析失敗.");
} catch (IOException e) {
Log.e("MainActivity", "XMLファイルの読み込みに失敗.");
}
//latLongs.add(latLong1);
//latLongs.add(latLong2);
//latLongs.add(latLong3);
polyline.setPoints(latLongs);
// this illustrates that bitmap shaders can be used on a path, but then any dash effect
// will not be applied.
Paint shaderPaint = Utils.createPaint(AndroidGraphicFactory.INSTANCE.createColor(Color.GREEN), 90, Style.STROKE);
shaderPaint.setBitmapShader(AndroidGraphicFactory.convertToBitmap(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDrawable(R.drawable.marker_green) : getResources().getDrawable(R.drawable.marker_green)));
Polyline polylineWithShader = new Polyline(shaderPaint, AndroidGraphicFactory.INSTANCE, true) {
@Override
public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) {
if (contains(tapXY, mapView.getMapViewProjection())) {
Toast.makeText(OverlayMapViewer.this, "Polyline tap\n" + tapLatLong, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
};
List<LatLong> latLongs2 = new ArrayList<>();
latLongs2.add(latLong7);
latLongs2.add(latLong8);
latLongs2.add(latLong9);
polylineWithShader.setPoints(latLongs2);
Paint paintFill = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.GREEN), 2,
Style.FILL);
Paint paintStroke = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.BLACK), 2,
Style.STROKE);
Polygon polygon = new Polygon(paintFill, paintStroke, AndroidGraphicFactory.INSTANCE) {
@Override
public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) {
if (contains(tapLatLong)) {
Toast.makeText(OverlayMapViewer.this, "Polygon tap\n" + tapLatLong, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
};
List<LatLong> latLongs3 = new ArrayList<>();
latLongs3.add(latLong2);
latLongs3.add(latLong3);
latLongs3.add(latLong4);
latLongs3.add(latLong5);
polygon.setPoints(latLongs3);
// A polygon filled with a shader, where the shader is not aligned
Paint paintFill2 = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.GREEN), 2,
Style.FILL);
paintFill2.setBitmapShader(AndroidGraphicFactory.convertToBitmap(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDrawable(R.drawable.marker_green) : getResources().getDrawable(R.drawable.marker_green)));
Paint paintStroke2 = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.BLACK), 2,
Style.STROKE);
Polygon polygonWithShaderNonAligned = new Polygon(paintFill2, paintStroke2,
AndroidGraphicFactory.INSTANCE);
List<LatLong> latLongs4 = new ArrayList<>();
latLongs4.add(latLong10);
latLongs4.add(latLong11);
latLongs4.add(latLong12);
latLongs4.add(latLong10);
polygonWithShaderNonAligned.setPoints(latLongs4);
Paint paintFill3 = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.RED), 2,
Style.FILL);
paintFill3.setBitmapShader(AndroidGraphicFactory.convertToBitmap(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDrawable(R.drawable.marker_red) : getResources().getDrawable(R.drawable.marker_red)));
Paint paintStroke3 = Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.BLACK), 2,
Style.STROKE);
Polygon polygonWithShaderAligned = new Polygon(paintFill3, paintStroke3,
AndroidGraphicFactory.INSTANCE, true);
List<LatLong> latLongs5 = new ArrayList<>();
latLongs5.add(latLong13);
latLongs5.add(latLong14);
latLongs5.add(latLong15);
latLongs5.add(latLong13);
polygonWithShaderAligned.setPoints(latLongs5);
//POIファイルの解析
try {
String listXmlPath = Path + "/"+ POI_FILE;
is = new FileInputStream(new File(listXmlPath));
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
//String content = new Scanner(
// new File(listXmlPath)).useDelimiter("\\z").next();
//XMLファイルをまとめて読み込み
XmlPullParser xpp = Xml.newPullParser();
xpp.setInput(reader);
//解析するXMLファイルの中身を渡す
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
Log.i("MainActivity", "ドキュメント開始");
break;
case XmlPullParser.START_TAG:
XPname = xpp.getName();
Log.i("MainActivity", XPname + "要素開始");
int attrCount = xpp.getAttributeCount();
for (int i = 0; i < attrCount; ++i) {
AtName = xpp.getAttributeName(i);
AtValue = xpp.getAttributeValue(i);
Log.i("MainActivity", " " +
i + "番目の属性 = " + xpp.getAttributeName(i));
Log.i("MainActivity"," " +
i + "番目の値 = " + xpp.getAttributeValue(i));
if(AtName.equals("lat")){
lati = parseDouble(AtValue);
}
if( AtName.equals("lon")) {
longi = parseDouble(AtValue);
latLongX = new LatLong(lati, longi);
//latLongs.add(latLong);
}
}
break;
case XmlPullParser.TEXT:
POIname = xpp.getText();
Log.i("MainActivity", "テキスト = " + POIname);
if (XPname.equals("icon")){
switch (POIname) {
case "1001009":
markers.add( Utils.createTappableMarker(this, R.drawable.left1, latLongX));
break;
case "1001010":
markers.add( Utils.createTappableMarker(this, R.drawable.left2, latLongX));
break;
case "1001011":
markers.add( Utils.createTappableMarker(this, R.drawable.left3, latLongX));
break;
case "1001012":
markers.add( Utils.createTappableMarker(this, R.drawable.left4, latLongX));
break;
case "1001013":
markers.add( Utils.createTappableMarker(this, R.drawable.left5, latLongX));
break;
case "1001014":
markers.add( Utils.createTappableMarker(this, R.drawable.left6, latLongX));
break;
case "1001015":
markers.add( Utils.createTappableMarker(this, R.drawable.left7, latLongX));
break;
case "1001016":
markers.add( Utils.createTappableMarker(this, R.drawable.left8, latLongX));
break;
case "1001001":
markers.add( Utils.createTappableMarker(this, R.drawable.right1, latLongX));
break;
case "1001002":
markers.add( Utils.createTappableMarker(this, R.drawable.right2, latLongX));
break;
case "1001003":
markers.add( Utils.createTappableMarker(this, R.drawable.right3, latLongX));
break;
case "1001004":
markers.add( Utils.createTappableMarker(this, R.drawable.right4, latLongX));
break;
case "1001005":
markers.add( Utils.createTappableMarker(this, R.drawable.right5, latLongX));
break;
case "1001006":
markers.add( Utils.createTappableMarker(this, R.drawable.right6, latLongX));
break;
case "1001007":
markers.add( Utils.createTappableMarker(this, R.drawable.right7, latLongX));
break;
case "1001008":
markers.add( Utils.createTappableMarker(this, R.drawable.right8, latLongX));
break;
}
}
break;
case XmlPullParser.END_TAG:
Log.i("MainActivity", xpp.getName() + "要素終了");
break;
}
eventType = xpp.next();
//次のトークンに進む
}
Log.i("MainActivity", "ドキュメント終了");
} catch (XmlPullParserException e) {
Log.e("MainActivity", "XMLの解析失敗.");
} catch (IOException e) {
Log.e("MainActivity", "XMLファイルの読み込みに失敗.");
}
//ArrayList<Marker> markers = new ArrayList<Marker>();
//markers.add( Utils.createTappableMarker(this,
//R.drawable.left1, latLongX));
//markers.add( Utils.createTappableMarker(this,
//R.drawable.right1, latLongY));
Marker marker1 = Utils.createMarker(this, R.drawable.right1, latLongY);
Circle circle = new Circle(latLong3, 100, Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.WHITE), 0,
Style.FILL), null) {
@Override
public boolean onTap(LatLong geoPoint, Point viewPosition,
Point tapPoint) {
if (this.contains(viewPosition, tapPoint, geoPoint.latitude,
mapView.getModel().mapViewPosition.getZoomLevel())) {
Toast.makeText(OverlayMapViewer.this,
"The Circle was tapped " + geoPoint.toString(),
Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
};
FixedPixelCircle tappableCircle = new FixedPixelCircle(
latLong6,
20,
Utils.createPaint(
AndroidGraphicFactory.INSTANCE.createColor(Color.GREEN),
0, Style.FILL), null) {
@Override
public boolean onTap(LatLong geoPoint, Point viewPosition,
Point tapPoint) {
if (this.contains(viewPosition, tapPoint)) {
Toast.makeText(OverlayMapViewer.this,
"The Circle was tapped " + geoPoint.toString(),
Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
};
layers.add(polyline);
layers.add(polylineWithShader);
layers.add(polygon);
layers.add(polygonWithShaderAligned);
layers.add(polygonWithShaderNonAligned);
layers.add(circle);
for (int i=0; i < markers.size(); i++ ){
layers.add(markers.get(i));
}
layers.add(tappableCircle);
}
@Override
protected void createLayers() {
super.createLayers();
setGPS=(SamplesApplication)getApplication();
// we just add a few more overlays
addOverlayLayers(mapView.getLayerManager().getLayers());
Drawable drawable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDrawable(R.drawable.ic_maps_indicator_current_position) : getResources().getDrawable(R.drawable.ic_maps_indicator_current_position);
Marker marker = new Marker(null, AndroidGraphicFactory.convertToBitmap(drawable), 0, 0);
Circle circle = new Circle(null, 0,
getPaint(AndroidGraphicFactory.INSTANCE.createColor(48, 0, 0, 255), 0, Style.FILL),
getPaint(AndroidGraphicFactory.INSTANCE.createColor(160, 0, 0, 255), 2, Style.STROKE));
myLocationOverlay = new MyLocationOverlay(marker, circle);
mapView.getLayerManager().getLayers().add(myLocationOverlay);
}
private static Paint getPaint(int color, int strokeWidth, Style style) {
Paint paint = AndroidGraphicFactory.INSTANCE.createPaint();
paint.setColor(color);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(style);
return paint;
}
private Marker createMarker(LatLong latlong, int resource) {
Drawable drawable = getResources().getDrawable(resource);
Bitmap bitmap = convertToBitmap(drawable);
return new Marker(latlong, bitmap, 0, -bitmap.getHeight() / 2);
}
@Override
public void onStart() {
super.onStart();
Log.d("DEBUG", "GPSStart");
if (setGPS.getGPScondition()==true) {
locationStart();
}
}
@Override
public void onStop() {
super.onStop();
Log.d("DEBUG", "GPSStop");
if (setGPS.getGPScondition()) {
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putFloat("Latitude", (float) Latitude);
editor.putFloat("Longitude", (float) Longitude);
editor.apply();
}
locationStop();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initLocationManager();
}
private void initLocationManager() {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
}
private void checkPermission() {
if (locationManager != null && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.d("debug", "location manager Enabled");
} else {
// GPSを設定するように促す
Intent settingsIntent =
new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);
Log.d("debug", "not gpsEnable, startActivity");
}
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1001);
}
}
private void locationStart() {
checkPermission();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,this);
}
private void locationStop() {
locationManager.removeUpdates(this);
}
@Override
public void onLocationChanged(Location location) {
Latitude = location.getLatitude();
Longitude = location.getLongitude();
this.myLocationOverlay.setPosition(Latitude, Longitude, location.getAccuracy());
// Follow location
this.mapView.setCenter(new LatLong(Latitude, Longitude));
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("DEBUG", "called onStatusChanged");
switch (status) {
case LocationProvider.AVAILABLE:
Log.d("DEBUG", "AVAILABLE");
break;
case LocationProvider.OUT_OF_SERVICE:
Log.d("DEBUG", "OUT_OF_SERVICE");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.d("DEBUG", "TEMPORARILY_UNAVAILABLE");
break;
default:
Log.d("DEBUG", "DEFAULT");
break;
}
}
@Override
public void onProviderDisabled(String provider) {
Log.d("DEBUG", "called onProviderDisabled");
}
@Override
public void onProviderEnabled(String provider) {
Log.d("DEBUG", "called onProviderEnabled");
}
}
RotateMapViewer
RotateMapViewerは地図を回転表示させるクラスです。自分のアプリではGPSのON/OFFを切り替えて、ONの時は現在地を表示するとともに、地図を端末の向いている方位に合わせて回転させています。回転角は地磁気センサーを使って取得しています。GPSがOFFの時は地図は北を向いて表示するようにしています。ルート全体を見たい時、この先のルートを見たい時などに使うようにしています。GPSがONの状態だと、地図で別の場所を見ようとしても強制的に現在地に引き戻されてしまうので、OFFの機能を付けています。
public class RotateMapViewer extends OverlayMapViewer {
private SensorManager sensorManager = null;
private SensorEventListener sensorEventListener = null;
private float[] fAccell = null;
private float[] fMagnetic = null;
float[] saveAcceleVal = new float[3];
float[] saveMagneticVal = new float[3];
private float Latitude;
private float Longitude;
private SamplesApplication setGPS;
@Override
protected void createControls() {
//Button rotateButton = (Button) findViewById(R.id.rotateButton);
//rotateButton.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// RotateView rotateView = (RotateView) findViewById(R.id.rotateView);
// rotateView.setHeading(rotateView.getHeading() - 45f);
// rotateView.postInvalidate();
// }
// });
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
fAccell = event.values.clone();
LowPassFilter(fAccell);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
fMagnetic = event.values.clone();
LowPassFilter2(fMagnetic);
if(fAccell!=null) {
float[] inR = new float[9];
SensorManager.getRotationMatrix(inR, null, fAccell, fMagnetic);
float[] outR = new float[9];
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_X, SensorManager.AXIS_Y, outR);
float[] fAttitude = new float[3];
SensorManager.getOrientation(outR, fAttitude);
//String buf =
// "---------- Orientation --------\n" +
// String.format( "方位角\n\t%d\n", (int)rad2deg( fAttitude[0] )) +
// String.format( "前後の傾斜\n\t%d\n", (int)rad2deg( fAttitude[1] )) +
// String.format( "左右の傾斜\n\t%d\n", (int)rad2deg( fAttitude[2] ));
//TextView t = (TextView) findViewById( R.id.textView1 );
//t.setText( buf );
RotateView rotateView = (RotateView) findViewById(R.id.rotateView);
rotateView.setHeading((int) rad2deg(fAttitude[0]));
rotateView.postInvalidate();
}
break;
}
//if (fAccell != null && fMagnetic != null){
//}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
ImageButton zoomInButton = (ImageButton) findViewById(R.id.zoomInButton);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapView.getModel().mapViewPosition.zoomIn();
}
});
ImageButton zoomOutButton = (ImageButton) findViewById(R.id.zoomOutButton);
zoomOutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapView.getModel().mapViewPosition.zoomOut();
}
});
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void createMapViews() {
mapView = getMapView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
findViewById(R.id.rotateView).setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
mapView.getModel().frameBufferModel.setOverdrawFactor(1.0d);
mapView.getModel().init(this.preferencesFacade);
mapView.setClickable(true);
// Use external scale bar
mapView.getMapScaleBar().setVisible(false);
MapScaleBarImpl mapScaleBar = new MapScaleBarImpl(
mapView.getModel().mapViewPosition,
mapView.getModel().mapViewDimension,
AndroidGraphicFactory.INSTANCE, mapView.getModel().displayModel);
mapScaleBar.setVisible(true);
mapScaleBar.setScaleBarMode(DefaultMapScaleBar.ScaleBarMode.BOTH);
mapScaleBar.setDistanceUnitAdapter(MetricUnitAdapter.INSTANCE);
mapScaleBar.setSecondaryDistanceUnitAdapter(ImperialUnitAdapter.INSTANCE);
MapScaleBarView mapScaleBarView = (MapScaleBarView) findViewById(R.id.mapScaleBarView);
mapScaleBarView.setMapScaleBar(mapScaleBar);
mapView.getModel().mapViewPosition.addObserver(mapScaleBarView);
mapView.setBuiltInZoomControls(hasZoomControls());
mapView.getMapZoomControls().setZoomLevelMin(getZoomLevelMin());
mapView.getMapZoomControls().setZoomLevelMax(getZoomLevelMax());
//initializePosition(mapView.getModel().mapViewPosition);
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
Latitude = preferences.getFloat("Latitude", (float) 34.491297);
Longitude = preferences.getFloat("Longitude", (float) 136.709685);
//Latitude = (float) 34.491297;
//Longitude = (float) 136.709685;
mapView.setCenter(new LatLong(Latitude, Longitude)); // 伊勢市駅
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
@SuppressWarnings("deprecation")
@Override
protected void createTileCaches() {
boolean persistent = sharedPreferences.getBoolean(
SamplesApplication.SETTING_TILECACHE_PERSISTENCE, true);
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
final int hypot;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
android.graphics.Point point = new android.graphics.Point();
display.getSize(point);
hypot = (int) Math.hypot(point.x, point.y);
} else {
hypot = (int) Math.hypot(display.getWidth(), display.getHeight());
}
this.tileCaches.add(AndroidUtil.createTileCache(this,
getPersistableId(),
this.mapView.getModel().displayModel.getTileSize(), hypot,
hypot,
this.mapView.getModel().frameBufferModel.getOverdrawFactor(), persistent));
}
@Override
protected int getLayoutId() {
return R.layout.rotatemapviewer;
}
@Override
protected boolean hasZoomControls() {
return false;
}
private float rad2deg( float rad ) {
return rad * (float) 180.0 / (float) Math.PI;
}
final float filterVal = 0.8f;
public void LowPassFilter(float[] target ){
float outVal[] = new float[3];
outVal[0] = (float)(saveAcceleVal[0] * filterVal
+ target[0] * (1-filterVal));
outVal[1] = (float)(saveAcceleVal[1] * filterVal
+ target[1] * (1-filterVal));
outVal[2] = (float)(saveAcceleVal[2] * filterVal
+ target[2] * (1-filterVal));
//現在の測定値を次の計算に使うため保存する
saveAcceleVal = target.clone();
//加速度センサーから得た値を書き換える
fAccell = outVal.clone();
return ;
}
public void LowPassFilter2(float[] target ){
float outVal[] = new float[3];
outVal[0] = (float)(saveMagneticVal[0] * filterVal
+ target[0] * (1-filterVal));
outVal[1] = (float)(saveMagneticVal[1] * filterVal
+ target[1] * (1-filterVal));
outVal[2] = (float)(saveMagneticVal[2] * filterVal
+ target[2] * (1-filterVal));
//現在の測定値を次の計算に使うため保存する
saveMagneticVal = target.clone();
//加速度センサーから得た値を書き換える
fMagnetic = outVal.clone();
return ;
}
public void onStart() { // ⇔ onStop
setGPS=(SamplesApplication)getApplication();
super.onStart();
if(setGPS.getGPScondition()==true) {
sensorManager.registerListener(
sensorEventListener,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
(int) 1e6);
sensorManager.registerListener(
sensorEventListener,
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
(int) 1e6);
}
}
public void onStop() { // ⇔ onStart
super.onStop();
sensorManager.unregisterListener( sensorEventListener );
}
}
SamplesApplication
SamplesApplicationでは、GPSのON/OFFを返すルーチンだけを追加しています。
public class SamplesApplication extends Application {
public static final String TAG = "Mapsforge Samples";
public static final String SETTING_DEBUG_TIMING = "debug_timing";
public static final String SETTING_LANGUAGE_SHOWLOCAL = "language_showlocal";
public static final String SETTING_PREFERRED_LANGUAGE = "language_selection";
public static final String SETTING_RENDERING_THREADS = "rendering_threads";
public static final String SETTING_SCALE = "scale";
public static final String SETTING_TEXTWIDTH = "textwidth";
public static final String SETTING_TILECACHE_PERSISTENCE = "tilecache_persistence";
public static final String SETTING_WAYFILTERING = "wayfiltering";
public static final String SETTING_WAYFILTERING_DISTANCE = "wayfiltering_distance";
private boolean setGPS;
@Override
public void onCreate() {
super.onCreate();
AndroidGraphicFactory.createInstance(this);
Log.e(TAG,
"Device scale factor "
+ Float.toString(DisplayModel.getDeviceScaleFactor()));
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
float fs = Float.valueOf(preferences.getString(SETTING_SCALE,
Float.toString(DisplayModel.getDefaultUserScaleFactor())));
Log.e(TAG, "User ScaleFactor " + Float.toString(fs));
if (fs != DisplayModel.getDefaultUserScaleFactor()) {
DisplayModel.setDefaultUserScaleFactor(fs);
}
MapFile.wayFilterEnabled = preferences.getBoolean(SETTING_WAYFILTERING, true);
if (MapFile.wayFilterEnabled) {
MapFile.wayFilterDistance = Integer.parseInt(preferences.getString(SETTING_WAYFILTERING_DISTANCE, "20"));
}
MapWorkerPool.DEBUG_TIMING = preferences.getBoolean(SETTING_DEBUG_TIMING, false);
setGPS = false;
}
public boolean getGPScondition() {
return setGPS;
}
public void setGPScondition(boolean setGPS) {
this.setGPS = setGPS;
}
}
SmplesBaseActivity
あまりよくわかっていませんが、基本的なセッティングなどを扱っているようです。ここも、基本は大きく変えていませんが、地図ファイルのファイル名やディレクトリなどをSharedPreferenceから読み込むようにしています。
public abstract class SamplesBaseActivity extends MapViewerTemplate implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String SETTING_SCALEBAR = "scalebar";
public static final String SETTING_SCALEBAR_METRIC = "metric";
public static final String SETTING_SCALEBAR_IMPERIAL = "imperial";
public static final String SETTING_SCALEBAR_NAUTICAL = "nautical";
public static final String SETTING_SCALEBAR_BOTH = "both";
public static final String SETTING_SCALEBAR_NONE = "none";
protected static final int DIALOG_ENTER_COORDINATES = 2923878;
protected SharedPreferences sharedPreferences;
@Override
protected int getLayoutId() {
return R.layout.mapviewer;
}
@Override
protected int getMapViewId() {
return R.id.mapView;
}
@Override
protected MapPosition getInitialPosition() {
int tileSize = this.mapView.getModel().displayModel.getTileSize();
byte zoomLevel = LatLongUtils.zoomForBounds(new Dimension(tileSize * 4, tileSize * 4), getMapFile().boundingBox(), tileSize);
return new MapPosition(getMapFile().boundingBox().getCenterPoint(), zoomLevel);
}
@Override
protected void createLayers() {
TileRendererLayer tileRendererLayer = AndroidUtil.createTileRendererLayer(this.tileCaches.get(0),
mapView.getModel().mapViewPosition, getMapFile(), getRenderTheme(), false, true, false,
getHillsRenderConfig());
this.mapView.getLayerManager().getLayers().add(tileRendererLayer);
// needed only for samples to hook into Settings.
setMaxTextWidthFactor();
}
@Override
protected void createControls() {
super.createControls();
setMapScaleBar();
}
@Override
protected void createMapViews() {
super.createMapViews();
mapView.getMapZoomControls().setZoomControlsOrientation(MapZoomControls.Orientation.VERTICAL_IN_OUT);
mapView.getMapZoomControls().setZoomInResource(R.drawable.zoom_control_in);
mapView.getMapZoomControls().setZoomOutResource(R.drawable.zoom_control_out);
mapView.getMapZoomControls().setMarginHorizontal(getResources().getDimensionPixelOffset(R.dimen.controls_margin));
mapView.getMapZoomControls().setMarginVertical(getResources().getDimensionPixelOffset(R.dimen.controls_margin));
}
@Override
protected void createTileCaches() {
boolean persistent = sharedPreferences.getBoolean(SamplesApplication.SETTING_TILECACHE_PERSISTENCE, true);
this.tileCaches.add(AndroidUtil.createTileCache(this, getPersistableId(),
this.mapView.getModel().displayModel.getTileSize(), this.getScreenRatio(),
this.mapView.getModel().frameBufferModel.getOverdrawFactor(), persistent));
}
@Override
protected String getMapFileName() {
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
String mapfile = (MainActivity.launchUrl == null) ? null : MainActivity.launchUrl.getQueryParameter("mapfile");
if (mapfile != null) {
return mapfile;
}
return preferences.getString("map", "berlin.map");
//return "berlin.map";
}
@Override
protected File getMapFileDirectory() {
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
String mapdir = (MainActivity.launchUrl == null) ? null : MainActivity.launchUrl.getQueryParameter("mapdir");
if (mapdir != null) {
File file = new File(mapdir);
if (file.exists() && file.isDirectory()) {
return file;
}
throw new RuntimeException(file + " does not exist or is not a directory (configured in launch URI " + MainActivity.launchUrl + " )");
}
return new File(preferences.getString("path", Environment.getExternalStorageDirectory().getPath()));
//return super.getMapFileDirectory();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getClass().getSimpleName());
}
@Override
protected void onDestroy() {
this.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
/*
* Settings related methods.
*/
@Override
protected void createSharedPreferences() {
super.createSharedPreferences();
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// problem that the first call to getAll() returns nothing, apparently the
// following two calls have to be made to read all the values correctly
// http://stackoverflow.com/questions/9310479/how-to-iterate-through-all-keys-of-shared-preferences
this.sharedPreferences.edit().clear();
PreferenceManager.setDefaultValues(this, R.xml.preferences, true);
this.sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
@SuppressWarnings("deprecation")
@SuppressLint("InflateParams")
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater factory = LayoutInflater.from(this);
switch (id) {
case DIALOG_ENTER_COORDINATES:
builder.setIcon(android.R.drawable.ic_menu_mylocation);
builder.setTitle(R.string.dialog_location_title);
final View view = factory.inflate(R.layout.dialog_enter_coordinates, null);
builder.setView(view);
builder.setPositiveButton(R.string.okbutton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
double lat = Double.parseDouble(((EditText) view.findViewById(R.id.latitude)).getText()
.toString());
double lon = Double.parseDouble(((EditText) view.findViewById(R.id.longitude)).getText()
.toString());
byte zoomLevel = (byte) ((((SeekBar) view.findViewById(R.id.zoomlevel)).getProgress()) +
SamplesBaseActivity.this.mapView.getModel().mapViewPosition.getZoomLevelMin());
SamplesBaseActivity.this.mapView.getModel().mapViewPosition.setMapPosition(
new MapPosition(new LatLong(lat, lon), zoomLevel));
}
});
builder.setNegativeButton(R.string.cancelbutton, null);
return builder.create();
}
return null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options_menu, menu);
return true;
}
@SuppressWarnings("deprecation")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.menu_preferences:
intent = new Intent(this, Setting.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
if (renderThemeStyleMenu != null) {
intent.putExtra(Setting.RENDERTHEME_MENU, renderThemeStyleMenu);
}
startActivity(intent);
return true;
case R.id.menu_position_enter_coordinates:
showDialog(DIALOG_ENTER_COORDINATES);
break;
case R.id.menu_svgclear:
AndroidGraphicFactory.clearResourceFileCache();
break;
}
return false;
}
@SuppressWarnings("deprecation")
@Override
protected void onPrepareDialog(int id, final Dialog dialog) {
if (id == DIALOG_ENTER_COORDINATES) {
IMapViewPosition currentPosition = SamplesBaseActivity.this.mapView.getModel().mapViewPosition;
LatLong currentCenter = currentPosition.getCenter();
EditText editText = (EditText) dialog.findViewById(R.id.latitude);
editText.setText(Double.toString(currentCenter.latitude));
editText = (EditText) dialog.findViewById(R.id.longitude);
editText.setText(Double.toString(currentCenter.longitude));
SeekBar zoomlevel = (SeekBar) dialog.findViewById(R.id.zoomlevel);
zoomlevel.setMax(currentPosition.getZoomLevelMax() - currentPosition.getZoomLevelMin());
zoomlevel.setProgress(SamplesBaseActivity.this.mapView.getModel().mapViewPosition.getZoomLevel()
- currentPosition.getZoomLevelMin());
final TextView textView = (TextView) dialog.findViewById(R.id.zoomlevelValue);
textView.setText(String.valueOf(zoomlevel.getProgress()));
zoomlevel.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
textView.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
// nothing
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
// nothing
}
});
} else {
super.onPrepareDialog(id, dialog);
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (SamplesApplication.SETTING_SCALE.equals(key)) {
this.mapView.getModel().displayModel.setUserScaleFactor(DisplayModel.getDefaultUserScaleFactor());
Log.d(SamplesApplication.TAG, "Tilesize now " + this.mapView.getModel().displayModel.getTileSize());
AndroidUtil.restartActivity(this);
}
if (SamplesApplication.SETTING_PREFERRED_LANGUAGE.equals(key)) {
String language = preferences.getString(SamplesApplication.SETTING_PREFERRED_LANGUAGE, null);
Log.d(SamplesApplication.TAG, "Preferred language now " + language);
AndroidUtil.restartActivity(this);
}
if (SamplesApplication.SETTING_TILECACHE_PERSISTENCE.equals(key)) {
if (!preferences.getBoolean(SamplesApplication.SETTING_TILECACHE_PERSISTENCE, false)) {
Log.d(SamplesApplication.TAG, "Purging tile caches");
for (TileCache tileCache : this.tileCaches) {
tileCache.purge();
}
}
AndroidUtil.restartActivity(this);
}
if (SamplesApplication.SETTING_TEXTWIDTH.equals(key)) {
AndroidUtil.restartActivity(this);
}
if (SETTING_SCALEBAR.equals(key)) {
setMapScaleBar();
}
if (SamplesApplication.SETTING_DEBUG_TIMING.equals(key)) {
MapWorkerPool.DEBUG_TIMING = preferences.getBoolean(SamplesApplication.SETTING_DEBUG_TIMING, false);
}
if (SamplesApplication.SETTING_RENDERING_THREADS.equals(key)) {
Parameters.NUMBER_OF_THREADS = preferences.getInt(SamplesApplication.SETTING_RENDERING_THREADS, 1);
AndroidUtil.restartActivity(this);
}
if (SamplesApplication.SETTING_WAYFILTERING_DISTANCE.equals(key) ||
SamplesApplication.SETTING_WAYFILTERING.equals(key)) {
MapFile.wayFilterEnabled = preferences.getBoolean(SamplesApplication.SETTING_WAYFILTERING, true);
if (MapFile.wayFilterEnabled) {
MapFile.wayFilterDistance = preferences.getInt(SamplesApplication.SETTING_WAYFILTERING_DISTANCE, 20);
}
}
}
/**
* Sets the scale bar from preferences.
*/
protected void setMapScaleBar() {
String value = this.sharedPreferences.getString(SETTING_SCALEBAR, SETTING_SCALEBAR_BOTH);
if (SETTING_SCALEBAR_NONE.equals(value)) {
AndroidUtil.setMapScaleBar(this.mapView, null, null);
} else {
if (SETTING_SCALEBAR_BOTH.equals(value)) {
AndroidUtil.setMapScaleBar(this.mapView, MetricUnitAdapter.INSTANCE, ImperialUnitAdapter.INSTANCE);
} else if (SETTING_SCALEBAR_METRIC.equals(value)) {
AndroidUtil.setMapScaleBar(this.mapView, MetricUnitAdapter.INSTANCE, null);
} else if (SETTING_SCALEBAR_IMPERIAL.equals(value)) {
AndroidUtil.setMapScaleBar(this.mapView, ImperialUnitAdapter.INSTANCE, null);
} else if (SETTING_SCALEBAR_NAUTICAL.equals(value)) {
AndroidUtil.setMapScaleBar(this.mapView, NauticalUnitAdapter.INSTANCE, null);
}
}
}
/**
* sets the value for breaking line text in labels.
*/
protected void setMaxTextWidthFactor() {
mapView.getModel().displayModel.setMaxTextWidthFactor(Float.valueOf(sharedPreferences.getString(SamplesApplication.SETTING_TEXTWIDTH, "0.7")));
}
}
SimplestMapViewer
ここが地図を描画する本体部分です。ここもマップファイル名を読み込む部分だけSharedPreferenceから読み込むようにしているだけです。
public class SimplestMapViewer extends MapViewerTemplate {
/**
* This MapViewer uses the built-in default theme.
*
* @return the render theme to use
*/
@Override
protected XmlRenderTheme getRenderTheme() {
return InternalRenderTheme.DEFAULT;
}
/**
* This MapViewer uses the standard xml layout in the Samples app.
*/
@Override
protected int getLayoutId() {
return R.layout.mapviewer;
}
/**
* The id of the mapview inside the layout.
*
* @return the id of the MapView inside the layout.
*/
@Override
protected int getMapViewId() {
return R.id.mapView;
}
/**
* The name of the map file.
*
* @return map file name
*/
@Override
protected String getMapFileName() {
SharedPreferences preferences = getSharedPreferences("DATA", Context.MODE_PRIVATE);
//return "berlin.map";
return preferences.getString("map", "berlin.map");
}
/**
* Creates a simple tile renderer layer with the AndroidUtil helper.
*/
@Override
protected void createLayers() {
TileRendererLayer tileRendererLayer = AndroidUtil.createTileRendererLayer(this.tileCaches.get(0),
this.mapView.getModel().mapViewPosition, getMapFile(), getRenderTheme(), false, true, false);
this.mapView.getLayerManager().getLayers().add(tileRendererLayer);
}
@Override
protected void createMapViews() {
super.createMapViews();
}
/**
* Creates the tile cache with the AndroidUtil helper
*/
@Override
protected void createTileCaches() {
this.tileCaches.add(AndroidUtil.createTileCache(this, getPersistableId(),
this.mapView.getModel().displayModel.getTileSize(), this.getScreenRatio(),
this.mapView.getModel().frameBufferModel.getOverdrawFactor()));
}
@Override
protected MapPosition getInitialPosition() {
int tileSize = this.mapView.getModel().displayModel.getTileSize();
byte zoomLevel = LatLongUtils.zoomForBounds(new Dimension(tileSize * 4, tileSize * 4), getMapFile().boundingBox(), tileSize);
return new MapPosition(getMapFile().boundingBox().getCenterPoint(), zoomLevel);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(getClass().getSimpleName());
}
}
ふう!! 長くなったので続きは次回に。