package com.cloudrail.poifinder; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.location.Location; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.app.Fragment; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; import com.cloudrail.si.interfaces.PointsOfInterest; import com.cloudrail.si.services.Foursquare; import com.cloudrail.si.services.GooglePlaces; import com.cloudrail.si.services.Yelp; import com.cloudrail.si.types.POI; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; import java.util.ArrayList; import java.util.List; /** * A simple {@link Fragment} subclass. * Use the {@link POIResult#newInstance} factory method to * create an instance of this fragment. */ public class POIResult extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static final String ARG_CATEGORY = "category"; private String mCategory; private PointsOfInterest poi; private GoogleApiClient mGoogleApiClient; private Context context; private ListView listView; public POIResult() { // Required empty public constructor } @Override public void onStart() { mGoogleApiClient.connect(); super.onStart(); } @Override public void onStop() { mGoogleApiClient.disconnect(); super.onStop(); } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param category The category of POIs to search for. * @return A new instance of fragment POIResult. */ public static POIResult newInstance(String category) { POIResult fragment = new POIResult(); Bundle args = new Bundle(); args.putString(ARG_CATEGORY, category); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mCategory = getArguments().getString(ARG_CATEGORY); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_poiresult, container, false); listView = (ListView) v.findViewById(R.id.poiList); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { POIAdapter poiAdapter = (POIAdapter) listView.getAdapter(); Pair<POI, Long> item = poiAdapter.getItem(position); com.cloudrail.si.types.Location location = item.first.getLocation(); Uri gmmIntentUri = Uri.parse("geo:0,0?q=" + location.getLatitude() + "," + location.getLongitude() + "(" + Uri.encode(item.first.getName()) + ")"); Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); mapIntent.setPackage("com.google.android.apps.maps"); startActivity(mapIntent); } }); return v; } @Override public void onAttach(Context context) { super.onAttach(context); initServices(context); // Create an instance of GoogleAPIClient. if (mGoogleApiClient == null) { mGoogleApiClient = new GoogleApiClient.Builder(context) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } this.context = context; } @Override public void onAttach(Activity activity) { super.onAttach(activity); initServices(activity); // Create an instance of GoogleAPIClient. if (mGoogleApiClient == null) { mGoogleApiClient = new GoogleApiClient.Builder(activity) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } context = activity; } @Override public void onConnected(@Nullable Bundle bundle) { try { final Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); new GetPOIsTask().execute(location); } catch (SecurityException se) { throw new RuntimeException("Missing permission to access location data."); } } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } private void initServices(Context context) { poi = new GooglePlaces(context, "AIzaSyBO1nbR0ZaDct5po9vwXapteN7gsQkCEGQ"); // poi = new Yelp(context, "iz0cItpo8zES7apeuK_aBQ", "ZGSKN2XmEV8j0melw_PvZX3pZPo", // "zP9c2NmgfYAIclIj6_6J74KJJklRda08", "GQTmYLfx441vsYQphKUb5ctVEc4"); // poi = new Foursquare(context, "CHP45LRN1001UWCO2TLU0USWMBXY2OFMAJSPRP5AJ0IBKNSC", // "5VCXTROQNDHUP1TVUYIWNQZOINMMQDVBN2X5GPH5OSDXZSL4"); } private static long distFrom(double lat1, double lng1, double lat2, double lng2) { double earthRadius = 6371.0; double dLat = Math.toRadians(lat2 - lat1); double dLng = Math.toRadians(lng2 - lng1); double sindLat = Math.sin(dLat / 2); double sindLng = Math.sin(dLng / 2); double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2) * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); double dist = earthRadius * c; return Math.round(dist * 1000); } private class GetPOIsTask extends AsyncTask<Location, Void, List<Pair<POI, Long>>> { @Override protected List<Pair<POI, Long>> doInBackground(Location... params) { double lat = params[0].getLatitude(); double lng = params[0].getLongitude(); List<String> categories = new ArrayList<>(); categories.add(mCategory); List<POI> list = poi.getNearbyPOIs(lat, lng, 5000L, null, categories); List<Pair<POI, Long>> res = new ArrayList<>(); for (POI poi : list) { com.cloudrail.si.types.Location location = poi.getLocation(); Pair<POI, Long> elem = new Pair<>(poi, distFrom(lat, lng, location.getLatitude(), location.getLongitude())); res.add(elem); } return res; } @Override protected void onPostExecute(List<Pair<POI, Long>> pois) { POIAdapter poiAdapter = new POIAdapter(context, R.layout.list_poi, pois); listView.setAdapter(poiAdapter); } } }