Skip to content

Instantly share code, notes, and snippets.

@cosmith
Created November 1, 2015 23:07
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save cosmith/1124ddef29e084729204 to your computer and use it in GitHub Desktop.
Save cosmith/1124ddef29e084729204 to your computer and use it in GitHub Desktop.
RN Geolocation
/**
* @providesModule GenericGeolocation
*/
"use strict";
var Platform = require("Platform");
if (Platform.OS === "android") {
var Manager = require("react-native").NativeModules.TruckflyGeolocationManager;
var GenericGeolocation = {
getCurrentPosition: function (onSuccess, onError, options) {
Manager.getCurrentPosition(options.timeout, options.maximumAge, options.enableHighAccuracy,
onSuccess, onError);
},
};
} else {
var GenericGeolocation = require("Geolocation");
}
module.exports = GenericGeolocation;
package com.yourapp.rctgeolocation;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableNativeMap;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
/**
* Created by corentin on 10/29/15.
*/
public class GeolocationModule extends ReactContextBaseJavaModule {
private GoogleApiClient mGoogleApiClient;
public GeolocationModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "TruckflyGeolocationManager";
}
/**
* @param timeout
* @param maximumAge
* @param enableHighAccuracy true -> PRIORITY_HIGH_ACCURACY
* false -> PRIORITY_BALANCED_POWER_ACCURACY
* @param onSuccess
* @param onError
*/
@SuppressWarnings("unused")
@ReactMethod
public void getCurrentPosition(final Integer timeout,
final Integer maximumAge,
final Boolean enableHighAccuracy,
final Callback onSuccess,
final Callback onError) {
if (onSuccess == null) {
Log.e(getName(), "no success callback");
return;
}
if (onError == null) {
Log.e(getName(), "no error callback");
return;
}
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(getReactApplicationContext())
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle connectionHint) {
Log.d(getName(), "onConnected");
_getLastKnownLocation(onSuccess, onError, timeout,
maximumAge, enableHighAccuracy);
}
@Override
public void onConnectionSuspended(int cause) {
Log.e(getName(), "onConnectionSuspended: " + cause);
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.e(getName(), "onConnectionFailed");
onError.invoke();
mGoogleApiClient.disconnect();
}
})
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
else if (mGoogleApiClient.isConnected()) {
_getLastKnownLocation(onSuccess, onError, timeout, maximumAge, enableHighAccuracy);
}
else {
mGoogleApiClient.connect();
}
}
private void _getLastKnownLocation(final Callback onSuccess,
final Callback onError,
Integer timeout,
Integer maximumAge,
Boolean enableHighAccuracy) {
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (lastLocation == null) {
Log.e(getName(), "lastLocation null");
onError.invoke();
return;
}
Log.e(getName(), "lastLocation found: " + lastLocation.toString());
WritableNativeMap result = new WritableNativeMap();
WritableNativeMap coords = new WritableNativeMap();
coords.putDouble("latitude", lastLocation.getLatitude());
coords.putDouble("longitude", lastLocation.getLongitude());
result.putMap("coords", coords);
onSuccess.invoke(result);
}
}
package com.yourapp.rctgeolocation;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by corentin on 10/29/15.
*/
public class GeolocationPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new GeolocationModule(reactContext));
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
@cosmith
Copy link
Author

cosmith commented Nov 1, 2015

You need to add the package in your MainActivity.java and add compile 'com.google.android.gms:play-services-location:8.1.0' to your app/build.gradle

@Tiagojdferreira
Copy link

Thanks man. I am trying to get it to work, but since this is my first time developing with native android code I am a bit lost.
I have started by replacing yourapp in package com.yourapp.rctgeolocation; with the actual name of my app.
Then, I have added the java files within my Android folder in the following path:

android/app/src/main/java/com/<myapp>/rtcgeolocation

And the javascript as a component within my normal javascript folder (App/Components/)

Then I added compile 'com.google.android.gms:play-services-location:8.1.0' to my build gradle.

When I require GenericGeolocation I got an error:

undefined is not an object (evaluating 'Manager.getCurrentPostion')

Coming from line 14: Manager.getCurrentPosition(...)

@Tiagojdferreira
Copy link

if I add .addPackage(new GeolocationPackage()) I get an error during the build:

MainActivity.java:29: error: cannot find symbol
                .addPackage(new GeolocationPackage())

@Tiagojdferreira
Copy link

@cosmith
I somewhat got it to work. I have managed to build the whole thing, but when calling the getCurrentLocation function I run into the following issue:

TypeError: expected dynamic type 'double', but had type 'null' ... at argument index 0

I am calling the function as follows:

GenericGeolocation.getCurrentPosition(
      20000,
      1000,
      true,
      (initialPosition) => this.setState({initialPosition}),
      (error) => console.log(error.message)
    );

@Tiagojdferreira
Copy link

I just noticed you use the argument structure of (onSuccess, onError, options). By applying it I always get the code to execute the onError callback. How can I debug the actual java code ?

P.S.: My onError is just a (error) => console.log(error) to which it prints undefined to the console

@Tiagojdferreira
Copy link

I was missing in my AndroidManifest. It works :) Awesome! How did you display a map, considering you don't have the MapView component for Android?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment