Migrate remaining Feature Activities in Android TestApp to Kotlin (#666)

This commit is contained in:
Birk Skyum
2023-01-08 20:00:59 +01:00
committed by GitHub
parent 0f5ea3f2ba
commit 3b4bf343f5
14 changed files with 1089 additions and 1216 deletions

View File

@@ -1,225 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.testapp.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Test activity showcasing the Polyline annotations API.
* <p>
* Shows how to add and remove polylines.
* </p>
*/
public class PolylineActivity extends AppCompatActivity {
private static final String STATE_POLYLINE_OPTIONS = "polylineOptions";
private static final LatLng ANDORRA = new LatLng(42.505777, 1.52529);
private static final LatLng LUXEMBOURG = new LatLng(49.815273, 6.129583);
private static final LatLng MONACO = new LatLng(43.738418, 7.424616);
private static final LatLng VATICAN_CITY = new LatLng(41.902916, 12.453389);
private static final LatLng SAN_MARINO = new LatLng(43.942360, 12.457777);
private static final LatLng LIECHTENSTEIN = new LatLng(47.166000, 9.555373);
private static final float FULL_ALPHA = 1.0f;
private static final float PARTIAL_ALPHA = 0.5f;
private static final float NO_ALPHA = 0.0f;
private List<Polyline> polylines;
private ArrayList<PolylineOptions> polylineOptions = new ArrayList<>();
private MapView mapView;
private MapboxMap mapboxMap;
private boolean fullAlpha = true;
private boolean visible = true;
private boolean width = true;
private boolean color = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_polyline);
if (savedInstanceState != null) {
polylineOptions = savedInstanceState.getParcelableArrayList(STATE_POLYLINE_OPTIONS);
} else {
polylineOptions.addAll(getAllPolylines());
}
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> {
PolylineActivity.this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.getPredefinedStyle("Satellite Hybrid"));
mapboxMap.setOnPolylineClickListener(polyline -> Toast.makeText(
PolylineActivity.this,
"You clicked on polyline with id = " + polyline.getId(),
Toast.LENGTH_SHORT
).show());
polylines = mapboxMap.addPolylines(polylineOptions);
});
View fab = findViewById(R.id.fab);
if (fab != null) {
fab.setOnClickListener(view -> {
if (mapboxMap != null) {
if (polylines != null && polylines.size() > 0) {
if (polylines.size() == 1) {
// test for removing annotation
mapboxMap.removeAnnotation(polylines.get(0));
} else {
// test for removing annotations
mapboxMap.removeAnnotations(polylines);
}
}
polylineOptions.clear();
polylineOptions.addAll(getRandomLine());
polylines = mapboxMap.addPolylines(polylineOptions);
}
});
}
}
private List<PolylineOptions> getAllPolylines() {
List<PolylineOptions> options = new ArrayList<>();
options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336"));
options.add(generatePolyline(ANDORRA, MONACO, "#FF5722"));
options.add(generatePolyline(MONACO, VATICAN_CITY, "#673AB7"));
options.add(generatePolyline(VATICAN_CITY, SAN_MARINO, "#009688"));
options.add(generatePolyline(SAN_MARINO, LIECHTENSTEIN, "#795548"));
options.add(generatePolyline(LIECHTENSTEIN, LUXEMBOURG, "#3F51B5"));
return options;
}
private PolylineOptions generatePolyline(LatLng start, LatLng end, String color) {
PolylineOptions line = new PolylineOptions();
line.add(start);
line.add(end);
line.color(Color.parseColor(color));
return line;
}
public List<PolylineOptions> getRandomLine() {
final List<PolylineOptions> randomLines = getAllPolylines();
Collections.shuffle(randomLines);
return new ArrayList<PolylineOptions>() {
{
add(randomLines.get(0));
}
};
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
outState.putParcelableArrayList(STATE_POLYLINE_OPTIONS, polylineOptions);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_polyline, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (polylines.size() <= 0) {
Toast.makeText(PolylineActivity.this, "No polylines on map", Toast.LENGTH_LONG).show();
return super.onOptionsItemSelected(item);
}
switch (item.getItemId()) {
case R.id.action_id_remove:
// test to remove all annotations
polylineOptions.clear();
mapboxMap.clear();
polylines.clear();
return true;
case R.id.action_id_alpha:
fullAlpha = !fullAlpha;
for (Polyline p : polylines) {
p.setAlpha(fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA);
}
return true;
case R.id.action_id_color:
color = !color;
for (Polyline p : polylines) {
p.setColor(color ? Color.RED : Color.BLUE);
}
return true;
case R.id.action_id_width:
width = !width;
for (Polyline p : polylines) {
p.setWidth(width ? 3.0f : 5.0f);
}
return true;
case R.id.action_id_visible:
visible = !visible;
for (Polyline p : polylines) {
p.setAlpha(visible ? (fullAlpha ? FULL_ALPHA : PARTIAL_ALPHA) : NO_ALPHA);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@@ -0,0 +1,209 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation
import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.mapboxsdk.annotations.Polyline
import com.mapbox.mapboxsdk.annotations.PolylineOptions
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.testapp.R
import java.util.*
/**
* Test activity showcasing the Polyline annotations API.
*
*
* Shows how to add and remove polylines.
*
*/
class PolylineActivity : AppCompatActivity() {
private var polylines: MutableList<Polyline>? = null
private var polylineOptions: ArrayList<PolylineOptions?>? = ArrayList()
private lateinit var mapView: MapView
private lateinit var mapboxMap: MapboxMap
private var fullAlpha = true
private var showPolylines = true
private var width = true
private var color = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_polyline)
if (savedInstanceState != null) {
polylineOptions = savedInstanceState.getParcelableArrayList(STATE_POLYLINE_OPTIONS)
} else {
polylineOptions!!.addAll(allPolylines)
}
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(
OnMapReadyCallback { mapboxMap: MapboxMap ->
this@PolylineActivity.mapboxMap = mapboxMap
mapboxMap.setStyle(Style.getPredefinedStyle("Satellite Hybrid"))
mapboxMap.setOnPolylineClickListener { polyline: Polyline ->
Toast.makeText(
this@PolylineActivity,
"You clicked on polyline with id = " + polyline.id,
Toast.LENGTH_SHORT
).show()
}
polylines = mapboxMap.addPolylines(polylineOptions!!)
}
)
val fab = findViewById<View>(R.id.fab)
fab?.setOnClickListener { view: View? ->
if (mapboxMap != null) {
if (polylines != null && polylines!!.size > 0) {
if (polylines!!.size == 1) {
// test for removing annotation
mapboxMap.removeAnnotation(polylines!![0])
} else {
// test for removing annotations
mapboxMap.removeAnnotations(polylines!!)
}
}
polylineOptions!!.clear()
polylineOptions!!.addAll(randomLine)
polylines = mapboxMap.addPolylines(polylineOptions!!)
}
}
}
private val allPolylines: List<PolylineOptions?>
private get() {
val options: MutableList<PolylineOptions?> = ArrayList()
options.add(generatePolyline(ANDORRA, LUXEMBOURG, "#F44336"))
options.add(generatePolyline(ANDORRA, MONACO, "#FF5722"))
options.add(generatePolyline(MONACO, VATICAN_CITY, "#673AB7"))
options.add(generatePolyline(VATICAN_CITY, SAN_MARINO, "#009688"))
options.add(generatePolyline(SAN_MARINO, LIECHTENSTEIN, "#795548"))
options.add(generatePolyline(LIECHTENSTEIN, LUXEMBOURG, "#3F51B5"))
return options
}
private fun generatePolyline(start: LatLng, end: LatLng, color: String): PolylineOptions {
val line = PolylineOptions()
line.add(start)
line.add(end)
line.color(Color.parseColor(color))
return line
}
val randomLine: List<PolylineOptions?>
get() {
val randomLines = allPolylines
Collections.shuffle(randomLines)
return object : ArrayList<PolylineOptions?>() {
init {
add(randomLines[0])
}
}
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
outState.putParcelableArrayList(STATE_POLYLINE_OPTIONS, polylineOptions)
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_polyline, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (polylines!!.size <= 0) {
Toast.makeText(this@PolylineActivity, "No polylines on map", Toast.LENGTH_LONG).show()
return super.onOptionsItemSelected(item)
}
return when (item.itemId) {
R.id.action_id_remove -> {
// test to remove all annotations
polylineOptions!!.clear()
mapboxMap.clear()
polylines!!.clear()
true
}
R.id.action_id_alpha -> {
fullAlpha = !fullAlpha
for (p in polylines!!) {
p.alpha = if (fullAlpha) FULL_ALPHA else PARTIAL_ALPHA
}
true
}
R.id.action_id_color -> {
color = !color
for (p in polylines!!) {
p.color = if (color) Color.RED else Color.BLUE
}
true
}
R.id.action_id_width -> {
width = !width
for (p in polylines!!) {
p.width = if (width) 3.0f else 5.0f
}
true
}
R.id.action_id_visible -> {
showPolylines = !showPolylines
for (p in polylines!!) {
p.alpha =
if (showPolylines) (if (fullAlpha) FULL_ALPHA else PARTIAL_ALPHA) else NO_ALPHA
}
true
}
else -> super.onOptionsItemSelected(item)
}
}
companion object {
private const val STATE_POLYLINE_OPTIONS = "polylineOptions"
private val ANDORRA = LatLng(42.505777, 1.52529)
private val LUXEMBOURG = LatLng(49.815273, 6.129583)
private val MONACO = LatLng(43.738418, 7.424616)
private val VATICAN_CITY = LatLng(41.902916, 12.453389)
private val SAN_MARINO = LatLng(43.942360, 12.457777)
private val LIECHTENSTEIN = LatLng(47.166000, 9.555373)
private const val FULL_ALPHA = 1.0f
private const val PARTIAL_ALPHA = 0.5f
private const val NO_ALPHA = 0.0f
}
}

View File

@@ -1,153 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.PointF;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.testapp.R;
import java.text.DecimalFormat;
import java.util.ArrayList;
/**
* Test activity showcasing to add a Marker on click.
* <p>
* Shows how to use a OnMapClickListener and a OnMapLongClickListener
* </p>
*/
public class PressForMarkerActivity extends AppCompatActivity {
private MapView mapView;
private MapboxMap mapboxMap;
private ArrayList<MarkerOptions> markerList = new ArrayList<>();
private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
private static String STATE_MARKER_LIST = "markerList";
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_press_for_marker);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(map -> {
mapboxMap = map;
resetMap();
mapboxMap.addOnMapLongClickListener(point -> {
addMarker(point);
return false;
});
mapboxMap.addOnMapClickListener(point -> {
addMarker(point);
return false;
});
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
if (savedInstanceState != null) {
markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
if (markerList != null) {
mapboxMap.addMarkers(markerList);
}
}
});
}
private void addMarker(LatLng point) {
final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", "
+ LAT_LON_FORMATTER.format(point.getLongitude());
String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
MarkerOptions marker = new MarkerOptions()
.position(point)
.title(title)
.snippet(snippet);
markerList.add(marker);
mapboxMap.addMarker(marker);
}
private void resetMap() {
if (mapboxMap == null) {
return;
}
markerList.clear();
mapboxMap.removeAnnotations();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_press_for_marker, menu);
return true;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
outState.putParcelableArrayList(STATE_MARKER_LIST, markerList);
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menuItemReset:
resetMap();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@@ -0,0 +1,134 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.mapboxsdk.annotations.MarkerOptions
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.testapp.R
import java.text.DecimalFormat
import java.util.ArrayList
/**
* Test activity showcasing to add a Marker on click.
*
*
* Shows how to use a OnMapClickListener and a OnMapLongClickListener
*
*/
class PressForMarkerActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var mapboxMap: MapboxMap
private var markerList: ArrayList<MarkerOptions>? = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_press_for_marker)
mapView = findViewById<View>(R.id.mapView) as MapView
mapView.onCreate(savedInstanceState)
mapView.getMapAsync { map: MapboxMap? ->
if (map != null) {
mapboxMap = map
}
resetMap()
mapboxMap.addOnMapLongClickListener { point: LatLng ->
addMarker(point)
false
}
mapboxMap.addOnMapClickListener { point: LatLng ->
addMarker(point)
false
}
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"))
if (savedInstanceState != null) {
markerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST)
if (markerList != null) {
mapboxMap.addMarkers(markerList!!)
}
}
}
}
private fun addMarker(point: LatLng) {
val pixel = mapboxMap.projection.toScreenLocation(point)
val title = (
LAT_LON_FORMATTER.format(point.latitude) + ", " +
LAT_LON_FORMATTER.format(point.longitude)
)
val snippet = "X = " + pixel.x.toInt() + ", Y = " + pixel.y.toInt()
val marker = MarkerOptions()
.position(point)
.title(title)
.snippet(snippet)
markerList!!.add(marker)
mapboxMap.addMarker(marker)
}
private fun resetMap() {
if (mapboxMap == null) {
return
}
markerList!!.clear()
mapboxMap.removeAnnotations()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_press_for_marker, menu)
return true
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
outState.putParcelableArrayList(STATE_MARKER_LIST, markerList)
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menuItemReset -> {
resetMap()
true
}
else -> super.onOptionsItemSelected(item)
}
}
companion object {
private val LAT_LON_FORMATTER = DecimalFormat("#.#####")
private const val STATE_MARKER_LIST = "markerList"
}
}

View File

@@ -1,81 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.espresso;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.testapp.R;
public class DeviceIndependentTestActivity extends AppCompatActivity implements OnMapReadyCallback {
public MapView mapView;
protected MapboxMap mapboxMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_test);
// Initialize map as normal
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull MapboxMap map) {
mapboxMap = map;
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"));
}
public MapboxMap getMapboxMap() {
return mapboxMap;
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}

View File

@@ -0,0 +1,65 @@
package com.mapbox.mapboxsdk.testapp.activity.espresso
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.testapp.R
class DeviceIndependentTestActivity : AppCompatActivity(), OnMapReadyCallback {
lateinit var mapView: MapView
lateinit var mapboxMap: MapboxMap
protected set
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera_test)
// Initialize map as normal
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
}
override fun onMapReady(map: MapboxMap) {
mapboxMap = map
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"))
}
public override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
public override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
}

View File

@@ -1,68 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.espresso;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
/**
* Base activity for instrumentation testing.
*/
public class EspressoTestActivity extends AppCompatActivity {
public MapView mapView;
protected MapboxMap mapboxMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_espresso_test);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}

View File

@@ -0,0 +1,56 @@
package com.mapbox.mapboxsdk.testapp.activity.espresso
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.testapp.R
/**
* Base activity for instrumentation testing.
*/
class EspressoTestActivity : AppCompatActivity() {
lateinit var mapView: MapView
protected lateinit var mapboxMap: MapboxMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_espresso_test)
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
}
public override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
public override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
}

View File

@@ -1,131 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatFontScale;
import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatTextColor;
import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatTextFont;
import static com.mapbox.mapboxsdk.style.expressions.Expression.formatEntry;
import static com.mapbox.mapboxsdk.style.expressions.Expression.image;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
/**
* Test image in label.
*/
public class ImageInLabelActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String ORIGINAL_SOURCE = "ORIGINAL_SOURCE";
private static final String ORIGINAL_LAYER = "ORIGINAL_LAYER";
private MapView mapView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stretchable_image);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.getPredefinedStyle("Streets"), style -> {
Bitmap us = BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.ic_us));
Bitmap android = BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.ic_android));
style.addImage("us", us);
style.addImage("android", android);
Point point = Point.fromLngLat(-10, 0);
Feature feature = Feature.fromGeometry(point);
FeatureCollection originalCollection = FeatureCollection.fromFeature(feature);
GeoJsonSource originalSource = new GeoJsonSource(ORIGINAL_SOURCE, originalCollection);
SymbolLayer originalLayer = new SymbolLayer(ORIGINAL_LAYER, ORIGINAL_SOURCE)
.withProperties(
textAllowOverlap(true),
textField(Expression
.format(
formatEntry(literal("Android: "),
formatFontScale(1.0),
formatTextColor(Color.BLUE),
formatTextFont(new String[] {"Ubuntu Medium", "Arial Unicode MS Regular"})),
formatEntry(image(literal("android"))),
formatEntry(literal("Us: "),
formatFontScale(1.5),
formatTextColor(Color.YELLOW)),
formatEntry(image(literal("us"))),
formatEntry(literal("suffix"),
formatFontScale(2.0),
formatTextColor(Color.CYAN))
)
)
);
style.addSource(originalSource);
style.addLayer(originalLayer);
});
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
}

View File

@@ -0,0 +1,123 @@
package com.mapbox.mapboxsdk.testapp.activity.style
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.geojson.Feature
import com.mapbox.geojson.FeatureCollection
import com.mapbox.geojson.Point
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.style.expressions.Expression
import com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption
import com.mapbox.mapboxsdk.style.layers.PropertyFactory
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
import com.mapbox.mapboxsdk.testapp.R
import com.mapbox.mapboxsdk.utils.BitmapUtils
/**
* Test image in label.
*/
class ImageInLabelActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mapView: MapView
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_stretchable_image)
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
}
override fun onMapReady(mapboxMap: MapboxMap) {
mapboxMap.setStyle(Style.getPredefinedStyle("Streets")) { style: Style ->
val us = BitmapUtils.getBitmapFromDrawable(
resources.getDrawable(R.drawable.ic_us)
)
val android =
BitmapUtils.getBitmapFromDrawable(resources.getDrawable(R.drawable.ic_android))
style.addImage("us", us!!)
style.addImage("android", android!!)
val point = Point.fromLngLat(-10.0, 0.0)
val feature = Feature.fromGeometry(point)
val originalCollection = FeatureCollection.fromFeature(feature)
val originalSource = GeoJsonSource(ORIGINAL_SOURCE, originalCollection)
val originalLayer = SymbolLayer(ORIGINAL_LAYER, ORIGINAL_SOURCE)
.withProperties(
PropertyFactory.textAllowOverlap(true),
PropertyFactory.textField(
Expression
.format(
Expression.formatEntry(
Expression.literal("Android: "),
FormatOption.formatFontScale(1.0),
FormatOption.formatTextColor(Color.BLUE),
FormatOption.formatTextFont(
arrayOf(
"Ubuntu Medium",
"Arial Unicode MS Regular"
)
)
),
Expression.formatEntry(Expression.image(Expression.literal("android"))),
Expression.formatEntry(
Expression.literal("Us: "),
FormatOption.formatFontScale(1.5),
FormatOption.formatTextColor(Color.YELLOW)
),
Expression.formatEntry(Expression.image(Expression.literal("us"))),
Expression.formatEntry(
Expression.literal("suffix"),
FormatOption.formatFontScale(2.0),
FormatOption.formatTextColor(Color.CYAN)
)
)
)
)
style.addSource(originalSource)
style.addLayer(originalLayer)
}
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
public override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
public override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
companion object {
private const val ORIGINAL_SOURCE = "ORIGINAL_SOURCE"
private const val ORIGINAL_LAYER = "ORIGINAL_LAYER"
}
}

View File

@@ -1,369 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
import static com.mapbox.mapboxsdk.style.expressions.Expression.division;
import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
import static com.mapbox.mapboxsdk.style.expressions.Expression.number;
import static com.mapbox.mapboxsdk.style.expressions.Expression.pi;
import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
import static com.mapbox.mapboxsdk.style.expressions.Expression.upcase;
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_BOTTOM;
import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_TOP;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOpacity;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAnchor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
/**
* Test activity showcasing using a symbol generator that generates Bitmaps from Android SDK Views.
*/
public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String SOURCE_ID = "com.mapbox.mapboxsdk.style.layers.symbol.source.id";
private static final String LAYER_ID = "com.mapbox.mapboxsdk.style.layers.symbol.layer.id";
private static final String FEATURE_ID = "brk_name";
private static final String FEATURE_RANK = "scalerank";
private static final String FEATURE_NAME = "name_sort";
private static final String FEATURE_TYPE = "type";
private static final String FEATURE_REGION = "continent";
private MapView mapView;
private MapboxMap mapboxMap;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_symbol_generator);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull final MapboxMap map) {
mapboxMap = map;
map.setStyle(Style.getPredefinedStyle("Outdoor"), style -> {
addSymbolClickListener();
new LoadDataTask(SymbolGeneratorActivity.this).execute();
});
}
private void addSymbolClickListener() {
mapboxMap.addOnMapClickListener(point -> {
PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID);
if (!features.isEmpty()) {
Feature feature = features.get(0);
// validate symbol flicker regression for #13407
SymbolLayer layer = mapboxMap.getStyle().getLayerAs(LAYER_ID);
layer.setProperties(iconOpacity(match(
get(FEATURE_ID), literal(1.0f),
stop(feature.getStringProperty(FEATURE_ID), 0.3f)
)));
Timber.v("Feature was clicked with data: %s", feature.toJson());
Toast.makeText(
SymbolGeneratorActivity.this,
"hello from: " + feature.getStringProperty(FEATURE_NAME),
Toast.LENGTH_LONG).show();
}
return false;
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_generator_symbol, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_action_icon_overlap) {
SymbolLayer layer = mapboxMap.getStyle().getLayerAs(LAYER_ID);
layer.setProperties(iconAllowOverlap(!layer.getIconAllowOverlap().getValue()));
return true;
} else if (item.getItemId() == R.id.menu_action_filter) {
SymbolLayer layer = mapboxMap.getStyle().getLayerAs(LAYER_ID);
layer.setFilter(eq(get(FEATURE_RANK), literal(1)));
Timber.e("Filter that was set: %s", layer.getFilter());
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
/**
* Utility class to generate Bitmaps for Symbol.
* <p>
* Bitmaps can be added to the map with {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)}
* </p>
*/
private static class SymbolGenerator {
/**
* Generate a Bitmap from an Android SDK View.
*
* @param view the View to be drawn to a Bitmap
* @return the generated bitmap
*/
public static Bitmap generate(@NonNull View view) {
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measureSpec, measureSpec);
int measuredWidth = view.getMeasuredWidth();
int measuredHeight = view.getMeasuredHeight();
view.layout(0, 0, measuredWidth, measuredHeight);
Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
}
private static class LoadDataTask extends AsyncTask<Void, Void, FeatureCollection> {
private WeakReference<SymbolGeneratorActivity> activity;
LoadDataTask(SymbolGeneratorActivity activity) {
this.activity = new WeakReference<>(activity);
}
@Override
protected FeatureCollection doInBackground(Void... params) {
Context context = activity.get();
if (context != null) {
// read local geojson from raw folder
String tinyCountriesJson = ResourceUtils.readRawResource(context, R.raw.tiny_countries);
return FeatureCollection.fromJson(tinyCountriesJson);
}
return null;
}
@Override
protected void onPostExecute(FeatureCollection featureCollection) {
super.onPostExecute(featureCollection);
SymbolGeneratorActivity activity = this.activity.get();
if (featureCollection == null || activity == null) {
return;
}
activity.onDataLoaded(featureCollection);
}
}
public void onDataLoaded(@NonNull FeatureCollection featureCollection) {
if (mapView.isDestroyed()) {
return;
}
// create expressions
Expression iconImageExpression = string(get(literal(FEATURE_ID)));
Expression iconSizeExpression = division(number(get(literal(FEATURE_RANK))), literal(2.0f));
Expression textSizeExpression = product(get(literal(FEATURE_RANK)), pi());
Expression textFieldExpression = concat(upcase(literal("a ")), upcase(string(get(literal(FEATURE_TYPE)))),
downcase(literal(" IN ")), string(get(literal(FEATURE_REGION)))
);
Expression textColorExpression = match(get(literal(FEATURE_RANK)),
literal(1), rgba(255, 0, 0, 1.0f),
literal(2), rgba(0, 0, 255.0f, 1.0f),
rgba(0.0f, 255.0f, 0.0f, 1.0f)
);
rgba(
division(literal(255), get(FEATURE_RANK)),
literal(0.0f),
literal(0.0f),
literal(1.0f)
);
// create symbol layer
SymbolLayer symbolLayer = new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(
// icon configuration
iconImage(iconImageExpression),
iconAllowOverlap(false),
iconSize(iconSizeExpression),
iconAnchor(ICON_ANCHOR_BOTTOM),
iconOffset(step(zoom(), literal(new float[] {0f, 0f}),
stop(1, new Float[] {0f, 0f}),
stop(10, new Float[] {0f, -35f})
)),
// text field configuration
textField(textFieldExpression),
textSize(textSizeExpression),
textAnchor(TEXT_ANCHOR_TOP),
textColor(textColorExpression)
);
// add a geojson source to the map
Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
mapboxMap.getStyle().addSource(source);
// add symbol layer
mapboxMap.getStyle().addLayer(symbolLayer);
// get expressions
Expression iconImageExpressionResult = symbolLayer.getIconImage().getExpression();
Expression iconSizeExpressionResult = symbolLayer.getIconSize().getExpression();
Expression textSizeExpressionResult = symbolLayer.getTextSize().getExpression();
Expression textFieldExpressionResult = symbolLayer.getTextField().getExpression();
Expression textColorExpressionResult = symbolLayer.getTextColor().getExpression();
// log expressions
Timber.e(iconImageExpressionResult.toString());
Timber.e(iconSizeExpressionResult.toString());
Timber.e(textSizeExpressionResult.toString());
Timber.e(textFieldExpressionResult.toString());
Timber.e(textColorExpressionResult.toString());
// reset expressions
symbolLayer.setProperties(
iconImage(iconImageExpressionResult),
iconSize(iconSizeExpressionResult),
textSize(textSizeExpressionResult),
textField(textFieldExpressionResult),
textColor(textColorExpressionResult)
);
new GenerateSymbolTask(mapboxMap, this).execute(featureCollection);
}
private static class GenerateSymbolTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
private MapboxMap mapboxMap;
private WeakReference<Context> context;
GenerateSymbolTask(MapboxMap mapboxMap, Context context) {
this.mapboxMap = mapboxMap;
this.context = new WeakReference<>(context);
}
@SuppressWarnings("WrongThread")
@Override
protected HashMap<String, Bitmap> doInBackground(FeatureCollection... params) {
HashMap<String, Bitmap> imagesMap = new HashMap<>();
Context context = this.context.get();
List<Feature> features = params[0].features();
if (context != null && features != null) {
for (Feature feature : features) {
String countryName = feature.getStringProperty(FEATURE_ID);
TextView textView = new TextView(context);
textView.setBackgroundColor(context.getResources().getColor(R.color.blueAccent));
textView.setPadding(10, 5, 10, 5);
textView.setTextColor(Color.WHITE);
textView.setText(countryName);
imagesMap.put(countryName, SymbolGenerator.generate(textView));
}
}
return imagesMap;
}
@Override
protected void onPostExecute(HashMap<String, Bitmap> bitmapHashMap) {
super.onPostExecute(bitmapHashMap);
mapboxMap.getStyle(new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
style.addImagesAsync(bitmapHashMap);
}
});
}
}
}

View File

@@ -0,0 +1,346 @@
package com.mapbox.mapboxsdk.testapp.activity.style
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.os.AsyncTask
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.geojson.FeatureCollection
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.style.expressions.Expression
import com.mapbox.mapboxsdk.style.layers.Property
import com.mapbox.mapboxsdk.style.layers.PropertyFactory
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
import com.mapbox.mapboxsdk.style.sources.Source
import com.mapbox.mapboxsdk.testapp.R
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils.readRawResource
import timber.log.Timber
import java.lang.ref.WeakReference
/**
* Test activity showcasing using a symbol generator that generates Bitmaps from Android SDK Views.
*/
class SymbolGeneratorActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mapView: MapView
private lateinit var mapboxMap: MapboxMap
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_symbol_generator)
mapView = findViewById<View>(R.id.mapView) as MapView
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
}
override fun onMapReady(map: MapboxMap) {
mapboxMap = map
map.setStyle(Style.getPredefinedStyle("Outdoor")) { style: Style? ->
addSymbolClickListener()
LoadDataTask(this@SymbolGeneratorActivity).execute()
}
}
private fun addSymbolClickListener() {
mapboxMap.addOnMapClickListener { point: LatLng? ->
val screenPoint = mapboxMap.projection.toScreenLocation(
point!!
)
val features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID)
if (!features.isEmpty()) {
val feature = features[0]
// validate symbol flicker regression for #13407
val layer = mapboxMap.style!!.getLayerAs<SymbolLayer>(LAYER_ID)
layer!!.setProperties(
PropertyFactory.iconOpacity(
Expression.match(
Expression.get(FEATURE_ID),
Expression.literal(1.0f),
Expression.stop(feature.getStringProperty(FEATURE_ID), 0.3f)
)
)
)
Timber.v("Feature was clicked with data: %s", feature.toJson())
Toast.makeText(
this@SymbolGeneratorActivity,
"hello from: " + feature.getStringProperty(FEATURE_NAME),
Toast.LENGTH_LONG
).show()
}
false
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_generator_symbol, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.menu_action_icon_overlap) {
val layer = mapboxMap.style!!.getLayerAs<SymbolLayer>(LAYER_ID)
layer!!.setProperties(PropertyFactory.iconAllowOverlap(!layer.iconAllowOverlap.getValue()!!))
return true
} else if (item.itemId == R.id.menu_action_filter) {
val layer = mapboxMap.style!!.getLayerAs<SymbolLayer>(LAYER_ID)
layer!!.setFilter(Expression.eq(Expression.get(FEATURE_RANK), Expression.literal(1)))
Timber.e("Filter that was set: %s", layer.filter)
return true
}
return super.onOptionsItemSelected(item)
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
public override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
public override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
/**
* Utility class to generate Bitmaps for Symbol.
*
*
* Bitmaps can be added to the map with [com.mapbox.mapboxsdk.maps.MapboxMap.addImage]
*
*/
private object SymbolGenerator {
/**
* Generate a Bitmap from an Android SDK View.
*
* @param view the View to be drawn to a Bitmap
* @return the generated bitmap
*/
fun generate(view: View): Bitmap {
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(measureSpec, measureSpec)
val measuredWidth = view.measuredWidth
val measuredHeight = view.measuredHeight
view.layout(0, 0, measuredWidth, measuredHeight)
val bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
bitmap.eraseColor(Color.TRANSPARENT)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
}
private class LoadDataTask internal constructor(activity: SymbolGeneratorActivity) :
AsyncTask<Void?, Void?, FeatureCollection?>() {
private val activity: WeakReference<SymbolGeneratorActivity>
init {
this.activity = WeakReference(activity)
}
override fun doInBackground(vararg p0: Void?): FeatureCollection? {
val context: Context? = activity.get()
if (context != null) {
// read local geojson from raw folder
val tinyCountriesJson = readRawResource(context, R.raw.tiny_countries)
return FeatureCollection.fromJson(tinyCountriesJson)
}
return null
}
override fun onPostExecute(featureCollection: FeatureCollection?) {
super.onPostExecute(featureCollection)
val activity = activity.get()
if (featureCollection == null || activity == null) {
return
}
activity.onDataLoaded(featureCollection)
}
}
fun onDataLoaded(featureCollection: FeatureCollection) {
if (mapView.isDestroyed) {
return
}
// create expressions
val iconImageExpression = Expression.string(Expression.get(Expression.literal(FEATURE_ID)))
val iconSizeExpression = Expression.division(
Expression.number(
Expression.get(
Expression.literal(
FEATURE_RANK
)
)
),
Expression.literal(2.0f)
)
val textSizeExpression = Expression.product(
Expression.get(
Expression.literal(
FEATURE_RANK
)
),
Expression.pi()
)
val textFieldExpression = Expression.concat(
Expression.upcase(Expression.literal("a ")),
Expression.upcase(
Expression.string(
Expression.get(Expression.literal(FEATURE_TYPE))
)
),
Expression.downcase(Expression.literal(" IN ")),
Expression.string(
Expression.get(
Expression.literal(
FEATURE_REGION
)
)
)
)
val textColorExpression = Expression.match(
Expression.get(Expression.literal(FEATURE_RANK)),
Expression.literal(1),
Expression.rgba(255, 0, 0, 1.0f),
Expression.literal(2),
Expression.rgba(0, 0, 255.0f, 1.0f),
Expression.rgba(0.0f, 255.0f, 0.0f, 1.0f)
)
Expression.rgba(
Expression.division(Expression.literal(255), Expression.get(FEATURE_RANK)),
Expression.literal(0.0f),
Expression.literal(0.0f),
Expression.literal(1.0f)
)
// create symbol layer
val symbolLayer = SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties( // icon configuration
PropertyFactory.iconImage(iconImageExpression),
PropertyFactory.iconAllowOverlap(false),
PropertyFactory.iconSize(iconSizeExpression),
PropertyFactory.iconAnchor(Property.ICON_ANCHOR_BOTTOM),
PropertyFactory.iconOffset(
Expression.step(
Expression.zoom(),
Expression.literal(floatArrayOf(0f, 0f)),
Expression.stop(1, arrayOf(0f, 0f)),
Expression.stop(10, arrayOf(0f, -35f))
)
), // text field configuration
PropertyFactory.textField(textFieldExpression),
PropertyFactory.textSize(textSizeExpression),
PropertyFactory.textAnchor(Property.TEXT_ANCHOR_TOP),
PropertyFactory.textColor(textColorExpression)
)
// add a geojson source to the map
val source: Source = GeoJsonSource(SOURCE_ID, featureCollection)
mapboxMap.style!!.addSource(source)
// add symbol layer
mapboxMap.style!!.addLayer(symbolLayer)
// get expressions
val iconImageExpressionResult = symbolLayer.iconImage.expression
val iconSizeExpressionResult = symbolLayer.iconSize.expression
val textSizeExpressionResult = symbolLayer.textSize.expression
val textFieldExpressionResult = symbolLayer.textField.expression
val textColorExpressionResult = symbolLayer.textColor.expression
// log expressions
Timber.e(iconImageExpressionResult.toString())
Timber.e(iconSizeExpressionResult.toString())
Timber.e(textSizeExpressionResult.toString())
Timber.e(textFieldExpressionResult.toString())
Timber.e(textColorExpressionResult.toString())
// reset expressions
symbolLayer.setProperties(
PropertyFactory.iconImage(iconImageExpressionResult),
PropertyFactory.iconSize(iconSizeExpressionResult),
PropertyFactory.textSize(textSizeExpressionResult),
PropertyFactory.textField(textFieldExpressionResult),
PropertyFactory.textColor(textColorExpressionResult)
)
GenerateSymbolTask(mapboxMap, this).execute(featureCollection)
}
private class GenerateSymbolTask internal constructor(
private val mapboxMap: MapboxMap?,
context: Context
) : AsyncTask<FeatureCollection?, Void?, HashMap<String, Bitmap>>() {
private val context: WeakReference<Context>
init {
this.context = WeakReference(context)
}
override fun doInBackground(vararg p0: FeatureCollection?): HashMap<String, Bitmap>? {
val imagesMap = HashMap<String, Bitmap>()
val context = context.get()
val features = p0[0]?.features()
if (context != null && features != null) {
for (feature in features) {
val countryName = feature.getStringProperty(FEATURE_ID)
val textView = TextView(context)
textView.setBackgroundColor(context.resources.getColor(R.color.blueAccent))
textView.setPadding(10, 5, 10, 5)
textView.setTextColor(Color.WHITE)
textView.text = countryName
imagesMap[countryName] = SymbolGenerator.generate(textView)
}
}
return imagesMap
}
override fun onPostExecute(bitmapHashMap: HashMap<String, Bitmap>) {
super.onPostExecute(bitmapHashMap)
mapboxMap?.getStyle { style -> style.addImagesAsync(bitmapHashMap) }
}
}
companion object {
private const val SOURCE_ID = "com.mapbox.mapboxsdk.style.layers.symbol.source.id"
private const val LAYER_ID = "com.mapbox.mapboxsdk.style.layers.symbol.layer.id"
private const val FEATURE_ID = "brk_name"
private const val FEATURE_RANK = "scalerank"
private const val FEATURE_NAME = "name_sort"
private const val FEATURE_TYPE = "type"
private const val FEATURE_REGION = "continent"
}
}

View File

@@ -1,189 +0,0 @@
package com.mapbox.mapboxsdk.testapp.activity.telemetry;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.module.http.HttpRequestUtil;
import com.mapbox.mapboxsdk.testapp.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import timber.log.Timber;
/**
* Test activity showcasing gathering performance measurement data.
*/
public class PerformanceMeasurementActivity extends AppCompatActivity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_simple);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
EventListener eventListener = new EventListener();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.eventListener(eventListener)
.build();
HttpRequestUtil.setOkHttpClient(okHttpClient);
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(
new Style.Builder().fromUri(Style.getPredefinedStyle("Streets"))));
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
HttpRequestUtil.setOkHttpClient(null);
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
private static void triggerPerformanceEvent(String style, long elapsed) {
List<Attribute<String>> attributes = new ArrayList<>();
attributes.add(
new Attribute<>("style_id", style));
attributes.add(
new Attribute<>("test_perf_event", "true"));
List<Attribute<Long>> counters = new ArrayList<>();
counters.add(new Attribute<>("elapsed", elapsed));
JsonObject metaData = new JsonObject();
metaData.addProperty("os", "android");
metaData.addProperty("manufacturer", Build.MANUFACTURER);
metaData.addProperty("brand", Build.BRAND);
metaData.addProperty("device", Build.MODEL);
metaData.addProperty("version", Build.VERSION.RELEASE);
metaData.addProperty("abi", Build.CPU_ABI);
metaData.addProperty("country", Locale.getDefault().getISO3Country());
metaData.addProperty("ram", getRam());
metaData.addProperty("screenSize", getWindowSize());
Gson gson = new Gson();
Bundle bundle = new Bundle();
bundle.putString("attributes", gson.toJson(attributes));
bundle.putString("counters", gson.toJson(counters));
bundle.putString("metadata", metaData.toString());
}
private static String getRam() {
ActivityManager actManager =
(ActivityManager) Mapbox.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
return String.valueOf(memInfo.totalMem);
}
private static String getWindowSize() {
WindowManager windowManager =
(WindowManager) Mapbox.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
return "{" + width + "," + height + "}";
}
private static class EventListener extends okhttp3.EventListener {
private final Map<String, Long> startTimes = new HashMap<>();
@Override
public void callStart(Call call) {
String url = call.request().url().toString();
startTimes.put(url, System.nanoTime());
super.callStart(call);
Timber.e("callStart: %s", url);
}
@Override
public void callEnd(Call call) {
String url = call.request().url().toString();
Timber.e("callEnd: %s", url);
Long start = startTimes.get(url);
if (start != null) {
long elapsed = System.nanoTime() - start;
triggerPerformanceEvent(url.substring(0, url.indexOf('?')), elapsed);
startTimes.remove(start);
Timber.e("callEnd: %s took %d", url, elapsed);
}
super.callEnd(call);
}
}
private static class Attribute<T> {
private String name;
private T value;
Attribute(String name, T value) {
this.name = name;
this.value = value;
}
}
}

View File

@@ -0,0 +1,156 @@
package com.mapbox.mapboxsdk.testapp.activity.telemetry
import android.app.ActivityManager
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.mapbox.mapboxsdk.Mapbox
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.module.http.HttpRequestUtil
import com.mapbox.mapboxsdk.testapp.R
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.OkHttpClient.Builder
import timber.log.Timber
import java.util.*
/**
* Test activity showcasing gathering performance measurement data.
*/
class PerformanceMeasurementActivity : AppCompatActivity() {
private lateinit var mapView: MapView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map_simple)
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
val eventListener = EventListener()
val okHttpClient: OkHttpClient = Builder()
.eventListener(eventListener)
.build()
HttpRequestUtil.setOkHttpClient(okHttpClient)
mapView.getMapAsync(
OnMapReadyCallback { mapboxMap: MapboxMap ->
mapboxMap.setStyle(
Style.Builder().fromUri(Style.getPredefinedStyle("Streets"))
)
}
)
}
override fun onStart() {
super.onStart()
mapView!!.onStart()
}
override fun onResume() {
super.onResume()
mapView!!.onResume()
}
override fun onPause() {
super.onPause()
mapView!!.onPause()
}
override fun onStop() {
super.onStop()
mapView!!.onStop()
}
override fun onLowMemory() {
super.onLowMemory()
mapView!!.onLowMemory()
}
override fun onDestroy() {
HttpRequestUtil.setOkHttpClient(null)
super.onDestroy()
mapView!!.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView!!.onSaveInstanceState(outState)
}
private class EventListener : okhttp3.EventListener() {
private val startTimes: MutableMap<String, Long> = HashMap()
override fun callStart(call: Call) {
val url = call.request().url.toString()
startTimes[url] = System.nanoTime()
super.callStart(call)
Timber.e("callStart: %s", url)
}
override fun callEnd(call: Call) {
val url = call.request().url.toString()
Timber.e("callEnd: %s", url)
val start = startTimes[url]
if (start != null) {
val elapsed = System.nanoTime() - start
triggerPerformanceEvent(url.substring(0, url.indexOf('?')), elapsed)
startTimes.remove(url)
Timber.e("callEnd: %s took %d", url, elapsed)
}
super.callEnd(call)
}
}
private class Attribute<T> internal constructor(private val name: String, private val value: T)
companion object {
private fun triggerPerformanceEvent(style: String, elapsed: Long) {
val attributes: MutableList<Attribute<String>> = ArrayList()
attributes.add(
Attribute("style_id", style)
)
attributes.add(
Attribute("test_perf_event", "true")
)
val counters: MutableList<Attribute<Long>> = ArrayList()
counters.add(Attribute("elapsed", elapsed))
val metaData = JsonObject()
metaData.addProperty("os", "android")
metaData.addProperty("manufacturer", Build.MANUFACTURER)
metaData.addProperty("brand", Build.BRAND)
metaData.addProperty("device", Build.MODEL)
metaData.addProperty("version", Build.VERSION.RELEASE)
metaData.addProperty("abi", Build.CPU_ABI)
metaData.addProperty("country", Locale.getDefault().isO3Country)
metaData.addProperty("ram", ram)
metaData.addProperty("screenSize", windowSize)
val gson = Gson()
val bundle = Bundle()
bundle.putString("attributes", gson.toJson(attributes))
bundle.putString("counters", gson.toJson(counters))
bundle.putString("metadata", metaData.toString())
}
private val ram: String
private get() {
val actManager = Mapbox.getApplicationContext()
.getSystemService(ACTIVITY_SERVICE) as ActivityManager
val memInfo = ActivityManager.MemoryInfo()
actManager.getMemoryInfo(memInfo)
return memInfo.totalMem.toString()
}
private val windowSize: String
private get() {
val windowManager =
Mapbox.getApplicationContext().getSystemService(WINDOW_SERVICE) as WindowManager
val display = windowManager.defaultDisplay
val metrics = DisplayMetrics()
display.getMetrics(metrics)
val width = metrics.widthPixels
val height = metrics.heightPixels
return "{$width,$height}"
}
}
}