Want to dive even deeper?

Take the course Android Lollipop 5.0 : Ultimate Tutorial for App Development by Eduonix and become an expert!
Android Lollipop 5.0 : Ultimate Tutorial for App Development
by Eduonix

Check it out!
You're watching a preview of this video, click the button on the left to puchase the full version from Richard Warburton's Channel.

Getting around with Google Maps Android API v2

As part of the Google Play services - a platform that offers a better integration with Google products - Google recently released perhaps one of the most frequently requested upgrade: the Google Maps Android API v2. This new framework allows you to embed standard or customized maps directly in your application. Now Google Maps Android API v2 lets you leverage Google's beautiful new vector based maps. In this session, we will learn about the new API and features introduced with Google Maps Android API v2 and how to start visualizing information geographically within your applications.

Published on
  • 1.438
  • 3
  • 0
  • 3
  • 0
  • Getting around with GOOGLE MAPS ANDROID API V2
  • @ CYRILMOTTIER
  • I once made a LOVELY & GOOD-LOOKING mobile app
  • I once made a LOVELY & GOOD-LOOKING mobile app
  • IT
 LOOKED LIKE THIS Myapp 1001 - Lorem ipsum amet Lorem ipsum amet 1002 - Lorem ipsum amet Lorem ipsum amet 1003 - Lorem ipsum amet Lorem ipsum amet 1004 - Lorem ipsum amet Lorem ipsum amet 1005 - Lorem ipsum amet Lorem ipsum amet 1006 - Lorem ipsum amet Lorem ipsum amet 1007 - Lorem ipsum amet Lorem ipsum amet 1008 - Lorem ipsum amet Lorem ipsum amet 1009 - Lorem ipsum amet Lorem ipsum amet
  • I started to do some quick USER TESTING
  • “That’s a pretty nice list of thingy things” – John Doe
  • “It sucks” – John Doe’s translator
  • Lists-based screens are boring and give no geographic context
  • Maps give the user some clear context on POI LOCATION
  • Maps give the user some clear context on POI LOCATION USER LOCATION
  • Maps give the user some clear context on POI LOCATION USER LOCATION DISTANCES
  • Maps give the user some clear context on POI LOCATION USER LOCATION DISTANCE DIRECTIONS
  • Maps give the user some clear context on POI LOCATION USER LOCATION DISTANCES DIRECTIONS
  • GOOGLE MAPS ANDROID API V2 TO THE RESCUE
  • Myapp Lorem ipsum park Map-based apps m t Lorem ipsum mall Lorem ipsum amet are immersive re Lo um ips e am
  • Myapp Lorem ipsum park Map-based apps m t and that’s awesome :) Lorem ipsum mall Lorem ipsum amet are immersive re Lo um ips e am
  • 1 Introducing MAPS API V2
  • v1 vs v2
  • v1 vs v2
  • v1 ed t ca re p e D vs v2
  • EXTREMELY STRAIGHTFORWARD API
  • Initial [Support]MapFragment setup 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class TestActivity extends FragmentActivity {! private GoogleMap mMap;! ! @Override! protected void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.activity_marker);! setUpMapIfNeeded();! }! ! @Override! protected void onResume() {! super.onResume();! setUpMapIfNeeded();! }! ! private void setUpMapIfNeeded() {! if (mMap == null) {! mMap = ((SupportMapFragment) getSupportFragmentManager().! findFragmentById(R.id.map)).getMap();! if (mMap != null) {! setUpMap();! }! }! }! ! private void setUpMap() { /* TODO */ }! }
  • Annotating with Markers 1 2 3 4 5 6 7 8 9 10 11 12 13 14 private static final LatLng LYON = new LatLng(45.764043, 4.835659);! ! private Marker mMarker;! ! private void setUpMap() {! mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LYON, 6));! ! mMarker = mMap.addMarker(new MarkerOptions().! position(LYON).! title("Lyon").! snippet("City of Lights").! icon(BitmapDescriptorFactory.! defaultMarker(BitmapDescriptorFactory.HUE_RED)));! }
  • Annotating with Markers 1 2 3 4 5 6 7 8 9 10 11 12 13 14 private static final LatLng LYON = new LatLng(45.764043, 4.835659);! ! private Marker mMarker;! ! private void setUpMap() {! mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LYON, 6));! ! mMarker = mMap.addMarker(new MarkerOptions().! position(LYON).! title("Lyon").! snippet("City of Lights").! icon(BitmapDescriptorFactory.! defaultMarker(BitmapDescriptorFactory.HUE_RED)));! }
  • Drawing shapes on MapView 3SHAPES POSSIBLE
  • Drawing shapes on MapView 3SHAPES POSSIBLE Polyline
  • Drawing shapes on MapView 3SHAPES POSSIBLE Polyline | Polygon
  • Drawing shapes on MapView 3SHAPES POSSIBLE Polyline | Polygon | Circle
  • Drawing shapes on MapView 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private void setUpMap() {! mMap.addCircle(getCircleOptions(new LatLng(45.8, 4.8), 20000));! mMap.addCircle(getCircleOptions(new LatLng(46.03, 4.6), 10000));! mMap.addCircle(getCircleOptions(new LatLng(46.03, 5), 10000));! }! ! private CircleOptions mCircleOptions = new CircleOptions();! ! private CircleOptions getCircleOptions(LatLng center,! double radius) {! final float w = 4 * getResources().getDisplayMetrics().density;! return mCircleOptions.! center(center).! radius(radius).! strokeWidth(w).! strokeColor(Color.RED);! }
  • Overlaying map with GroundOverlay 1 2 3 4 5 6 7 8 9 10 11 private static final LatLng NEWARK = new LatLng(40.71408, -74.22869);! ! private void setUpMap() {! mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(NEWARK, 11));! ! mMap.addGroundOverlay(new GroundOverlayOptions().! image(BitmapDescriptorFactory.! fromResource(R.drawable.newark_1922)).! anchor(0, 1).! position(NEWARK, 8600f, 6500f));! }
  • Rendering custom tiles with TileOverlay 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private static final String MOON_MAP_URL_FORMAT =! "http://www.google.moon/bw/%d/%d/%d.jpg";! ! private void setUpMap() {! mMap.setMapType(GoogleMap.MAP_TYPE_NONE);! ! TileProvider tileProvider = new UrlTileProvider(256, 256) {! @Override! public synchronized URL getTileUrl(int x, int y, int zoom) {! String s = String.format(Locale.US,! MOON_MAP_URL_FORMAT, x, y, zoom);! try {! return new URL(s);! } catch (MalformedURLException e) {! throw new AssertionError(e);! }! }! };! ! mMap.addTileOverlay(new TileOverlayOptions().! tileProvider(tileProvider));! }
  • 2 Deep dive into THE INTERNALS
  • Google Maps Android API v2 is part of Google Play Services
  • YOUR APP
  • Maps API YOUR APP
  • Maps API YOUR APP GMS SERVICE
  • Maps API YOUR APP GMS SERVICE
  • Maps API YOUR APP PLAY STORE GMS SERVICE
  • EVERYTHING EVERYTHING EVERYTHING EVERYTHING IS PARCELABLE EVERYTHING EVERYTHING EVERYTHING
  • Each call to the API is a done through a Binder … slo … and it may be w ols w
  • A VIEW MAY HIDE ANOTHER
  • TextureView API 16+ SurfaceView API 15-
  • 1 Only Bitmaps can be rendered 2 No Drawable/View automatic refresh 3 No direct Canvas-based rendering
  • You must be on the UI THREAD WHEN CALLING ANY METHOD ON any VIEW
  • You must be on the UI THREAD WHEN CALLING ANY METHOD ON any GOOGLEMAP
  • 3 Google Maps Android API v2 TIPS AND TRICKS
  • Attaching information to Markers
  • Attaching information to Markers
  • Attaching information to Markers
  • Use a MAPPING COLLECTION Map<K, V> HashMap | LinkedHashMap | ArrayMap
  • Use a MAPPING COLLECTION Map<K, V> HashMap | LinkedHashMap | ArrayMap NEW
  • Attaching information to Markers 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private Map<Marker, Integer> mMarkerPositions = new HashMap<Marker, Integer>();! private Cursor mCursor;! ! private void setUpMap() {! updatePois();! }! ! private void updatePois() {! mMarkerPositions.clear();! if (mMap != null) {! mMap.clear();! if (mCursor != null) {! final MarkerOptions markerOptions = new MarkerOptions();! while (mCursor.moveToNext()) {! final Marker marker = mMap.addMarker(markerOptions.! position(new LatLng(! mCursor.getDouble(PoisQuery.LAT),! mCursor.getDouble(PoisQuery.LNG))));! mMarkerPositions.put(marker, mCursor.getPosition());! }! }! }! }!
  • 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 mCursor.getDouble(PoisQuery.LAT),! mCursor.getDouble(PoisQuery.LNG))));! mMarkerPositions.put(marker, mCursor.getPosition());! Attaching information to Markers }! }! }! }! ! private final LoaderManager.LoaderCallbacks<Cursor> mLoaderCallbacks =! new LoaderManager.LoaderCallbacks<Cursor>() {! @Override! public Loader<Cursor> onCreateLoader(int id, Bundle args) {! return new CursorLoader(getBaseContext() /* ... */);! }! ! @Override! public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {! mCursor = cursor;! updatePois();! }! ! @Override! public void onLoaderReset(Loader<Cursor> loader) {! mCursor = null;! updatePois();! }! };
  • The “be” attitude BE lazy when possible mindful on memory nice with users
  • 1 private void setUpMap() {! 2 mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {! 3 @Override! 4 public View getInfoWindow(Marker marker) {! 5 return null;! 6 }! 7 ! 8 @Override! 9 public View getInfoContents(Marker marker) {! 10 Integer position = mMarkerPositions.get(marker);! 11 if (position == null || mCursor == null) {! 12 return null;! 13 }! 14 mCursor.moveToPosition(position);! 15 marker.setTitle(mCursor.getString(PoisQuery.TITLE));! 16 marker.setSnippet(mCursor.getString(PoisQuery.SUBTITLE));! 17 return null;! 18 }! 19 });! 20 //...! 21 }
  • Animate state transitions
  • Animate state transitions
  • No actual animation support in GOOGLE MAPS ANDROID API V2
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class LatLngEvaluator implements TypeEvaluator<LatLng> {! ! @Override! public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {! double endValueLng = endValue.longitude;! ! // Take the shortest path across the 180th meridian.! double lngDelta = startValue.longitude - endValue.longitude;! if (Math.abs(lngDelta) >= 180) {! endValueLng = endValue.longitude + Math.signum(lngDelta) * 360;! }! ! double newLat = eval(fraction, startValue.latitude, endValue.latitude);! double newLng = eval(fraction, startValue.longitude, endValueLng);! return new LatLng(newLat, newLng);! }! ! private static double eval(float fraction, double startValue, double endValue) {! return startValue + fraction * (endValue - startValue);! }! }
  • SOLUTION Do it ON YOUR OWN!
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class LatLngEvaluator implements TypeEvaluator<LatLng> {! ! @Override! public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {! double endValueLng = endValue.longitude;! ! // Take the shortest path across the 180th meridian.! double lngDelta = startValue.longitude - endValue.longitude;! if (Math.abs(lngDelta) >= 180) {! endValueLng = endValue.longitude + Math.signum(lngDelta) * 360;! }! ! double newLat = eval(fraction, startValue.latitude, endValue.latitude);! double newLng = eval(fraction, startValue.longitude, endValueLng);! return new LatLng(newLat, newLng);! }! ! private static double eval(float fraction, double startValue, double endValue) {! return startValue + fraction * (endValue - startValue);! }! }
  • 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private static final LatLngEvaluator LAT_LNG_EVALUATOR = new LatLngEvaluator();! private static final Property<Marker, LatLng> MARKER_POSITION_PROPERTY =! Property.of(Marker.class, LatLng.class, "position");! ! private static final LatLng LYON = new LatLng(45.764043, 4.835659);! private static final LatLng PARIS = new LatLng(48.856614, 2.3522219);! ! private LatLng mCurrentDest = LYON;! private Marker mMarker;! private ObjectAnimator mMarkerAnimator;! ! private void setUpMap() {! mMap.setOnMarkerClickListener(mOnMarkerClickListener);! mMarker = mMap.addMarker(new MarkerOptions().position(mCurrentDest));! }! ! ! ! ! ! ! ! !
  • 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 ! ! ! ! ! ! private final GoogleMap.OnMarkerClickListener mOnMarkerClickListener =! new GoogleMap.OnMarkerClickListener() {! @Override! public boolean onMarkerClick(Marker marker) {! mCurrentDest = mCurrentDest.equals(LYON) ? PARIS : LYON;! if (mMarkerAnimator == null) {! mMarkerAnimator = ObjectAnimator.ofObject(mMarker,! MARKER_POSITION_PROPERTY,! LAT_LNG_EVALUATOR,! mCurrentDest);! } else {! mMarkerAnimator.setObjectValues(mCurrentDest);! }! mMarkerAnimator.start();! return true;! }! };!
  • config.proguard -keepclassmembers public class! com.google.android.gms.maps.model.Marker {! void setPosition(***);! *** getPosition();! }
  • Need more? googlemaps.github.io/android-maps-utils/
  • Thank you! @cyrilmottier cyrilmottier.com

Comments

Be the first one to add a comment

No Data Found