diff --git a/app/build.gradle b/app/build.gradle
index 1913b202..4a0fc28f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -26,5 +26,7 @@ dependencies {
})
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:recyclerview-v7:25.0.1'
+ compile 'com.google.android.gms:play-services-places:9.8.0'
+ compile 'com.google.android.gms:play-services-location:9.8.0'
testCompile 'junit:junit:4.12'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 89b2b127..44d2738d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,6 +8,11 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+
+
+
@@ -22,4 +27,6 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/android/shushme/MainActivity.java b/app/src/main/java/com/example/android/shushme/MainActivity.java
index 102a5ab8..0361f01e 100644
--- a/app/src/main/java/com/example/android/shushme/MainActivity.java
+++ b/app/src/main/java/com/example/android/shushme/MainActivity.java
@@ -16,19 +16,54 @@
* limitations under the License.
*/
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.Toast;
-public class MainActivity extends AppCompatActivity {
+import com.example.android.shushme.provider.PlaceContract;
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
+import com.google.android.gms.common.GooglePlayServicesRepairableException;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
+import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
+import com.google.android.gms.common.api.PendingResult;
+import com.google.android.gms.common.api.ResultCallback;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.location.places.Place;
+import com.google.android.gms.location.places.PlaceBuffer;
+import com.google.android.gms.location.places.Places;
+import com.google.android.gms.location.places.ui.PlacePicker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends AppCompatActivity implements
+ ConnectionCallbacks,
+ OnConnectionFailedListener {
// Constants
public static final String TAG = MainActivity.class.getSimpleName();
+ private static final int PERMISSIONS_REQUEST_FINE_LOCATION = 111;
+ private static final int PLACE_PICKER_REQUEST = 1;
// Member variables
private PlaceListAdapter mAdapter;
private RecyclerView mRecyclerView;
+ private GoogleApiClient mClient;
/**
* Called when the activity is starting
@@ -43,9 +78,154 @@ protected void onCreate(Bundle savedInstanceState) {
// Set up the recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.places_list_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- mAdapter = new PlaceListAdapter(this);
+ mAdapter = new PlaceListAdapter(this, null);
mRecyclerView.setAdapter(mAdapter);
+
+ // Build up the LocationServices API client
+ // Uses the addApi method to request the LocationServices API
+ // Also uses enableAutoManage to automatically when to connect/suspend the client
+ mClient = new GoogleApiClient.Builder(this)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .addApi(LocationServices.API)
+ .addApi(Places.GEO_DATA_API)
+ .enableAutoManage(this, this)
+ .build();
+
+ }
+
+ /***
+ * Called when the Google API Client is successfully connected
+ *
+ * @param connectionHint Bundle of data provided to clients by Google Play services
+ */
+ @Override
+ public void onConnected(@Nullable Bundle connectionHint) {
+ refreshPlacesData();
+ Log.i(TAG, "API Client Connection Successful!");
+ }
+
+ /***
+ * Called when the Google API Client is suspended
+ *
+ * @param cause cause The reason for the disconnection. Defined by constants CAUSE_*.
+ */
+ @Override
+ public void onConnectionSuspended(int cause) {
+ Log.i(TAG, "API Client Connection Suspended!");
+ }
+
+ /***
+ * Called when the Google API Client failed to connect to Google Play Services
+ *
+ * @param result A ConnectionResult that can be used for resolving the error
+ */
+ @Override
+ public void onConnectionFailed(@NonNull ConnectionResult result) {
+ Log.e(TAG, "API Client Connection Failed!");
+ }
+
+ public void refreshPlacesData() {
+ Uri uri = PlaceContract.PlaceEntry.CONTENT_URI;
+ Cursor data = getContentResolver().query(
+ uri,
+ null,
+ null,
+ null,
+ null);
+
+ if (data == null || data.getCount() == 0) return;
+ List guids = new ArrayList();
+ while (data.moveToNext()) {
+ guids.add(data.getString(data.getColumnIndex(PlaceContract.PlaceEntry.COLUMN_PLACE_ID)));
+ }
+ PendingResult placeResult = Places.GeoDataApi.getPlaceById(mClient,
+ guids.toArray(new String[guids.size()]));
+ placeResult.setResultCallback(new ResultCallback() {
+ @Override
+ public void onResult(@NonNull PlaceBuffer places) {
+ mAdapter.swapPlaces(places);
+
+ }
+ });
+ }
+
+ /***
+ * Button Click event handler to handle clicking the "Add new location" Button
+ *
+ * @param view
+ */
+ public void onAddPlaceButtonClicked(View view) {
+ if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ Toast.makeText(this, getString(R.string.need_location_permission_message), Toast.LENGTH_LONG).show();
+ return;
+ }
+ try {
+ // Start a new Activity for the Place Picker API, this will trigger {@code #onActivityResult}
+ // when a place is selected or with the user cancels.
+ PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
+ Intent i = builder.build(this);
+ startActivityForResult(i, PLACE_PICKER_REQUEST);
+ } catch (GooglePlayServicesRepairableException e) {
+ Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
+ } catch (GooglePlayServicesNotAvailableException e) {
+ Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
+ } catch (Exception e) {
+ Log.e(TAG, String.format("PlacePicker Exception: %s", e.getMessage()));
+ }
+ }
+
+
+ /***
+ * Called when the Place Picker Activity returns back with a selected place (or after canceling)
+ *
+ * @param requestCode The request code passed when calling startActivityForResult
+ * @param resultCode The result code specified by the second activity
+ * @param data The Intent that carries the result data.
+ */
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == PLACE_PICKER_REQUEST && resultCode == RESULT_OK) {
+ Place place = PlacePicker.getPlace(this, data);
+ if (place == null) {
+ Log.i(TAG, "No place selected");
+ return;
+ }
+
+ // Extract the place information from the API
+ String placeName = place.getName().toString();
+ String placeAddress = place.getAddress().toString();
+ String placeID = place.getId();
+
+ // Insert a new place into DB
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(PlaceContract.PlaceEntry.COLUMN_PLACE_ID, placeID);
+ getContentResolver().insert(PlaceContract.PlaceEntry.CONTENT_URI, contentValues);
+
+ // Get live data information
+ refreshPlacesData();
+ }
}
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // Initialize location permissions checkbox
+ CheckBox locationPermissions = (CheckBox) findViewById(R.id.location_permission_checkbox);
+ if (ActivityCompat.checkSelfPermission(MainActivity.this,
+ android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ locationPermissions.setChecked(false);
+ } else {
+ locationPermissions.setChecked(true);
+ locationPermissions.setEnabled(false);
+ }
+ }
+
+ public void onLocationPermissionClicked(View view) {
+ ActivityCompat.requestPermissions(MainActivity.this,
+ new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
+ PERMISSIONS_REQUEST_FINE_LOCATION);
+ }
}
diff --git a/app/src/main/java/com/example/android/shushme/PlaceListAdapter.java b/app/src/main/java/com/example/android/shushme/PlaceListAdapter.java
index 793ac1d5..c48916ac 100644
--- a/app/src/main/java/com/example/android/shushme/PlaceListAdapter.java
+++ b/app/src/main/java/com/example/android/shushme/PlaceListAdapter.java
@@ -23,17 +23,21 @@
import android.view.ViewGroup;
import android.widget.TextView;
+import com.google.android.gms.location.places.PlaceBuffer;
+
public class PlaceListAdapter extends RecyclerView.Adapter {
private Context mContext;
+ private PlaceBuffer mPlaces;
/**
* Constructor using the context and the db cursor
*
* @param context the calling context/activity
*/
- public PlaceListAdapter(Context context) {
+ public PlaceListAdapter(Context context, PlaceBuffer places) {
this.mContext = context;
+ this.mPlaces = places;
}
/**
@@ -59,9 +63,19 @@ public PlaceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
*/
@Override
public void onBindViewHolder(PlaceViewHolder holder, int position) {
-
+ String placeName = mPlaces.get(position).getName().toString();
+ String placeAddress = mPlaces.get(position).getAddress().toString();
+ holder.nameTextView.setText(placeName);
+ holder.addressTextView.setText(placeAddress);
}
+ public void swapPlaces(PlaceBuffer newPlaces){
+ mPlaces = newPlaces;
+ if (mPlaces != null) {
+ // Force the RecyclerView to refresh
+ this.notifyDataSetChanged();
+ }
+ }
/**
* Returns the number of items in the cursor
@@ -70,7 +84,8 @@ public void onBindViewHolder(PlaceViewHolder holder, int position) {
*/
@Override
public int getItemCount() {
- return 0;
+ if(mPlaces==null) return 0;
+ return mPlaces.getCount();
}
/**
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 3d6e2bf4..3471ef2d 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -59,12 +59,49 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -90,4 +127,28 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d87fb1a1..21b72366 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,7 +2,11 @@
ShushMe
Add new location
Locations
+ You need to enable location permissions first
+ Location Permissions Granted
EnabledSetting
Settings
+ Location Permissions
Enable Geofences
+ http://www.google.com/policies/privacy