The Friend Finder - MapActivity using GPS - Part: II / II
>> Back to Part I <<
>> Part II / II <<
View: >> Full Source for this Tutorial <<
(click here for basic information on this Tutorial)
>> Part II / II <<
View: >> Full Source for this Tutorial <<
(click here for basic information on this Tutorial)


0. Create a new Class called "FriendFinderMap.java" (extending MapActivity)in the same source-folder/package where "FriendFinderMap.java" is located.
In order to make this second Activity startable through an Intent (what is the way you open other Activities in Android), we have to register that new Activity in the AndroidManifest.xml .
Using xml Syntax Highlighting
- // ....
- </activity>
- <activity class=".FriendFinderMap" android:label="@string/map_title">
- <intent-filter>
- <action android:value="android.intent.action.VIEW" />
- <category android:value="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
Parsed in 0.002 seconds, using GeSHi 1.0.8.4
1. So we add the following lines to 'FriendFinder.java' to get obtain our own menu.
Using java Syntax Highlighting
- /** Called only the first time the options menu is displayed.
- * Create the menu entries.
- * Menus are added in the order they are hardcoded. */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- boolean supRetVal = super.onCreateOptionsMenu(menu);
- menu.add(0, 0, getString(R.string.main_menu_open_map));
- return supRetVal;
- }
- @Override
- public boolean onOptionsItemSelected(Menu.Item item) {
- switch (item.getId()) {
- case 0:
- startSubActivity(new Intent(this, FriendFinderMap.class), 0);
- return true;
- }
- return false;
- }
Parsed in 0.032 seconds, using GeSHi 1.0.8.4
There will be no further changes to 'FriendFinder.java'.
2. Lets take a look at 'FriendFinderMap.java's onCreate(...)-method:
It bascially does the same as the FriendFinder(List) but also some Map-Setup and some Graphic/Overlay-Preparation.
Using java Syntax Highlighting
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- /* Create a new MapView and show it */
- this.myMapView = new MapView(this);
- this.setContentView(myMapView);
- /* MapController is capable of zooming
- * and animating and stuff like that */
- this.myMapController = this.myMapView.getController();
- /* With these objects we are capable of
- * drawing graphical stuff on top of the map */
- this.myOverlayController = this.myMapView.createOverlayController();
- MyLocationOverlay myLocationOverlay = new MyLocationOverlay();
- this.myOverlayController.add(myLocationOverlay, true);
- this.myMapController.zoomTo(2); // Far out
- // Initialize the LocationManager
- this.myLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
- this.updateView();
- /* Prepare the things, that will give
- * us the ability, to receive Information
- * about our GPS-Position. */
- this.setupForGPSAutoRefreshing();
- /* Update the list of our friends once on the start,
- * as they are not(yet) moving, no updates to them are necessary */
- this.refreshFriendsList(NEARFRIEND_MAX_DISTANCE);
- }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4
3. As the 'refreshFriendsList(...) method does the same as in the first Class ot 99,9% I wont repeat the code here. What it does is putting all friends closer than 'NEARFRIEND_MAX_DISTANCE' to the field 'this.nearFriends'.
4. The same procedure for 'setupForGPSAutoRefreshing()', it it even 100% the same as in the first Class. Also the same for the IntenReceiver, IntentFilter, onFreeze() and onResume()
5. The function that was called updateList in the first Class is nwo called updateView() and does not much except updating our own GPS-Location and calling 'myMapView.invalidate()' what causes a full redraw of your MapView, what leads a draw()-call in our 'MyLocationOverlay'-Class and in the end to a moving circle (== us) on the screen.

Using java Syntax Highlighting
- private void updateView() {
- // Refresh our gps-location
- this.myLocation = myLocationManager.getCurrentLocation("gps");
- /* Redraws the mapViee, which also makes our
- * OverlayController redraw our Circles and Lines */
- this.myMapView.invalidate();
- /* As the location of our Friends is static and
- * for performance-reasons, we do not call this */
- // this.refreshFriendsList(NEARFRIEND_MAX_DISTANCE);
- }
Parsed in 0.035 seconds, using GeSHi 1.0.8.4
6. What is different in this Class is the way of visualizing data (in the Map not in a List this time). In onCreate we created an Object of the type MyLocationOverlay, which is doing its work everytime the MapView is being redrawn.
Using java Syntax Highlighting
- MyLocationOverlay myLocationOverlay = new MyLocationOverlay();
Parsed in 0.035 seconds, using GeSHi 1.0.8.4
The MyLocationOverlay-class looks the following, as the method is heavily commented I'll just paste it here:
Using java Syntax Highlighting
- /**
- * This method is so huge,
- * because it does a lot of FANCY painting.
- * We could shorten this method to a few lines.
- * But as users like eye-candy apps <img src="http://www.anddev.org/images/smilies/wink.png" alt=";)" title="Wink" /> ...
- */
- protected class MyLocationOverlay extends Overlay {
- @Override
- public void draw(Canvas canvas, PixelCalculator calculator, boolean shadow) {
- super.draw(canvas, calculator, shadow);
- // Setup our "brush"/"pencil"/ whatever...
- Paint paint = new Paint();
- paint.setTextSize(14);
- // Create a Point that represents our GPS-Location
- Double lat = FriendFinderMap.this.myLocation.getLatitude() * 1E6;
- Double lng = FriendFinderMap.this.myLocation.getLongitude() * 1E6;
- Point point = new Point(lat.intValue(), lng.intValue());
- int[] myScreenCoords = new int[2];
- // Converts lat/lng-Point to OUR coordinates on the screen.
- calculator.getPointXY(point, myScreenCoords);
- // Draw a circle for our location
- RectF oval = new RectF(myScreenCoords[0] - 7, myScreenCoords[1] + 7,
- myScreenCoords[0] + 7, myScreenCoords[1] - 7);
- // Setup a color for our location
- paint.setStyle(Style.FILL);
- paint.setARGB(255, 80, 150, 30); // Nice strong Android-Green
- // Draw our name
- canvas.drawText(getString(R.string.map_overlay_own_name),
- myScreenCoords[0] +9, myScreenCoords[1], paint);
- // Change the paint to a 'Lookthrough' Android-Green
- paint.setARGB(80, 156, 192, 36);
- paint.setStrokeWidth(1);
- // draw an oval around our location
- canvas.drawOval(oval, paint);
- // With a black stroke around the oval we drew before.
- paint.setARGB(255,0,0,0);
- paint.setStyle(Style.STROKE);
- canvas.drawCircle(myScreenCoords[0], myScreenCoords[1], 7, paint);
- int[] friendScreenCoords = new int[2];
- //Draw each friend with a line pointing to our own location.
- for(Friend aFriend : FriendFinderMap.this.nearFriends){
- lat = aFriend.itsLocation.getLatitude() * 1E6;
- lng = aFriend.itsLocation.getLongitude() * 1E6;
- point = new Point(lat.intValue(), lng.intValue());
- // Converts lat/lng-Point to coordinates on the screen.
- calculator.getPointXY(point, friendScreenCoords);
- if(Math.abs(friendScreenCoords[0]) < 2000 && Math.abs(friendScreenCoords[1]) < 2000){
- // Draw a circle for this friend and his name
- oval = new RectF(friendScreenCoords[0] - 7, friendScreenCoords[1] + 7,
- friendScreenCoords[0] + 7, friendScreenCoords[1] - 7);
- // Setup a color for all friends
- paint.setStyle(Style.FILL);
- paint.setARGB(255, 255, 0, 0); // Nice red
- canvas.drawText(aFriend.itsName, friendScreenCoords[0] +9,
- friendScreenCoords[1], paint);
- // Draw a line connecting us to the current Friend
- paint.setARGB(80, 255, 0, 0); // Nice red, more look through...
- paint.setStrokeWidth(2);
- canvas.drawLine(myScreenCoords[0], myScreenCoords[1],
- friendScreenCoords[0], friendScreenCoords[1], paint);
- paint.setStrokeWidth(1);
- // draw an oval around our friends location
- canvas.drawOval(oval, paint);
- // With a black stroke around the oval we drew before.
- paint.setARGB(255,0,0,0);
- paint.setStyle(Style.STROKE);
- canvas.drawCircle(friendScreenCoords[0], friendScreenCoords[1], 7, paint);
- }
- }
- }
- }
Parsed in 0.048 seconds, using GeSHi 1.0.8.4
7. The very last thing we need to do is to add some HotKeys and the Menu, both for Toggling the Sattelite-View and zooming in/out.
Using java Syntax Highlighting
- // Called only the first time the options menu is displayed.
- // Create the menu entries.
- // Menu adds items in the order shown.
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- boolean supRetVal = super.onCreateOptionsMenu(menu);
- menu.add(0, 0, getString(R.string.map_menu_zoom_in));
- menu.add(0, 1, getString(R.string.map_menu_zoom_out));
- menu.add(0, 2, getString(R.string.map_menu_toggle_street_satellite));
- menu.add(0, 3, getString(R.string.map_menu_back_to_list));
- return supRetVal;
- }
- @Override
- public boolean onOptionsItemSelected(Menu.Item item){
- switch (item.getId()) {
- case 0:
- // Zoom not closer than possible
- this.myMapController.zoomTo(Math.min(21, this.myMapView.getZoomLevel() + 1));
- return true;
- case 1:
- // Zoom not farer than possible
- this.myMapController.zoomTo(Math.max(1, this.myMapView.getZoomLevel() - 1));
- return true;
- case 2:
- // Switch to satellite view
- myMapView.toggleSatellite();
- return true;
- case 3:
- this.finish();
- return true;
- }
- return false;
- }
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_I) {
- // Zoom not closer than possible
- this.myMapController.zoomTo(Math.min(21, this.myMapView.getZoomLevel() + 1));
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_O) {
- // Zoom not farer than possible
- this.myMapController.zoomTo(Math.max(1, this.myMapView.getZoomLevel() - 1));
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_T) {
- // Switch to satellite view
- myMapView.toggleSatellite();
- return true;
- }
- return false;
- }
Parsed in 0.043 seconds, using GeSHi 1.0.8.4
Regards,
plusminus







