Hi there. I'm a somewhat experienced Scala dev who's *very* new to Android development and Macroid, but am very excited to learn more, stick around and contribute, so hoping folks will bear with my n00b-ishness for a sec.
I'm making a simple location-sharing Android app, and step 1 is to make an Activity in which the user clicks a button and the app shows them their lat/lon. I've worked through all the Macroid docs and the first few sections of the
Android API and was trying to translate
this example java code from Google into the context of a Macroid app.
This is what I've got so far (also pasted below my signature). I'm still a bit hazy on how to handle slots and passing completed futures into the Ui code, so that code might be futzy, but what I'm really focused on at the moment is the call to `buildClient` on
line 58:
def buildClient: Option[GoogleApiClient] = {
this.synchronized {
Some(
new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()) } }
Currently, that function is triggering the following runtime error, which crashes the app:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference
As
best I can tell that's because there's some sort of friction between how I'm including the context in Macroid (which I assume is using implicits):
class MainActivity extends Activity with Contexts[Activity]
with ConnectionCallbacks with OnConnectionFailedListener {
and how Java wants to look for them when it uses the Activity instance to pass to the API client user. But once I get to that depth, I'm lost.
Can anyone help point me in the right direction?
Best,
Austin
PS: Here's the full code for the Activity in question:
package org.tlc.whereat.components.activities
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.{Button, LinearLayout, TextView}
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.common.api.GoogleApiClient.{ConnectionCallbacks, OnConnectionFailedListener}
import com.google.android.gms.location.LocationServices
import macroid.Contexts
import macroid.FullDsl._
import org.tlc.whereat.ui.tweaks.MainTweaks
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Promise
/**
* Author: @aguestuser
* Date: 4/22/15
* License: GPLv2 (https://www.gnu.org/licenses/gpl-2.0.html)
*/
class MainActivity extends Activity with Contexts[Activity] with ConnectionCallbacks with OnConnectionFailedListener { // include implicit contexts
var context = activityActivityContext
var apiClient: Option[GoogleApiClient] = None
var locView: Option[TextView] = slot[TextView]
val locText: Promise[String] = Promise[String]()
override protected def onCreate(savedInstanceState: Bundle): Unit = {
super .onCreate(savedInstanceState)
apiClient = buildClient
setContentView {
getUi {
l[LinearLayout](
w[Button] <~
text("Get Location") <~
On.click {
locView <~ show
},
w[TextView] <~
wire(locView) <~
locText.future.map(text)
) <~ MainTweaks.orient } } }
override protected def onStart(): Unit = {
apiClient.get.connect() }
override protected def onStop(): Unit = {
super.onStop()
if (apiClient.get.isConnected) apiClient.get.disconnect() }
def buildClient: Option[GoogleApiClient] = {
this.synchronized {
Some(
new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build()) } }
override def onConnected(connectionHint: Bundle): Unit = {
val loc = LocationServices.FusedLocationApi.getLastLocation(apiClient.get)
if (loc != null) locText.success{ s"Lat: ${loc.getLatitude}, Lon: ${loc.getLongitude}" }
else toast("No location detected!") <~long <~fry }
override def onConnectionFailed(res: ConnectionResult): Unit = {
Log.i("whereat", "Connection failed: ConnectionResult.getErrorCode() = " + res.getErrorCode) }
override def onConnectionSuspended(cause: Int) {
Log.i("whereat", "Connection suspended")
apiClient.get.connect() }
}