Location picker changes

* Request location permission before opening geofence settings
* Enable maps in generic build (Android 5+)
* Resolve Play Services errors in settings
pull/795/head
Alex Baker 7 years ago
parent 5ea5bb851f
commit e28d93eb56

@ -14,5 +14,9 @@ public class GeofenceApi {
public void cancel(Location geofence) {}
public void cancel(List<Location> geofences) {}
public void registerAll() {}
public void cancel(long taskId) {}
public void register(long taskId) {}
}

@ -25,4 +25,9 @@ public class GoogleMapFragment implements MapFragment {
@Override
public void showMyLocation() {}
@Override
public int getMarkerId() {
return 0;
}
}

@ -16,6 +16,11 @@ public class GooglePlacesSearchProvider implements PlaceSearchProvider {
@Override
public void saveState(Bundle outState) {}
@Override
public int getAttributionRes(boolean dark) {
return 0;
}
@Override
public void search(
String query,

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="support_maps">true</bool>
</resources>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="support_maps">false</bool>
<bool name="support_geofences">false</bool>
</resources>

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="location_enabled">true</bool>
<bool name="support_maps">true</bool>
<bool name="support_geofences">true</bool>
</resources>

@ -99,7 +99,7 @@ public class DefaultsPreferences extends InjectingPreferenceActivity
updateRadius();
requires(syncAdapters.isSyncEnabled(), R.string.p_default_remote_list);
requires(device.supportsLocationServices(), R.string.p_default_location_reminder_key);
requires(device.supportsGeofences(), R.string.p_default_location_reminder_key);
}
private void startCalendarSelectionActivity() {

@ -45,6 +45,14 @@ public class Geofence implements Serializable, Parcelable {
public Geofence() {}
@Ignore
public Geofence(String place, boolean arrival, boolean departure, int radius) {
this.place = place;
this.arrival = arrival;
this.departure = departure;
this.radius = radius;
}
@Ignore
public Geofence(Geofence o) {
id = o.id;

@ -1,7 +1,6 @@
package org.tasks.dialogs;
import static android.app.Activity.RESULT_OK;
import static org.tasks.PermissionUtil.verifyPermissions;
import static org.tasks.dialogs.SeekBarDialog.newSeekBarDialog;
import android.app.Dialog;
@ -18,7 +17,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnCheckedChanged;
import butterknife.OnClick;
import javax.inject.Inject;
import org.tasks.R;
@ -28,12 +26,10 @@ import org.tasks.injection.DialogFragmentComponent;
import org.tasks.injection.ForActivity;
import org.tasks.injection.InjectingDialogFragment;
import org.tasks.locale.Locale;
import org.tasks.preferences.FragmentPermissionRequestor;
import org.tasks.preferences.PermissionChecker;
import org.tasks.preferences.PermissionRequestor;
import org.tasks.ui.Toaster;
public class LocationDialog extends InjectingDialogFragment {
public class GeofenceDialog extends InjectingDialogFragment {
public static final String EXTRA_GEOFENCE = "extra_geofence";
private static final String EXTRA_ORIGINAL = "extra_original";
@ -45,7 +41,6 @@ public class LocationDialog extends InjectingDialogFragment {
@Inject @ForActivity Context context;
@Inject Locale locale;
@Inject PermissionChecker permissionChecker;
@Inject FragmentPermissionRequestor permissionRequestor;
@Inject Toaster toaster;
@BindView(R.id.location_arrival)
@ -57,21 +52,14 @@ public class LocationDialog extends InjectingDialogFragment {
@BindView(R.id.location_radius_value)
TextView radiusValue;
public static LocationDialog newLocationDialog(Location location) {
LocationDialog dialog = new LocationDialog();
public static GeofenceDialog newGeofenceDialog(Location location) {
GeofenceDialog dialog = new GeofenceDialog();
Bundle args = new Bundle();
args.putParcelable(EXTRA_ORIGINAL, location);
dialog.setArguments(args);
return dialog;
}
@OnCheckedChanged({R.id.location_arrival, R.id.location_departure})
void geofenceCheckedChanged(boolean enabled) {
if (enabled) {
permissionRequestor.requestFineLocation();
}
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
@ -130,24 +118,7 @@ public class LocationDialog extends InjectingDialogFragment {
super.onResume();
if (!permissionChecker.canAccessLocation()) {
arrivalView.setChecked(false);
departureView.setChecked(false);
}
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PermissionRequestor.REQUEST_LOCATION) {
if (!verifyPermissions(grantResults)) {
dialogBuilder
.newMessageDialog(R.string.location_permission_required_geofence)
.setTitle(R.string.missing_permissions)
.setPositiveButton(android.R.string.ok, null)
.show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
dismiss();
}
}

@ -17,8 +17,10 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.tasks.BuildConfig;
import org.tasks.R;
import org.tasks.injection.ForActivity;
import org.tasks.preferences.Device;
import org.tasks.preferences.Preferences;
import org.tasks.sync.SyncAdapters;
@ -80,12 +82,18 @@ public class TaskEditControlSetFragmentManager {
private final Context context;
private final List<String> displayOrder;
private final SyncAdapters syncAdapters;
private final Device device;
private int numRows;
@Inject
public TaskEditControlSetFragmentManager(
Context context, Preferences preferences, SyncAdapters syncAdapters) {
@ForActivity Context context,
Preferences preferences,
SyncAdapters syncAdapters,
Device device) {
this.context = context;
this.syncAdapters = syncAdapters;
this.device = device;
displayOrder = BeastModePreferences.constructOrderedControlList(preferences, context);
displayOrder.add(0, context.getString(EditTitleControlSet.TAG));
displayOrder.add(1, context.getString(CommentBarFragment.TAG));
@ -154,7 +162,7 @@ public class TaskEditControlSetFragmentManager {
case ReminderControlSet.TAG:
return new ReminderControlSet();
case LocationControlSet.TAG:
return Device.SupportsLocationServices(context) ? new LocationControlSet() : null;
return device.supportsMaps() ? new LocationControlSet() : null;
case FilesControlSet.TAG:
return new FilesControlSet();
case TimerControlSet.TAG:

@ -6,7 +6,6 @@ import dagger.Module;
import dagger.Provides;
import org.tasks.R;
import org.tasks.billing.Inventory;
import org.tasks.fragments.TaskEditControlSetFragmentManager;
import org.tasks.gtasks.PlayServices;
import org.tasks.location.GoogleMapFragment;
import org.tasks.location.GooglePlacesSearchProvider;
@ -15,7 +14,6 @@ import org.tasks.location.MapboxMapFragment;
import org.tasks.location.MapboxSearchProvider;
import org.tasks.location.PlaceSearchProvider;
import org.tasks.preferences.Preferences;
import org.tasks.sync.SyncAdapters;
import org.tasks.themes.ThemeAccent;
import org.tasks.themes.ThemeBase;
import org.tasks.themes.ThemeCache;
@ -59,13 +57,6 @@ public class ActivityModule {
return themeCache.getThemeAccent(preferences.getInt(R.string.p_theme_accent, 1));
}
@Provides
@ActivityScope
public TaskEditControlSetFragmentManager getTaskEditControlSetFragmentManager(
Preferences preferences, SyncAdapters syncAdapters) {
return new TaskEditControlSetFragmentManager(activity, preferences, syncAdapters);
}
@Provides
@ActivityScope
public PlaceSearchProvider getPlaceSearchProvider(

@ -5,7 +5,7 @@ import org.tasks.activities.CalendarSelectionDialog;
import org.tasks.activities.RemoteListSupportPicker;
import org.tasks.dialogs.AddAttachmentDialog;
import org.tasks.dialogs.ColorPickerDialog;
import org.tasks.dialogs.LocationDialog;
import org.tasks.dialogs.GeofenceDialog;
import org.tasks.dialogs.RecordAudioDialog;
import org.tasks.dialogs.SeekBarDialog;
import org.tasks.dialogs.SortDialog;
@ -37,7 +37,7 @@ public interface DialogFragmentComponent {
void inject(BasicRecurrenceDialog basicRecurrenceDialog);
void inject(LocationDialog locationDialog);
void inject(GeofenceDialog geofenceDialog);
void inject(SeekBarDialog seekBarDialog);
}

@ -77,6 +77,7 @@ public class BasicPreferences extends InjectingPreferenceActivity
@Inject Inventory inventory;
@Inject PlayServices playServices;
@Inject Toaster toaster;
@Inject Device device;
private Bundle result;
@ -238,8 +239,8 @@ public class BasicPreferences extends InjectingPreferenceActivity
return;
}
} else if (which == 1) {
if (!playServices.isPlayServicesAvailable()) {
toaster.longToast(R.string.requires_google_play_services);
if (!playServices.refreshAndCheck()) {
playServices.resolve(this);
dialog.dismiss();
return;
}
@ -272,8 +273,8 @@ public class BasicPreferences extends InjectingPreferenceActivity
return;
}
} else if (which == 1) {
if (!playServices.isPlayServicesAvailable()) {
toaster.longToast(R.string.requires_google_play_services);
if (!playServices.refreshAndCheck()) {
playServices.resolve(this);
dialog.dismiss();
return;
}

@ -29,10 +29,6 @@ public class Device {
this.locale = locale;
}
public static boolean SupportsLocationServices(Context context) {
return context.getResources().getBoolean(R.bool.location_enabled);
}
public boolean hasCamera() {
return context
.getPackageManager()
@ -47,8 +43,12 @@ public class Device {
return intent.resolveActivity(context.getPackageManager()) != null;
}
public boolean supportsLocationServices() {
return SupportsLocationServices(context);
public boolean supportsMaps() {
return context.getResources().getBoolean(R.bool.support_maps);
}
public boolean supportsGeofences() {
return context.getResources().getBoolean(R.bool.support_geofences);
}
public boolean voiceInputAvailable() {

@ -2,7 +2,8 @@ package org.tasks.ui;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static org.tasks.dialogs.LocationDialog.newLocationDialog;
import static org.tasks.PermissionUtil.verifyPermissions;
import static org.tasks.dialogs.GeofenceDialog.newGeofenceDialog;
import static org.tasks.location.LocationPickerActivity.EXTRA_PLACE;
import android.app.Activity;
@ -36,17 +37,21 @@ import org.tasks.data.Location;
import org.tasks.data.LocationDao;
import org.tasks.data.Place;
import org.tasks.dialogs.DialogBuilder;
import org.tasks.dialogs.LocationDialog;
import org.tasks.dialogs.GeofenceDialog;
import org.tasks.injection.FragmentComponent;
import org.tasks.location.GeofenceApi;
import org.tasks.location.LocationPickerActivity;
import org.tasks.preferences.Device;
import org.tasks.preferences.FragmentPermissionRequestor;
import org.tasks.preferences.PermissionChecker;
import org.tasks.preferences.PermissionRequestor;
import org.tasks.preferences.Preferences;
public class LocationControlSet extends TaskEditControlFragment {
public static final int TAG = R.string.TEA_ctrl_locations_pref;
private static final int REQUEST_LOCATION_REMINDER = 12153;
private static final int REQUEST_LOCATION_DETAILS = 12154;
private static final int REQUEST_GEOFENCE_DETAILS = 12154;
private static final String FRAG_TAG_LOCATION_DIALOG = "location_dialog";
private static final String EXTRA_ORIGINAL = "extra_original_location";
private static final String EXTRA_LOCATION = "extra_new_location";
@ -55,6 +60,9 @@ public class LocationControlSet extends TaskEditControlFragment {
@Inject DialogBuilder dialogBuilder;
@Inject GeofenceApi geofenceApi;
@Inject LocationDao locationDao;
@Inject Device device;
@Inject FragmentPermissionRequestor permissionRequestor;
@Inject PermissionChecker permissionChecker;
@BindView(R.id.location_name)
TextView locationName;
@ -62,8 +70,8 @@ public class LocationControlSet extends TaskEditControlFragment {
@BindView(R.id.location_address)
TextView locationAddress;
@BindView(R.id.location_more)
ImageView locationOptions;
@BindView(R.id.geofence_options)
ImageView geofenceOptions;
private Location original;
private Location location;
@ -78,27 +86,39 @@ public class LocationControlSet extends TaskEditControlFragment {
if (!task.isNew()) {
original = locationDao.getGeofences(task.getId());
if (original != null) {
setLocation(new Location(original.geofence, original.place));
location = new Location(original.geofence, original.place);
}
}
} else {
original = savedInstanceState.getParcelable(EXTRA_ORIGINAL);
setLocation(savedInstanceState.getParcelable(EXTRA_LOCATION));
location = savedInstanceState.getParcelable(EXTRA_LOCATION);
}
return view;
}
@Override
public void onResume() {
super.onResume();
updateUi();
}
private void setLocation(@Nullable Location location) {
this.location = location;
updateUi();
}
private void updateUi() {
if (this.location == null) {
locationName.setText("");
locationOptions.setVisibility(View.GONE);
geofenceOptions.setVisibility(View.GONE);
locationAddress.setVisibility(View.GONE);
} else {
locationOptions.setVisibility(View.VISIBLE);
locationOptions.setImageResource(
this.location.isArrival() || this.location.isDeparture()
geofenceOptions.setVisibility(device.supportsGeofences() ? View.VISIBLE : View.GONE);
geofenceOptions.setImageResource(
permissionChecker.canAccessLocation()
&& (this.location.isArrival() || this.location.isDeparture())
? R.drawable.ic_outline_notifications_24px
: R.drawable.ic_outline_notifications_off_24px);
String name = this.location.getDisplayName();
@ -155,10 +175,34 @@ public class LocationControlSet extends TaskEditControlFragment {
startActivityForResult(intent, REQUEST_LOCATION_REMINDER);
}
@OnClick(R.id.location_more)
void locationOptions(View view) {
LocationDialog dialog = newLocationDialog(location);
dialog.setTargetFragment(this, REQUEST_LOCATION_DETAILS);
@OnClick(R.id.geofence_options)
void geofenceOptions(View view) {
if (permissionRequestor.requestFineLocation()) {
showGeofenceOptions();
}
}
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PermissionRequestor.REQUEST_LOCATION) {
if (verifyPermissions(grantResults)) {
showGeofenceOptions();
} else {
dialogBuilder
.newMessageDialog(R.string.location_permission_required_geofence)
.setTitle(R.string.missing_permissions)
.setPositiveButton(android.R.string.ok, null)
.show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private void showGeofenceOptions() {
GeofenceDialog dialog = newGeofenceDialog(location);
dialog.setTargetFragment(this, REQUEST_GEOFENCE_DETAILS);
dialog.show(getFragmentManager(), FRAG_TAG_LOCATION_DIALOG);
}
@ -237,25 +281,31 @@ public class LocationControlSet extends TaskEditControlFragment {
if (requestCode == REQUEST_LOCATION_REMINDER) {
if (resultCode == Activity.RESULT_OK) {
Place place = data.getParcelableExtra(EXTRA_PLACE);
Geofence geofence = new Geofence();
Geofence geofence;
if (location == null) {
geofence.setRadius(preferences.getInt(R.string.p_default_location_radius, 250));
int defaultReminders =
preferences.getIntegerFromString(R.string.p_default_location_reminder_key, 1);
geofence.setArrival(defaultReminders == 1 || defaultReminders == 3);
geofence.setDeparture(defaultReminders == 2 || defaultReminders == 3);
geofence =
new Geofence(
place.getUid(),
defaultReminders == 1 || defaultReminders == 3,
defaultReminders == 2 || defaultReminders == 3,
preferences.getInt(R.string.p_default_location_radius, 250));
} else {
Geofence existing = location.geofence;
geofence.setArrival(existing.isArrival());
geofence.setDeparture(existing.isDeparture());
geofence.setRadius(existing.getRadius());
geofence =
new Geofence(
place.getUid(),
existing.isArrival(),
existing.isDeparture(),
existing.getRadius());
}
setLocation(new Location(geofence, place));
}
} else if (requestCode == REQUEST_LOCATION_DETAILS) {
} else if (requestCode == REQUEST_GEOFENCE_DETAILS) {
if (resultCode == Activity.RESULT_OK) {
location.geofence = data.getParcelableExtra(LocationDialog.EXTRA_GEOFENCE);
setLocation(location);
location.geofence = data.getParcelableExtra(GeofenceDialog.EXTRA_GEOFENCE);
updateUi();
}
} else {
super.onActivityResult(requestCode, resultCode, data);

@ -4,11 +4,11 @@
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#EF5350"
android:fillColor="#e22b29"
android:pathData="M38.2558,14.5577C38.2558,7.0849 31.944,1.026 24.1527,1.0019V1C24.1454,1 24.1372,1.0009 24.1289,1.0009C24.1217,1.0009 24.1135,1 24.1062,1V1.0019C16.3143,1.026 10.0031,7.0849 10.0031,14.5577C10.0031,14.5577 9.8545,17.9323 11.6149,21.4284C12.9266,24.0362 14.5912,25.7794 16.3003,28.1506C18.9353,31.8058 20.187,33.7253 21.5007,37.2636C22.4339,39.7745 23.3293,42.7376 24.1285,47C24.9286,42.7376 25.8245,39.7745 26.7577,37.2636C28.0728,33.7248 29.3245,31.8054 31.9581,28.1506C33.6672,25.7798 35.3308,24.0362 36.644,21.4284C38.4039,17.9323 38.2558,14.5577 38.2558,14.5577ZM24.1193,19.463C21.2291,19.463 18.8874,17.2184 18.8874,14.4482C18.8874,11.6794 21.2287,9.4358 24.1193,9.4358C27.0104,9.4358 29.3516,11.6794 29.3516,14.4482C29.3516,17.2179 27.0104,19.463 24.1193,19.463Z"
android:strokeWidth="1.0"
android:strokeColor="#ffffff" />
<path
android:fillColor="#952F2D"
android:fillColor="#6d0a0f"
android:pathData="M18,14.4166a6,5.75 0,1 0,12 0a6,5.75 0,1 0,-12 0z" />
</vector>

@ -7,6 +7,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/header_gap"
android:orientation="vertical">
<Switch
android:id="@+id/location_arrival"

@ -5,7 +5,7 @@
android:baselineAligned="false">
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/location_more"
android:id="@+id/geofence_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
@ -26,8 +26,8 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@id/location_more"
android:layout_toStartOf="@id/location_more"
android:layout_toLeftOf="@id/geofence_options"
android:layout_toStartOf="@id/geofence_options"
android:clickable="true"
android:focusable="true"
android:hint="@string/add_location"
@ -42,8 +42,8 @@
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/location_name"
android:layout_toLeftOf="@id/location_more"
android:layout_toStartOf="@id/location_more"
android:layout_toLeftOf="@id/geofence_options"
android:layout_toStartOf="@id/geofence_options"
android:clickable="true"
android:ellipsize="end"
android:focusable="true"

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="two_pane_layout">false</bool>
<bool name="location_enabled">false</bool>
<bool name="default_bundle_notifications">false</bool>
</resources>

@ -878,7 +878,6 @@ File %1$s contained %2$s.\n\n
<string name="map_provider">Map provider</string>
<string name="map_search_provider">Search provider</string>
<string name="requires_android_version">Requires Android %s</string>
<string name="requires_google_play_services">Requires Google Play Services</string>
<string name="missing_permissions">Missing permissions</string>
<string name="location_permission_required_geofence">Location permissions are needed for location reminders</string>
<string name="location_permission_required_location">Location permissions are needed to find your current location</string>

Loading…
Cancel
Save