Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
7 changes: 7 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="insert-your-api-key-here" />

<activity android:name="com.example.android.shushme.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand All @@ -22,4 +27,6 @@

</application>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
184 changes: 182 additions & 2 deletions app/src/main/java/com/example/android/shushme/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<String> guids = new ArrayList<String>();
while (data.moveToNext()) {
guids.add(data.getString(data.getColumnIndex(PlaceContract.PlaceEntry.COLUMN_PLACE_ID)));
}
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mClient,
guids.toArray(new String[guids.size()]));
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
@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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<PlaceListAdapter.PlaceViewHolder> {

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;
}

/**
Expand All @@ -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
Expand All @@ -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();
}

/**
Expand Down
61 changes: 61 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,49 @@
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:paddingRight="8dp"
android:paddingTop="4dp"
android:src="@drawable/ic_my_location_primary_24dp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/location_permissions"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/black" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<CheckBox
android:id="@+id/location_permission_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="8dp"
android:onClick="onLocationPermissionClicked" />

</RelativeLayout>
</LinearLayout>


<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:background="@color/colorPrimary"
android:onClick="onAddPlaceButtonClicked"
android:text="@string/add_new_location"
android:textAppearance="@style/TextAppearance.AppCompat.Button"
android:textColor="@android:color/white" />
Expand All @@ -90,4 +127,28 @@

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="vertical">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="4dp"
android:src="@drawable/powered_by_google_light" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:paddingBottom="4dp"
android:text="@string/privacy"
android:textAlignment="center" />
</LinearLayout>


</RelativeLayout>
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
<string name="app_name">ShushMe</string>
<string name="add_new_location">Add new location</string>
<string name="location_list">Locations</string>
<string name="need_location_permission_message">You need to enable location permissions first</string>
<string name="location_permissions_granted_message">Location Permissions Granted</string>
<string name="setting_enabled" translatable="false">EnabledSetting</string>
<string name="settings_label">Settings</string>
<string name="location_permissions">Location Permissions</string>
<string name="enable_geofences">Enable Geofences</string>
<string name="privacy">http://www.google.com/policies/privacy</string>
</resources>