GPS?

Monkey Targets Forums/Android/GPS?

Big Jim(Posted 2011) [#1]
Is it possible to read a device's GPS information?


matt(Posted 2011) [#2]
You mean get location data? not as far as I am aware

Platforms that would meet the criteria for this sort of support would be: iOS, Android, HTML5 and... perhaps GLFW?


Big Jim(Posted 2011) [#3]
It'd be a nice to have (since we're doing Android, an iPod development), but not a show stopper. I think Monkey is pretty awesome.


matty(Posted 2011) [#4]
Just bumping this thread - surely there must be some way we can call an "extern" function for Android that returns the location coordinates of the user's position somehow?

I know it is possible to call functions such as the launch email, share app etc (see other threads in Monkey Code section) - but maybe there's a way to return a value as well from one of these function calls?


therevills(Posted 2011) [#5]
Heres a pure Java example how to do it:

http://www.firstdroid.com/2010/04/29/android-development-using-gps-to-get-current-location-2/

So you need to alter the AndroidManifest.xml, add a LocationManager and create a new class to implements LocationListener...

Shouldnt be too hard ;)


matty(Posted 2011) [#6]
I really need to learn Java I think...there's so much goodness hidden away in my little Android phone that Monkey could use if I were to learn how to do this myself....I may have to thankfully - would be good to be able to incorporate so many of the features....


therevills(Posted 2011) [#7]
Okay I've got it to work, but its messy...

You have to hack mojo.android.java :/ or you will get the following error:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()


So here goes...

Create a few new variables called myManager, latitude, longitude in the MonkeyGame Activity and make the Activity implement LocationListener:
public class MonkeyGame extends Activity implements android.location.LocationListener{

	static MonkeyGame activity;
	static MonkeyView view;
	static gxtkApp app;
	
	static String latitude; // new GPS var
	static String longitude; // new GPS var
	private android.location.LocationManager myManager; // new GPS var


In the onCreate method instantiate the manager:
	/** Called when the activity is first created. */
	@Override
	public void onCreate( Bundle savedInstanceState ){	//onStart
		super.onCreate( savedInstanceState );

		activity=this;

		myManager = (android.location.LocationManager) getSystemService(LOCATION_SERVICE); // GPS stuff


Then add the following methods:

	private void startListening() {        
		myManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER,0,0,this);    
	}
		
	private void stopListening() { 
		if (myManager != null)
			myManager.removeUpdates(this);
	}  
 
	@Override   
	public void onLocationChanged(android.location.Location location) {     
		latitude = location.getLatitude() +"";
		longitude = location.getLongitude() +"";
	}  
	@Override    
	public void onProviderDisabled(String provider) {}  
	@Override 
	public void onProviderEnabled(String provider) {}  
	@Override  
	public void onStatusChanged(String provider, int status, Bundle extras) {}


And alter the onStart, onResume, onPause and onDestroy methods:

	@Override
	public void onStart(){		//onResume; onStop
		startListening(); // GPS Stuff
		super.onStart();
	}
	
	@Override
	public void onResume(){		//onPause
		startListening(); // GPS Stuff
		super.onResume();
		view.onResume();
		app.InvokeOnResume();
	}
	
	@Override 
	public void onPause(){		//onResume; onStop
		stopListening(); // GPS Stuff
		super.onPause();
		if( app.dead ) System.exit( 0 );
		view.onPause();
		app.InvokeOnSuspend();
	}

	
	@Override
	public void onDestroy(){
		stopListening(); // GPS Stuff
		super.onDestroy();
	}


Now you can create an extern to get the latitude & longitude variables:
	static String getLatitiude() {
		return MonkeyGame.activity.latitude+"";
	}


Function GetLatitiude:String() = "diddy.getLatitiude"



Hopefully there is a better way...


matty(Posted 2011) [#8]
Wow..thanks, I wasn't expecting you to put the code together but that is really good of you. Thanks, Matt.


therevills(Posted 2011) [#9]
No probs... I like the little challenges... Oh I forgot you also need to alter the AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


Just wish I could do it without hacking mojo...


therevills(Posted 2011) [#10]
I was hoping to get it to work like this in an external java file:

	public static void startGps()
	{
		myManager = (LocationManager)MonkeyGame.activity.getSystemService(Context.LOCATION_SERVICE);

		LocationListener locationListener = new LocationListener() {
			public void onLocationChanged(Location location) {
				// Called when a new location is found by the network location provider.
			}
			public void onStatusChanged(String provider, int status, Bundle extras) {}
			public void onProviderEnabled(String provider) {}
			public void onProviderDisabled(String provider) {}
		};
		myManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); 
	}


Anyone knows why I get the looper error when doing it this way? I think its to due to the UI thread, but Im dont know how to get around it without hacking mojo itself... :(


therevills(Posted 2011) [#11]
WAYHAY!! :D

Samah suggested a possible fix and it worked great :)

So here is working code without hacking mojo:

AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


Extern.java


MonkeyExtern.monkey
Extern
	Function StartGps:Void()="diddy.startGps"
	Function GetLatitiude:String()="diddy.getLatitiude"
	Function GetLongitude:String()="diddy.getLongitude"


And to use call StartGps() once, say OnCreate then call GetLatitiude() and GetLongitude(). Also remember it sometimes takes awhile to get a GPS signal.

Of course I am going add this to Diddy ;)


matty(Posted 2011) [#12]
This is great, thanks - but I'm just wondering - I see there is a "startGPS" function but would it be worth having a "stopGPS" function - or is it unnecessary?


therevills(Posted 2011) [#13]
"stopGPS"


The GPS thread does stop when the application has ended... but yeah I should add it too :)


matty(Posted 2011) [#14]
Strange - the initial set of code with the mojo hack worked fine on my phone but this new one I keep getting "Null Object Error" or a force close if I even check if the string returned by the two Get.. commands is null or not.

Basic code:



I've included the manifest change, and included your code above in my own 'extern' routine:

(basically this is a cut and paste from yours above)


and the following in monkey:



Not sure what is wrong with this.


therevills(Posted 2011) [#15]
Can you try switching StartGps and SetUpdateRate:

Method OnCreate:Int()
	SetUpdateRate 30
	StartGps()
	Return 0
End Method


Also can you check out the Diddy code and try the Function example?


matty(Posted 2011) [#16]
I've already played around with the SetUpdateRate - no difference...

However I'm still fairly new to this and am not sure how to go about the diddy bit since I don't actually have a copy of diddy - when I downloaded it a few minutes ago I wasn't sure where to put the gps stuff.

Edit - however I did get the gps working with the earlier code snipped at the top.


therevills(Posted 2011) [#17]
Are you still using the "hacked" version of Mojo?

Try this:

androidgps.monkey


android.java


And of course after the first compile add this to the AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


Files here:
http://www.mediafire.com/?ystol0vxd4vbwz7

Also I'll put together a tutorial on how to download the source from google code on the Diddy wiki.

[edit]
Done:
http://code.google.com/p/diddy/wiki/HowToInstall
[/edit]


matty(Posted 2011) [#18]
Thanks, will have to have another look tomorrow. I wasn't using the hacked version of mojo..I'd put it back but thanks again will try again tomorrow. You have been very helpful, I should buy you a drink if you're ever in Melbourne.(except that I don't drink, still the offer is there)


Big Jim(Posted 2011) [#19]
Hey TheRevills, sounds like a neat little feature to add to diddy!


therevills(Posted 2011) [#20]
@matty - thanks for the offer... I'm up the road in Adelaide :P

@jim - its already there ;) http://code.google.com/p/diddy/source/detail?r=254


matty(Posted 2011) [#21]
Thanks again - it works perfectly....


matty(Posted 2011) [#22]
Actually - there's a new problem, and it is rather bizarre...or at least I don't understand it.

Try this code:

If I try and store the latitude and longitude in a variable (which is a string) and then test if it is empty or not - the program fails. See below - I've commented out an 'if..endif' block - program runs fine like that, but if I uncomment out the 'if..endif' block then the program crashes (force closes) on my phone.

As you can probably see I am trying to convert the string value of the gps coordinates into a floating point number...but I can't even check if the string is not null, or if it has any value at all...

Strangely I could get this to work with the old mojo hack but for some reason with this code it doesn't like it...

Any ideas?




therevills(Posted 2011) [#23]
Couple of things your can do:

1. Alter the Java code so latitude and longitude are floats and cast location.getLatitude(); to a float:
				public void onLocationChanged(Location location) {
					latitude = (float)location.getLatitude();
					longitude = (float)location.getLongitude();
				}

Then alter the getters to return float instead of string, this will return 0.0 when GPS hasnt found a signal yet.

2. Alter the Java getters so if the latitude or the longitude are null return an empty string:
	static String getLatitiude() {
		if (latitude==null)
			return "";
		return latitude;
	}
	static String getLongitude() {
		if (longitude==null)
			return "";
		return longitude;
	}



matty(Posted 2011) [#24]
Thanks , I realised afterwards I could try that but I don't understand why I can't even test the value of the returned string?


therevills(Posted 2011) [#25]
but I don't understand why I can't even test the value of the returned string?


On my phone it didnt "crash", it displayed a Toast message saying something about a Null value...

Basically, when the GPS signal isnt started the location.getLatitude()/location.getLongitude() methods return null since "location" isnt active yet, so the strings latitude and longitude are null and Java "kindly" outputs that as "null". Then in your test "If slat Then" I "think" monkey isnt trying to convert it into a number and you can not have a null number... I think ;)


matty(Posted 2011) [#26]
This works on my phone - using floats:

"android.java" (in same folder as monkey source "androidgps.monkey")


"androidgps.monkey" - note I'm about to test the distance function to see if it works...




matty(Posted 2011) [#27]
Good Morning all,

After reading blitzsupport's post in the General Help of the blitzbasic forums I updated this program in the post here: (the one above this one basically)

http://www.monkeycoder.co.nz/Community/post.php?topic=1366&post=15570

It now shows the correct distance using the Haversine formula using the GPS on the phone.

I've only tested it in the car park outside work but it seems to work, and it seems to be fine down to quite small distances.

Thanks all for all the help in getting this to work.

Now to use it for something!


MonkeyPlotter(Posted 2016) [#28]
Hi, I attempted to compile this for the Android target but received the following error:

(Also, I'd to add a couple of return 0 lines within Method OnUpdate(). One concern I have is Monkey seems to be using buildv79e when I was expecting it to use V86e, also investigating this.)


-compile:
[javac] Compiling 3 source files to E:\Monkey_Dev_WC\trunk\MonkeyXPro86e\GPS_Finder\androidgps.buildv79e\android\bin\classes
[javac] warning: [options] source value 1.5 is obsolete and will be removed in a future release
[javac] warning: [options] target value 1.5 is obsolete and will be removed in a future release
[javac] warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
[javac] E:\Monkey_Dev_WC\trunk\MonkeyXPro86e\GPS_Finder\androidgps.buildv79e\android\src\com\monkeycoder\monkeygame\MonkeyGame.java:2782: error: cannot find symbol
[javac] myManager = (LocationManager)MonkeyGame.activity.getSystemService(Context.LOCATION_SERVICE);
[javac] ^
[javac] symbol: variable activity
[javac] location: class MonkeyGame
[javac] E:\Monkey_Dev_WC\trunk\MonkeyXPro86e\GPS_Finder\androidgps.buildv79e\android\src\com\monkeycoder\monkeygame\MonkeyGame.java:2797: error: cannot find symbol
[javac] MonkeyGame.activity.runOnUiThread(new Runnable() {
[javac] ^
[javac] symbol: variable activity
[javac] location: class MonkeyGame
[javac] Note: E:\Monkey_Dev_WC\trunk\MonkeyXPro86e\GPS_Finder\androidgps.buildv79e\android\src\com\monkeycoder\monkeygame\MonkeyGame.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.

[javac] 2 errors
[javac] 3 warnings
BUILD FAILED
C:\android-sdk-windows\tools\ant\build.xml:716: The following error occurred while executing this line:
TRANS FAILED: Android build failed.
C:\android-sdk-windows\tools\ant\build.xml:730: Compile failed; see the compiler error output for details.




I am about to see if I can locate the compiler error output for more details.....