Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Commit

Permalink
Merge pull request #73 from flibbertigibbet/feature/kak/add-geofencin…
Browse files Browse the repository at this point in the history
…g#44

Feature/kak/add geofencing#44
  • Loading branch information
flibbertigibbet authored Jun 6, 2018
2 parents 7556be8 + ca4a9ba commit c4b3081
Show file tree
Hide file tree
Showing 29 changed files with 1,143 additions and 38 deletions.
28 changes: 4 additions & 24 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ dependencies {
def playServicesVersion = '15.0.1'
implementation "com.google.android.gms:play-services-location:$playServicesVersion"
implementation "com.google.android.gms:play-services-maps:$playServicesVersion"
// Android WorkManager
implementation "android.arch.work:work-runtime:1.0.0-alpha02"
// Carousel
implementation 'com.github.flibbertigibbet:carouselview:1.0.5'
// Badges
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Listen for reboot to set up geofences again -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
android:name=".GoPhillyGoApp"
android:allowBackup="true"
Expand Down Expand Up @@ -93,6 +96,23 @@
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />

<!-- Set up geofences again after reboot or location provider changes -->
<receiver android:name=".tasks.AddGeofencesBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!-- FIXME: implicit system broadcast intent cannot start background thread
<action android:name="android.location.PROVIDERS_CHANGED" /> -->
</intent-filter>
</receiver>

<!-- Listen to geofence transitions. -->
<receiver android:name=".tasks.GeofenceTransitionBroadcastReceiver"
android:exported="false" android:enabled="true">
<intent-filter>
<action android:name="com.gophillygo.app.tasks.ACTION_GEOFENCE_TRANSITION" />
</intent-filter>
</receiver>
</application>

</manifest>
14 changes: 13 additions & 1 deletion app/src/main/java/com/gophillygo/app/GoPhillyGoApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,36 @@

import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.util.Log;

import com.gophillygo.app.di.AppInjector;

import javax.inject.Inject;

import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasActivityInjector;
import dagger.android.HasBroadcastReceiverInjector;

/**
* Based on:
* https://github.com/googlesamples/android-architecture-components/blob/178fe541643adb122d2a8925cf61a21950a4611c/GithubBrowserSample/app/src/main/java/com/android/example/github/GithubApp.java
*/


public class GoPhillyGoApp extends Application implements HasActivityInjector {
public class GoPhillyGoApp extends Application implements HasActivityInjector, HasBroadcastReceiverInjector {

private static final String LOG_LABEL = "GPGApp";

@SuppressWarnings("WeakerAccess")
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

@SuppressWarnings("WeakerAccess")
@Inject
DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;

@Override
public void onCreate() {
super.onCreate();
Expand All @@ -38,4 +45,9 @@ public void onCreate() {
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}

@Override
public AndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.gophillygo.app.activities;

import android.arch.persistence.room.util.StringUtil;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
Expand All @@ -19,19 +18,41 @@
import com.gophillygo.app.data.models.AttractionInfo;
import com.gophillygo.app.data.models.DestinationInfo;
import com.gophillygo.app.data.models.DestinationLocation;
import com.gophillygo.app.data.models.EventInfo;
import com.gophillygo.app.tasks.AddGeofencesBroadcastReceiver;
import com.gophillygo.app.tasks.RemoveGeofenceWorker;
import com.synnapps.carouselview.CarouselView;

abstract class AttractionDetailActivity extends AppCompatActivity {
protected static final int COLLAPSED_LINE_COUNT = 4;
protected static final int EXPANDED_MAX_LINES = 50;
private static final String LOG_LABEL = "AttractionDetail";
protected DestinationInfo destinationInfo;

protected DestinationInfo destinationInfo;
protected View.OnClickListener toggleClickListener;

protected abstract Class getMapActivity();
protected abstract int getAttractionId();

protected void addOrRemoveGeofence(AttractionInfo info, Boolean haveExistingGeofence, Boolean settingGeofence) {
if (settingGeofence) {
if (haveExistingGeofence) {
Log.d(LOG_LABEL, "No change to geofence");
return;
}
// add geofence
Log.d(LOG_LABEL, "Add attraction geofence");
if (info instanceof EventInfo) {
AddGeofencesBroadcastReceiver.addOneGeofence((EventInfo)info);
} else if (info instanceof DestinationInfo) {
AddGeofencesBroadcastReceiver.addOneGeofence(((DestinationInfo) info).getDestination());
}
} else if (haveExistingGeofence) {
Log.e(LOG_LABEL, "Removing attraction geofence");
RemoveGeofenceWorker.removeOneGeofence(info);
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -74,7 +95,6 @@ public void goToMap(View view) {
public void goToDirections(View view) {
// pass parameters destination and destinationText to https://gophillygo.org/
Uri directionsUri = new Uri.Builder().scheme("https").authority("gophillygo.org")
// TODO: #9 send current user location as origin
.appendQueryParameter("origin", "")
.appendQueryParameter("originText", "")
.appendQueryParameter("destination", destinationInfo.getDestination().getLocation().toString())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gophillygo.app.activities;

import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
Expand All @@ -10,11 +11,16 @@
import android.util.Log;

import com.gophillygo.app.data.DestinationViewModel;
import com.gophillygo.app.data.models.AttractionInfo;
import com.gophillygo.app.data.models.Destination;
import com.gophillygo.app.data.models.DestinationInfo;
import com.gophillygo.app.data.models.DestinationLocation;
import com.gophillygo.app.data.models.EventInfo;
import com.gophillygo.app.data.networkresource.Status;
import com.gophillygo.app.di.GpgViewModelFactory;
import com.gophillygo.app.tasks.AddGeofenceWorker;
import com.gophillygo.app.tasks.AddGeofencesBroadcastReceiver;
import com.gophillygo.app.tasks.RemoveGeofenceWorker;
import com.gophillygo.app.utils.GpgLocationUtils;
import com.gophillygo.app.utils.UserUuidUtils;

Expand Down Expand Up @@ -57,6 +63,26 @@ public abstract class BaseAttractionActivity extends AppCompatActivity
@SuppressWarnings("WeakerAccess")
DestinationViewModel viewModel;

protected void addOrRemoveGeofence(AttractionInfo info, Boolean haveExistingGeofence, Boolean settingGeofence) {
if (settingGeofence) {
if (haveExistingGeofence) {
Log.d(LOG_LABEL, "No change to geofence");
return;
}
// add geofence
Log.d(LOG_LABEL, "Add attraction geofence");
if (info instanceof EventInfo) {
AddGeofencesBroadcastReceiver.addOneGeofence((EventInfo)info);
} else if (info instanceof DestinationInfo) {
AddGeofencesBroadcastReceiver.addOneGeofence(((DestinationInfo) info).getDestination());
}

} else if (haveExistingGeofence) {
Log.e(LOG_LABEL, "Removing attraction geofence");
RemoveGeofenceWorker.removeOneGeofence(info);
}
}


private void setDefaultLocation() {
Log.w(LOG_LABEL, "Using City Hall as default location");
Expand Down Expand Up @@ -215,12 +241,25 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
if (requestCode == GpgLocationUtils.PERMISSION_REQUEST_ID) {
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(LOG_LABEL, "Re-requesting location after getting permissions");
Log.d(LOG_LABEL, "Re-requesting location after getting fine location permissions");
fetchLastLocationOrUseDefault();
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
GpgLocationUtils.displayPermissionRequestRationale(getApplicationContext());
}
}
} else if (requestCode == GpgLocationUtils.LOCATION_SETTINGS_REQUEST_ID) {
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(LOG_LABEL, "Re-requesting location after getting location network permissions");
fetchLastLocationOrUseDefault();
Log.d(LOG_LABEL, "Attempting to register geofences from database again");
Intent intent = new Intent(getApplicationContext(), AddGeofencesBroadcastReceiver.class);
intent.setAction(AddGeofenceWorker.ACTION_GEOFENCE_TRANSITION);
sendBroadcast(intent);
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
Log.w(LOG_LABEL, "Location network permissions not updated; geofencing may not work");
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
import com.gophillygo.app.R;
import com.gophillygo.app.data.DestinationViewModel;
import com.gophillygo.app.data.EventViewModel;
import com.gophillygo.app.data.models.AttractionFlag;
import com.gophillygo.app.data.models.DestinationInfo;
import com.gophillygo.app.data.models.Event;
import com.gophillygo.app.data.models.EventInfo;
import com.gophillygo.app.databinding.ActivityEventDetailBinding;
import com.gophillygo.app.di.GpgViewModelFactory;
import com.gophillygo.app.tasks.AddGeofencesBroadcastReceiver;
import com.gophillygo.app.tasks.RemoveGeofenceWorker;
import com.gophillygo.app.utils.FlagMenuUtils;
import com.gophillygo.app.utils.UserUuidUtils;
import com.synnapps.carouselview.CarouselView;
Expand Down Expand Up @@ -92,7 +95,7 @@ protected void onCreate(Bundle savedInstanceState) {
viewModel = ViewModelProviders.of(this, viewModelFactory).get(EventViewModel.class);
destinationViewModel = ViewModelProviders.of(this, viewModelFactory).get(DestinationViewModel.class);
viewModel.getEvent(eventId).observe(this, eventInfo -> {
// TODO: handle if event not found (go to list of events?)
// TODO: #61 handle if event not found (go to list of events?)
if (eventInfo == null || eventInfo.getEvent() == null) {
Log.e(LOG_LABEL, "No matching event found for ID " + eventId);
return;
Expand Down Expand Up @@ -185,9 +188,13 @@ private void displayEvent() {
Log.d(LOG_LABEL, "Clicked flags button");
PopupMenu menu = FlagMenuUtils.getFlagPopupMenu(this, flagOptionsCard, eventInfo.getFlag());
menu.setOnMenuItemClickListener(item -> {
Boolean haveExistingGeofence = eventInfo.getFlag().getOption()
.api_name.equals(AttractionFlag.Option.WantToGo.api_name);

eventInfo.updateAttractionFlag(item.getItemId());
viewModel.updateAttractionFlag(eventInfo.getFlag(), userUuid, getString(R.string.user_flag_post_api_key));

Boolean settingGeofence = destinationInfo.getFlag().getOption().api_name.equals(AttractionFlag.Option.WantToGo.api_name);
addOrRemoveGeofence(destinationInfo, haveExistingGeofence, settingGeofence);
return true;
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
import com.gophillygo.app.R;
import com.gophillygo.app.adapters.EventsListAdapter;
import com.gophillygo.app.data.EventViewModel;
import com.gophillygo.app.data.models.AttractionFlag;
import com.gophillygo.app.data.models.AttractionInfo;
import com.gophillygo.app.data.models.EventInfo;
import com.gophillygo.app.data.networkresource.Resource;
import com.gophillygo.app.data.networkresource.Status;
import com.gophillygo.app.databinding.ActivityEventsListBinding;
import com.gophillygo.app.databinding.FilterButtonBarBinding;
import com.gophillygo.app.di.GpgViewModelFactory;
import com.gophillygo.app.tasks.AddGeofencesBroadcastReceiver;
import com.gophillygo.app.tasks.RemoveGeofenceWorker;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -65,9 +68,22 @@ public void clickedAttraction(int position) {
}

public boolean clickedFlagOption(MenuItem item, AttractionInfo eventInfo, Integer position) {
Boolean haveExistingGeofence = eventInfo.getFlag()
.getOption().api_name.equals(AttractionFlag.Option.WantToGo.api_name);

eventInfo.updateAttractionFlag(item.getItemId());
viewModel.updateAttractionFlag(eventInfo.getFlag(), userUuid, getString(R.string.user_flag_post_api_key));
adapter.notifyItemChanged(position);

// do not attempt to add a geofence for an event with no location
if (((EventInfo)eventInfo).hasDestinationName()) {
Boolean settingGeofence = eventInfo.getFlag().getOption().api_name.equals(AttractionFlag.Option.WantToGo.api_name);
addOrRemoveGeofence(eventInfo, haveExistingGeofence, settingGeofence);
} else {
// TODO: notify user?
Log.w(LOG_LABEL, "Cannot add geofence for an event without an associated destination");
}

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
import com.gophillygo.app.CarouselViewListener;
import com.gophillygo.app.R;
import com.gophillygo.app.adapters.PlaceCategoryGridAdapter;
import com.gophillygo.app.data.models.AttractionFlag;
import com.gophillygo.app.data.models.Destination;
import com.synnapps.carouselview.CarouselView;

import java.util.List;


public class HomeActivity extends BaseAttractionActivity {

Expand Down Expand Up @@ -45,6 +48,7 @@ protected void onCreate(Bundle savedInstanceState) {

// initialize carousel if destinations already loaded
locationOrDestinationsChanged();

}

@Override
Expand Down
Loading

0 comments on commit c4b3081

Please sign in to comment.