A Wrapper of Android Google Maps API for Scala.

ScalaMap is a wrapper of Android Google Maps API for Scala.

Sorry for my poor English, but I think this may be useful if you wnat develop Android w/ Google Maps API application using Scala.

Overview

Currently, it's not easy to use Android's Google Maps API for two reasons.

  • There is a bug in Scala compiler. If a Java library reference to a static inner class in another Java library, the compiler will complain that "classfile is broken" (Scala 2.7.7) or "Missing dependency" (Scala 2.8).

    • Unfortunately, it is what happened in MapView, it return ViewGroup.LayoutParams in several public methods.
  • Scala cannot access Java protected static classes / fields / methods.

    • That is what happened in ItemizedOverlay, where you should call protected static method boundCenter(Drawable drawable) or boundCenterBottom (Drawable drawable) in subclass's constructor.

To overcome this problem, I've created a simple wrapper library located at this GitHub repository. It's not prefect and has a lot limitations , but I think it should work.

License

This library is release under GNU Lesser General Public License. See COPYING AND COPYING.LESSER for details.

Install

This wrapper library use SBT (Simple Build Tool) as build system, it is not required, but will make things easier. You should install it.

  1. Download and install SBT following this instruction, it should be easy.
  2. Download the source code of ScalaMap.
  3. Unzip it to a directory called scalamap/
  4. Copy your android.jar and maps.jar library files to scalamap/lib/
  5. $ cd scalamap/
  6. $ sbt package
  7. After step 7, you should get a JAR file called scalamap-0.0.1.jar under target/ directory.

USAGE

  • Remember adding scalamap-0.0.1.tar.gz to your classpath when you compile your project.

  • Take a look at the example code below and project under demo/ directory.

  • Import org.maidroid.scalamap._

  • Basically, you could use the following code to create a SMapView object, where R.id.mapview is pointed to a MapView object in layout file.

  • val sMapView = new SMapView (findViewById (R.id.mapview))

  • You should be able to use a SMapView object just like an ordinary MapView, but remember, it is a wrapper using composition instead of inheritance, so there are some methods is not implemented in this wrapper.

NOTE

  • If you need MapController, use sMapView.getSMapController() to get a SMapController wrapper object.

  • If you need hook listener to a MapView, use sMapView.getViewGroup() to get the MapView object as instance of ViewGroup.

  • DO NOT USE sMapView.getMapView() / s or you will get a compiler error message like "class is borken", YOU'VE BEEN WARNED.

  • There are two minor API difference:

  • The constructor of SItemizedOverlay is (Drawable drawalbe, int mode), where mode is one of BOUND_CENTER, BOUND_CENTER_BOOTOM, and NO_BOUND in SItemizedOverlay.
  • SMapView.setReticleDrawMode takes an arguement of type Int, which is one of the following three value: SMapView.DRAW_RETICLE_NEVER, SMapView.DRAW_RETICLE_OVER, and SMapView.DRAW_RETICLE_UNDER.

CODE EXAMPLE

This is the code example corresponding to the tutorial Hellp, MapView on Android Developer site.

package org.bone;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ZoomControls;
import android.widget.LinearLayout;

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Overlay;

import org.maidroid.scalamap.SMapView

class HelloMap extends MapActivity
{
    private lazy val layout      = findViewById (R.id.zoomview).
                                   asInstanceOf[LinearLayout]
    private lazy val mapView     = new SMapView (findViewById(R.id.mapview))
    private lazy val mapOverlays = mapView.getOverlays
    private lazy val drawable    = getResources.
                                   getDrawable (R.drawable.androidmarker)
    private lazy val itemizedoverlay = new HelloItemizedOverlay (drawable)


    override def isRouteDisplayed = false
    override def onCreate(savedInstanceState: Bundle)
    {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.main)

        mapView.setBuiltInZoomControls (true)

        val point1 = new GeoPoint (19240000, -99120000)
        val point2 = new GeoPoint(35410000, 139460000)

        val overlayitem1 = new OverlayItem (point1, "", "")
        val overlayitem2 = new OverlayItem (point2, "", "")

        itemizedoverlay.addOverlay (overlayitem1)
        itemizedoverlay.addOverlay (overlayitem2)

        mapOverlays.add (itemizedoverlay)
    }
}
package org.bone

import android.graphics.drawable.Drawable
import com.google.android.maps.OverlayItem
import java.util.ArrayList

import org.maidroid.scalamap.SItemizedOverlay
import SItemizedOverlay.BOUND_CENTER_BOTTOM

class HelloItemizedOverlay (drawable: Drawable) extends 
      SItemizedOverlay[OverlayItem] (drawable, BOUND_CENTER_BOTTOM)
{
    private lazy val mOverlays = new ArrayList[OverlayItem]

    override def createItem (i: Int) = mOverlays.get(i)
    override def size () = mOverlays.size() 

    def addOverlay (overlay: OverlayItem)
    {
        mOverlays.add (overlay);
        populate ();
    }
}

回響