Java tutorial
package com.tingbacke.wearmaps; /** * Johan Tingbacke, 2015-04-19 * From tutorial: http://blog.teamtreehouse.com/beginners-guide-location-android * <p/> * To add custom notifications: http://possiblemobile.com/2014/07/create-custom-ongoing-notification-android-wear/ */ import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.content.IntentSender; import android.graphics.BitmapFactory; import android.graphics.Color; import android.location.Address; import android.location.Criteria; import android.location.Geocoder; import android.location.Location; import android.location.LocationManager; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NotificationCompat; import android.text.Html; import android.util.Log; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.PolylineOptions; import com.google.android.gms.wearable.Wearable; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; public class MobileActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private GoogleMap mMap; // Might be null if Google Play services APK is not available. private GoogleApiClient mGoogleApiClient; public static final String TAG = MobileActivity.class.getSimpleName(); private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; private LocationRequest mLocationRequest; public NotificationManager notificationManager; private Marker[] placeMarkers; private final int MAX_PLACES = 20; private MarkerOptions[] places; ArrayList<LatLng> markerPoints; // Variable used for calculating current distance to destination public float currDistance; // Hardcoded LatLng location for a destination. Ribersborgs Kallbadhus. public double destLat = 55.6048; public double destLong = 12.9658; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mobile); setUpMapIfNeeded(); UiSettings mapSettings; mapSettings = mMap.getUiSettings(); mapSettings.setZoomControlsEnabled(true); mapSettings.setCompassEnabled(true); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(Wearable.API).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); // Create the LocationRequest object mLocationRequest = LocationRequest.create().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(5000) // 5 seconds, in milliseconds .setFastestInterval(1000); // 1 second, in milliseconds // Initializing markerPoints = new ArrayList<LatLng>(); } @Override protected void onDestroy() { super.onDestroy(); mGoogleApiClient.disconnect(); } @Override protected void onStart() { super.onStart(); mGoogleApiClient.connect(); } @Override protected void onStop() { super.onStop(); mGoogleApiClient.disconnect(); } @Override protected void onResume() { super.onResume(); setUpMapIfNeeded(); mGoogleApiClient.connect(); } @Override protected void onPause() { super.onPause(); setUpMapIfNeeded(); mGoogleApiClient.isConnected(); } /** * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly * installed) and the map has not already been instantiated.. This will ensure that we only ever * call {@link #setUpMap()} once when {@link #mMap} is not null. * <p/> * If it isn't installed {@link SupportMapFragment} (and * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to * install/update the Google Play services APK on their device. * <p/> * A user can return to this FragmentActivity after following the prompt and correctly * installing/updating/enabling the Google Play services. Since the FragmentActivity may not * have been completely destroyed during this process (it is likely that it would only be * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this * method in {@link #onResume()} to guarantee that it will be called. */ private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); placeMarkers = new Marker[MAX_PLACES]; // Setting onclick event listener for the map mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { @Override public void onMapLongClick(LatLng point) { // Already two locations if (markerPoints.size() > 1) { markerPoints.clear(); mMap.clear(); } // Adding new item to the ArrayList markerPoints.add(point); // Creating MarkerOptions MarkerOptions options = new MarkerOptions(); // Setting the position of the marker options.position(point); //For the start/end location, marker colors are blue/green if (markerPoints.size() == 1) { options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); } else if (markerPoints.size() == 2) { options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)); } // Add new marker to the Google Map Android API V2 mMap.addMarker(options); // Checks, whether start and end locations are captured if (markerPoints.size() >= 2) { LatLng origin = markerPoints.get(0); LatLng dest = markerPoints.get(1); // Getting URL to the Google Directions API String url = getDirectionsUrl(origin, dest); GetPlaces downloadTask = new GetPlaces(); // Start downloading json data from Google Directions API downloadTask.execute(url); } } }); } } } /** * This is where we can add markers or lines, add listeners or move the camera. In this case, we * just add a marker near Africa. * <p/> * This should only be called once and when we are sure that {@link #mMap} is not null. */ private void setUpMap() { mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); mMap.setMyLocationEnabled(true); /** * https://geolocation.ws/map/55.588227,13.002735/13/en?types=&limit=300&licenses= * Dammfrivgen 61 = 55.587116, 12.979788 */ /* mMap.addMarker(new MarkerOptions().position(new LatLng(55.61015, 12.9786)).title("Cykelpump Kockums Torg")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5877, 12.9887)).title("Cykelpump Malm gamla stadion")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6093, 12.9967)).title("Cykelpump, Anna Linds plats")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6025, 12.9679)).title("Cykelpump, Ribersborgsstigen")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6131, 12.9767)).title("Turning Torso")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6140, 12.9839)).title("Stapelbddsparken, skatepark")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6125, 12.9914)).title("Media Evolution City")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6144, 12.9895)).title("Doc Piazza Trattoria")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6156, 12.9857)).title("Kranen K3, Malm Hgskola")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6150, 12.9858)).title("Ubtshallen")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6108, 12.9949)).title("Orkanen, Malm Hgskola")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5850, 12.9873)).title("Swedbank Stadion")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5922, 12.9975)).title("Pildammsparken Entr")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5901, 12.9887)).title("Pildammsparken Tallriken")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5890, 12.9825)).title("Jet bensinmack, Lorensborg")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6048, 12.9658)).title("Ribersborgs Kallbadhus")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6041, 12.9735)).title("Toalett, Ribersborgsstigen")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6086, 12.9774)).title("Kockum fritid")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6138, 12.9812)).title("Varvsparken")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6137, 12.9725)).title("Daniabadet, Vstra Hamnen")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.6171, 12.9744)).title("Scaniabadet, Vstra Hamnen")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5967, 13.0053)).title("MALM")); mMap.addMarker(new MarkerOptions().position(new LatLng(55.5986, 12.9836)).title("Kronprinsen")); //mMap.addMarker(new MarkerOptions().position(new LatLng()).title("")); */ // Get LocationManager object from System Service LOCATION_SERVICE LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); // Create a criteria object to retrieve provider Criteria criteria = new Criteria(); // Get the name of the best provider String provider = locationManager.getBestProvider(criteria, true); // Get Current Location Location myLocation = locationManager.getLastKnownLocation(provider); // Get latitude of the current location double latitude = myLocation.getLatitude(); // Get longitude of the current location double longitude = myLocation.getLongitude(); // Create a LatLng object for the current location LatLng latLng = new LatLng(latitude, longitude); // Show the current location in Google Map mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng).zoom(18).bearing(0).tilt(25) .build(); mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); LatLng myCoordinates = new LatLng(latitude, longitude); CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(myCoordinates, 18); mMap.animateCamera(yourLocation); } /** * Updates my location to currentLocation, moves the camera. * * @param location */ private void handleNewLocation(Location location) { Log.d(TAG, location.toString()); double latitude = location.getLatitude(); double longitude = location.getLongitude(); LatLng latLng = new LatLng(latitude, longitude); mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng).zoom(18).bearing(0).tilt(25) .build(); mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); TextView myLatitude = (TextView) findViewById(R.id.textView); TextView myLongitude = (TextView) findViewById(R.id.textView2); TextView myAddress = (TextView) findViewById(R.id.textView3); ImageView myImage = (ImageView) findViewById(R.id.imageView); myLatitude.setText("Latitude: " + String.valueOf(latitude)); myLongitude.setText("Longitude: " + String.valueOf(longitude)); // Instantiating currDistance to get distance to destination from my location currDistance = getDistance(latitude, longitude, destLat, destLong); Geocoder geocoder = new Geocoder(this, Locale.ENGLISH); try { List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1); if (addresses != null) { Address returnedAddress = addresses.get(0); StringBuilder strReturnedAddress = new StringBuilder(""); for (int i = 0; i < returnedAddress.getMaxAddressLineIndex(); i++) { strReturnedAddress.append(returnedAddress.getAddressLine(i)).append("\n"); } // Hardcoded string which searches through strReturnedAddress for specifics // if statements decide which information will be displayed String fake = strReturnedAddress.toString(); if (fake.contains("stra Varvsgatan")) { myAddress.setText("K3, Malm Hgskola" + "\n" + "Cykelparkering: 50m" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.kranen); } else if (fake.contains("Lilla Varvsgatan")) { myAddress.setText("Turning Torso" + "\n" + "Caf: 90m " + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.turning); } else if (fake.contains("Vstra Varvsgatan")) { myAddress.setText("Kockum Fritid" + "\n" + "Bankomat: 47m" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.kockum); } else if (fake.contains("Stapelbddsgatan")) { myAddress.setText("Stapelbddsparken" + "\n" + "Toalett: 63m" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.stapel); } else if (fake.contains("Stora Varvsgatan")) { myAddress.setText("Media Evolution City" + "\n" + "Busshllplats: 94m" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.media); } else if (fake.contains("Masttorget")) { myAddress.setText("Ica Maxi" + "\n" + "Systembolaget: 87m" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.ica); } else if (fake.contains("Riggaregatan")) { myAddress.setText("Scaniabadet" + "\n" + "\n" + "Dest: " + Math.round(currDistance) + "m away"); myImage.setImageResource(R.mipmap.scaniabadet); } else if (fake.contains("Dammfrivgen")) { //fakear Turning Torso p min adress fr tillfllet myAddress.setText("Turning Torso" + "\n" + "453m away"); myImage.setImageResource(R.mipmap.turning); } //myAddress.setText(strReturnedAddress.toString()+ "Dest: " + Math.round(currDistance) + "m away"); /* // Added this Toast to display address ---> In order to find out where to call notification builder for wearable Toast.makeText(MobileActivity.this, myAddress.getText().toString(), Toast.LENGTH_LONG).show(); */ //Here is where I call the notification builder for the wearable showNotification(1, "basic", getBasicNotification("myStack")); } else { myAddress.setText("No Address returned!"); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); myAddress.setText("Cannot get Address!"); } } /** * Show a notification. * * @param id The notification id * @param tag The notification tag * @param notification The notification */ private void showNotification(int id, String tag, Notification notification) { notificationManager.notify(tag, id, notification); } private Notification getBasicNotification(String stack) { String title = "Vstra Hamnen"; TextView tv = (TextView) findViewById(R.id.textView3); String text = tv.getText().toString(); // Here I determine the vibration pattern for the notification long[] pattern = { 0, 200, 0 }; /* // This seems only to be for adding longer texts to a notification... NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); bigTextStyle.setBigContentTitle(title); */ /* Spannable sb = new SpannableString("Bold this and italic that."); sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); sb.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 14, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); */ NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() .setBackground(BitmapFactory.decodeResource(getResources(), R.mipmap.turn)); NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); inboxStyle.addLine(Html.fromHtml("<b>Turning Torso</b>")); inboxStyle.addLine(Html.fromHtml("<b>453m away</b>")); return new NotificationCompat.Builder(this).setSmallIcon(R.mipmap.icon_mdpi).setContentTitle(title) .setContentText(text) //.setStyle(bigPic) //.setStyle(inboxStyle) .extend(extender) //.setStyle(bigTextStyle) .setVibrate(pattern).setGroup(stack).build(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { if (connectionResult.hasResolution()) { try { // Start an Activity that tries to resolve the error connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } } else { Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode()); } } @Override public void onConnected(Bundle bundle) { Log.i(TAG, "Location services connected."); Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (location == null) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (LocationListener) this); } else { handleNewLocation(location); } } @Override public void onConnectionSuspended(int i) { Log.i(TAG, "Location services suspended. Please reconnect."); } private String getDirectionsUrl(LatLng origin, LatLng dest) { // Origin of route String str_origin = "origin=" + origin.latitude + "," + origin.longitude; // Destination of route String str_dest = "destination=" + dest.latitude + "," + dest.longitude; //Denna tog tid att frst sig p, men nu jvlar! // Change travel mode String tr_mode = "mode=bicycling"; // Sensor enabled String sensor = "sensor=false"; // Building the parameters to the web service String parameters = str_origin + "&" + str_dest + "&" + "&" + tr_mode + "&" + sensor; // Output format String output = "json"; // Building the url to the web service String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters; return url; } /** * A method to download json data from url */ private String downloadUrl(String strUrl) throws IOException { String data = ""; InputStream iStream = null; HttpURLConnection urlConnection = null; try { URL url = new URL(strUrl); // Creating an http connection to communicate with url urlConnection = (HttpURLConnection) url.openConnection(); // Connecting to url urlConnection.connect(); // Reading data from url iStream = urlConnection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); StringBuffer sb = new StringBuffer(); String line = ""; while ((line = br.readLine()) != null) { sb.append(line); } data = sb.toString(); br.close(); } catch (Exception e) { Log.d("Exception while dl url", e.toString()); } finally { iStream.close(); urlConnection.disconnect(); } return data; } // Fetches data from url passed private class GetPlaces extends AsyncTask<String, Void, String> { // Downloading data in non-ui thread @Override protected String doInBackground(String... url) { // Fetch places // For storing data from web service String data = ""; try { // Fetching the data from web service data = downloadUrl(url[0]); } catch (Exception e) { Log.d("Background Task", e.toString()); } return data; } // Executes in UI thread, after the execution of // doInBackground() @Override protected void onPostExecute(String result) { super.onPostExecute(result); ParserTask parserTask = new ParserTask(); // Invokes the thread for parsing the JSON data parserTask.execute(result); } } /** * A class to parse the Google Places in JSON format */ private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> { // Parsing the data in non-ui thread @Override protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) { JSONObject jObject; List<List<HashMap<String, String>>> routes = null; try { jObject = new JSONObject(jsonData[0]); DirectionsJSONParser parser = new DirectionsJSONParser(); // Starts parsing data routes = parser.parse(jObject); } catch (Exception e) { e.printStackTrace(); } return routes; } // Executes in UI thread, after the parsing process @Override protected void onPostExecute(List<List<HashMap<String, String>>> result) { ArrayList<LatLng> points = null; PolylineOptions lineOptions = null; MarkerOptions markerOptions = new MarkerOptions(); // Traversing through all the routes for (int i = 0; i < result.size(); i++) { points = new ArrayList<LatLng>(); lineOptions = new PolylineOptions(); // Fetching i-th route List<HashMap<String, String>> path = result.get(i); // Fetching all the points in i-th route for (int j = 0; j < path.size(); j++) { HashMap<String, String> point = path.get(j); double lat = Double.parseDouble(point.get("lat")); double lng = Double.parseDouble(point.get("lng")); LatLng position = new LatLng(lat, lng); points.add(position); } // Adding all the points in the route to LineOptions lineOptions.addAll(points); lineOptions.width(3); lineOptions.color(Color.RED); } // Drawing polyline in the Google Map for the i-th route mMap.addPolyline(lineOptions); } } // Method for calculating distance between current position and destination public float getDistance(double lat1, double longi, double lat2, double longi2) { float[] dist = new float[1]; try { Location.distanceBetween(lat1, longi, lat2, longi2, dist); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // Making a toast of the returned value, rounding it using Math.round() to get an "int" Toast.makeText(getApplicationContext(), String.valueOf(Math.round(dist[0])) + " meters away", Toast.LENGTH_LONG).show(); return dist[0]; } }