diff --git a/app/build.gradle b/app/build.gradle
index 5e578bc..7822a96 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -39,6 +39,7 @@ dependencies {
//Google Maps SDK
implementation 'com.google.android.gms:play-services-maps:19.1.0'
+ implementation 'com.google.android.gms:play-services-location:21.3.0'
// Glide
implementation 'com.github.bumptech.glide:glide:4.16.0' // Check for the latest version
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 533cec3..9591bd0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
+
@@ -39,6 +40,9 @@
android:name=".workers.SleepTimerHelper"
android:foregroundServiceType="specialUse" />
+
+
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/DoerflingerHelpersDeviceAdminReceiver.java b/app/src/main/java/com/aldo/apps/familyhelpers/DoerflingerHelpersDeviceAdminReceiver.java
index 114981b..983e8eb 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/DoerflingerHelpersDeviceAdminReceiver.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/DoerflingerHelpersDeviceAdminReceiver.java
@@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
public class DoerflingerHelpersDeviceAdminReceiver extends DeviceAdminReceiver {
@Override
- public void onEnabled(@NonNull final Context context, @NonNull final Intent intent) {
+ public void onEnabled(@NonNull final Context context, @NonNull final Intent intent) {
// Called when the app is enabled as a device administrator.
}
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/HelperGridActivity.java b/app/src/main/java/com/aldo/apps/familyhelpers/HelperGridActivity.java
index 66f126e..9c276bd 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/HelperGridActivity.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/HelperGridActivity.java
@@ -1,7 +1,6 @@
package com.aldo.apps.familyhelpers;
import static android.Manifest.permission.POST_NOTIFICATIONS;
-
import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SIGN_IN_PROVIDERS;
import android.content.Intent;
@@ -20,8 +19,8 @@ import androidx.core.content.ContextCompat;
import com.aldo.apps.familyhelpers.ui.HelperGroupTile;
import com.aldo.apps.familyhelpers.ui.SleepTimerPopup;
import com.aldo.apps.familyhelpers.utils.DevicePolicyManagerHelper;
-import com.aldo.apps.familyhelpers.workers.LocationHelper;
import com.aldo.apps.familyhelpers.workers.DatabaseHelper;
+import com.aldo.apps.familyhelpers.workers.LocationHelper;
import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract;
import com.firebase.ui.auth.IdpResponse;
@@ -67,11 +66,10 @@ public class HelperGridActivity extends AppCompatActivity {
private FirebaseUser mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
/**
- * The instance of the {@link DatabaseHelper}.
+ * The {@link ActivityResultLauncher} for the sign in of a firebase user.
*/
- private DatabaseHelper mDbHelper;
-
- /**
+ private final ActivityResultLauncher mSignInLauncher =
+ registerForActivityResult(new FirebaseAuthUIActivityResultContract(), this::onSignInResult); /**
* The {@link ActivityResultLauncher} to ask for the NotificationPermission.
*/
private final ActivityResultLauncher mRequestPermissionLauncher =
@@ -87,12 +85,6 @@ public class HelperGridActivity extends AppCompatActivity {
}
});
- /**
- * The {@link ActivityResultLauncher} for the sign in of a firebase user.
- */
- private final ActivityResultLauncher mSignInLauncher =
- registerForActivityResult(new FirebaseAuthUIActivityResultContract(), this::onSignInResult);
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -108,7 +100,6 @@ public class HelperGridActivity extends AppCompatActivity {
} else {
mWelcomeMessageView.setText(String.format(getString(R.string.welcome_message_placeholder),
mCurrentUser.getDisplayName()));
- mDbHelper = new DatabaseHelper();
mLocationHelper = LocationHelper.getInstance(this);
}
}
@@ -159,7 +150,13 @@ public class HelperGridActivity extends AppCompatActivity {
@Override
public void launchHelper() {
Log.d(TAG, "launchHelper: Clicked ShareLocation");
- if (mLocationHelper.requestLocationPermissions(HelperGridActivity.this)) {
+ // First check if the notification permission is granted
+ if (!requestNotificationPermission()) {
+ Log.d(TAG, "launchHelper: Notifications not allowed, return...");
+ return;
+ }
+ if (mLocationHelper.requestLocationPermissions(HelperGridActivity.this)
+ && mLocationHelper.requestBackgroundLocationPermission(HelperGridActivity.this)) {
Log.d(TAG, "launchHelper: Permission already granted");
final Intent intent = new Intent(HelperGridActivity.this, ShareLocationActivity.class);
startActivity(intent);
@@ -196,14 +193,13 @@ public class HelperGridActivity extends AppCompatActivity {
*
* @param result The result code, used to determine whether is succeeded or not.
*/
- private void onSignInResult(final FirebaseAuthUIAuthenticationResult result) {
+ private void onSignInResult(final FirebaseAuthUIAuthenticationResult result) {
final IdpResponse idpResponse = result.getIdpResponse();
if (result.getResultCode() == RESULT_OK) {
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
Log.d(TAG, "onSignInResult: Successfully logged in [" + mCurrentUser.getDisplayName() + "]");
mWelcomeMessageView.setText(String.format(getString(R.string.welcome_message_placeholder),
mCurrentUser.getDisplayName()));
- mDbHelper = new DatabaseHelper();
mLocationHelper = LocationHelper.getInstance(this);
} else {
Log.w(TAG, "onSignInResult: Sign-In failed");
@@ -213,7 +209,7 @@ public class HelperGridActivity extends AppCompatActivity {
Log.w(TAG, "onSignInResult: User canceled, cannot continue");
} else {
Log.e(TAG, "onSignInResult: Login failed with errorCode ["
- + idpResponse.getError().getErrorCode() + "]");
+ + idpResponse.getError().getErrorCode() + "]");
}
}
}
@@ -223,10 +219,12 @@ public class HelperGridActivity extends AppCompatActivity {
@NonNull final String[] permissions,
@NonNull final int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (mLocationHelper.handlePermissionResult(requestCode, grantResults)) {
+ if (mLocationHelper.handlePermissionResult(HelperGridActivity.this, requestCode, grantResults)) {
final Intent intent = new Intent(HelperGridActivity.this, ShareLocationActivity.class);
startActivity(intent);
}
}
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/ShareLocationActivity.java b/app/src/main/java/com/aldo/apps/familyhelpers/ShareLocationActivity.java
index 4f62661..3949052 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/ShareLocationActivity.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/ShareLocationActivity.java
@@ -2,19 +2,16 @@ package com.aldo.apps.familyhelpers;
import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_HOME_LATITUDE;
import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_HOME_LONGITUDE;
-import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS;
-import static com.aldo.apps.familyhelpers.utils.GlobalConstants.DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS;
import static com.aldo.apps.familyhelpers.utils.GlobalConstants.METER_PER_SECOND_TO_KMH_CONVERTER;
+import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import android.widget.CompoundButton;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -27,6 +24,7 @@ import com.aldo.apps.familyhelpers.model.User;
import com.aldo.apps.familyhelpers.ui.ActiveShareAdapter;
import com.aldo.apps.familyhelpers.workers.DatabaseHelper;
import com.aldo.apps.familyhelpers.workers.LocationHelper;
+import com.aldo.apps.familyhelpers.workers.ShareLocationBackgroundWorker;
import com.bumptech.glide.Glide;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
@@ -40,8 +38,6 @@ import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
-import org.checkerframework.checker.units.qual.A;
-
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -61,95 +57,77 @@ public class ShareLocationActivity extends AppCompatActivity implements OnMapRea
* Tag for debugging purpose.
*/
private static final String TAG = "ShareLocationActivity";
-
+ /**
+ * Map containing all markers and the corresponding ID.
+ */
+ private final Map mMarkerMap = new HashMap<>();
+ /**
+ * {@link List} of all {@link User}s.
+ */
+ private final List mAllUsers = new ArrayList<>();
/**
* The {@link GoogleMap} view.
*/
private GoogleMap mGmap;
-
/**
* The {@link DatabaseHelper} to read and load data from.
*/
private DatabaseHelper mDbHelper;
-
/**
* The currently logged in {@link FirebaseUser}.
*/
private FirebaseUser mCurrentUser;
-
/**
* The ID of the location updates to listen to.
*/
private String mShareId;
-
/**
* The InfoBox {@link ImageView} showing the user icon.
*/
private ImageView mInfoBoxIcon;
-
/**
* The InfoBox {@link TextView} showing the title.
*/
private TextView mInfoBoxTitle;
-
/**
* The InfoBox {@link TextView} showing the Location information.
*/
private TextView mInfoBoxLocation;
-
/**
* The InfoBox {@link TextView} showing the altitude..
*/
private TextView mInfoBoxAltitude;
-
/**
* The InfoBox {@link TextView} showing the last received speed.
*/
private TextView mInfoBoxSpeed;
-
/**
* The InfoBox {@link TextView} showing the timestamp of the last update.
*/
private TextView mInfoBoxTimeStamp;
-
/**
* The {@link Disposable} holding the subscription to the {@link LocationObject}
* {@link io.reactivex.rxjava3.subjects.BehaviorSubject} in order to have it cancellable.
*/
private Disposable mLocationUpdateSubscription;
-
/**
* The {@link Disposable} holding the subscription to the {@link String}
* {@link io.reactivex.rxjava3.subjects.BehaviorSubject} in order to know whom to follow.
*/
private Disposable mCurrentlyFollowingSubscription;
-
/**
* The {@link Disposable} holding the subscription to {@link User}
* {@link io.reactivex.rxjava3.subjects.BehaviorSubject} in order to have it cancellable.
*/
private Disposable mUserSubscription;
-
/**
* Boolean flag indicating whether the system is currently in night mode or not.
*/
private boolean mIsNightMode;
-
/**
* Reference to the Google Maps Marker, to update it's position rather than adding a new one.
*/
private Marker mGmapsMarker;
-
- /**
- * Map containing all markers and the corresponding ID.
- */
- private final Map mMarkerMap = new HashMap<>();
-
- /**
- * {@link List} of all {@link User}s.
- */
- private final List mAllUsers = new ArrayList<>();
-
/**
* The ID of who the user is currently following.
*/
@@ -186,22 +164,6 @@ public class ShareLocationActivity extends AppCompatActivity implements OnMapRea
mInfoBoxTimeStamp = findViewById(R.id.share_location_info_timestamp);
mNoActiveShares = findViewById(R.id.tv_no_active_shares);
mActiveShares = findViewById(R.id.active_share_layout);
- final MaterialSwitch shareLocationToggle = findViewById(R.id.switch_start_stop_sharing_location);
- final LocationHelper locationHelper = LocationHelper.getInstance(this);
- shareLocationToggle.setChecked(locationHelper.isCurrentlySharing());
- shareLocationToggle.setOnCheckedChangeListener((buttonView, isChecked) -> {
- if (isChecked) {
- locationHelper.startLocationUpdates(ShareLocationActivity.this,
- DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS,
- DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS)
- ;
- } else {
- locationHelper.stopLocationUpdates();
- }
- });
-
- locationHelper.getSharingStateSubject().subscribe(isSharing -> shareLocationToggle.setChecked(isSharing),
- this::handleSubscriptionError);
mActiveShares.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mActiveShareAdapter = new ActiveShareAdapter(this);
@@ -225,6 +187,8 @@ public class ShareLocationActivity extends AppCompatActivity implements OnMapRea
if (mLocationUpdateSubscription != null) {
mLocationUpdateSubscription.dispose();
}
+
+ initAndSetupShareToggle();
mUserSubscription = mDbHelper.getAllUsers()
.subscribe(this::handleAllUsers, this::handleUserSubscriptionFailed);
mLocationUpdateSubscription = mDbHelper.subscribeToAllLocationUpdates()
@@ -233,6 +197,28 @@ public class ShareLocationActivity extends AppCompatActivity implements OnMapRea
.subscribe(this::handleCurrentlyFollowingChanged, this::handleSubscriptionError);
}
+ /**
+ * Initializes the share switch button.
+ */
+ private void initAndSetupShareToggle() {
+ final MaterialSwitch shareLocationToggle = findViewById(R.id.switch_start_stop_sharing_location);
+
+ final LocationHelper locationHelper = LocationHelper.getInstance(this);
+ shareLocationToggle.setChecked(locationHelper.isCurrentlySharing());
+ shareLocationToggle.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (isChecked) {
+ final Intent shareLocationService = new Intent(this, ShareLocationBackgroundWorker.class);
+ startForegroundService(shareLocationService);
+ } else {
+ final Intent stopLocationService = new Intent(this, ShareLocationBackgroundWorker.class);
+ stopService(stopLocationService);
+ }
+ });
+
+ locationHelper.getSharingStateSubject().subscribe(isSharing -> shareLocationToggle.setChecked(isSharing),
+ this::handleSubscriptionError);
+ }
+
@Override
protected void onPause() {
super.onPause();
@@ -291,11 +277,11 @@ public class ShareLocationActivity extends AppCompatActivity implements OnMapRea
}
- /**
- * Removed all markers that became invalid because the sharing was stopped.
- *
- * @param locationObjectMap The {@link Map} matching shareIds to {@link LocationObject}s.
- */
+ /**
+ * Removed all markers that became invalid because the sharing was stopped.
+ *
+ * @param locationObjectMap The {@link Map} matching shareIds to {@link LocationObject}s.
+ */
private void removeInvalidExistingMarkers(final Map locationObjectMap) {
final List toBeRemovedKeys = new ArrayList<>();
for (Map.Entry markerEntry : mMarkerMap.entrySet()) {
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/model/LocationObject.java b/app/src/main/java/com/aldo/apps/familyhelpers/model/LocationObject.java
index 7fc5597..ff70331 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/model/LocationObject.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/model/LocationObject.java
@@ -68,6 +68,19 @@ public class LocationObject {
this.timestamp = timestamp;
}
+ /**
+ * Helper method to create a {@link LocationObject} from a handed in {@link Location}.
+ *
+ * @param location The received {@link Location} from the locationManager.
+ * @return The created {@link LocationObject}.
+ */
+ public static LocationObject fromLocation(final Location location) {
+ final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
+ return new LocationObject(firebaseUser.getUid(), location.getLatitude(),
+ location.getLongitude(), location.getAltitude(), location.getSpeed(),
+ location.getTime());
+ }
+
/**
* Returns the unique identifier for the shared location.
*
@@ -122,20 +135,6 @@ public class LocationObject {
return timestamp;
}
- /**
- * Helper method to create a {@link LocationObject} from a handed in {@link Location}.
- *
- * @param location The received {@link Location} from the locationManager.
- *
- * @return The created {@link LocationObject}.
- */
- public static LocationObject fromLocation(final Location location) {
- final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
- return new LocationObject(firebaseUser.getUid(), location.getLatitude(),
- location.getLongitude(), location.getAltitude(), location.getSpeed(),
- location.getTime());
- }
-
@NonNull
@Override
public String toString() {
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/model/User.java b/app/src/main/java/com/aldo/apps/familyhelpers/model/User.java
index 0eb7103..676addf 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/model/User.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/model/User.java
@@ -55,6 +55,30 @@ public class User {
this.creationDate = creationDate;
}
+ /**
+ * Creates a {@link User} from a handed in {@link FirebaseUser}.
+ *
+ * @param firebaseUser The {@link FirebaseUser} to read the fields from.
+ * @return The {@link User} representation of the {@link FirebaseUser}, or null if no
+ * {@link FirebaseUser} is available.
+ */
+ public static User fromFirebaseUser(final FirebaseUser firebaseUser) {
+ if (firebaseUser == null) {
+ return null;
+ }
+ final String uid = firebaseUser.getUid();
+ final String displayName = firebaseUser.getDisplayName();
+ final Uri photoUrl = firebaseUser.getPhotoUrl();
+ final FirebaseUserMetadata metaData = firebaseUser.getMetadata();
+ final long creationDate;
+ if (metaData == null) {
+ creationDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
+ } else {
+ creationDate = metaData.getCreationTimestamp();
+ }
+ return new User(uid, displayName, photoUrl == null ? null : photoUrl.toString(), creationDate);
+ }
+
/**
* Returns the unique Identifies of the user.
*
@@ -91,31 +115,6 @@ public class User {
return creationDate;
}
- /**
- * Creates a {@link User} from a handed in {@link FirebaseUser}.
- *
- * @param firebaseUser The {@link FirebaseUser} to read the fields from.
- *
- * @return The {@link User} representation of the {@link FirebaseUser}, or null if no
- * {@link FirebaseUser} is available.
- */
- public static User fromFirebaseUser(final FirebaseUser firebaseUser) {
- if (firebaseUser == null) {
- return null;
- }
- final String uid = firebaseUser.getUid();
- final String displayName = firebaseUser.getDisplayName();
- final Uri photoUrl = firebaseUser.getPhotoUrl();
- final FirebaseUserMetadata metaData = firebaseUser.getMetadata();
- final long creationDate;
- if (metaData == null) {
- creationDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
- } else {
- creationDate = metaData.getCreationTimestamp();
- }
- return new User(uid,displayName, photoUrl == null ? null : photoUrl.toString(), creationDate);
- }
-
@Override
public String toString() {
return "User{" +
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/ui/ActiveShareAdapter.java b/app/src/main/java/com/aldo/apps/familyhelpers/ui/ActiveShareAdapter.java
index f4b659e..414d2c1 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/ui/ActiveShareAdapter.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/ui/ActiveShareAdapter.java
@@ -1,7 +1,6 @@
package com.aldo.apps.familyhelpers.ui;
import android.content.Context;
-import android.graphics.PorterDuff;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
@@ -10,7 +9,6 @@ import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.aldo.apps.familyhelpers.R;
@@ -20,20 +18,46 @@ import com.bumptech.glide.Glide;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import de.hdodenhof.circleimageview.CircleImageView;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
+/**
+ * The {@link RecyclerView.Adapter} for the {@link ActiveShareAdapter.ActiveShareViewHolder} to display
+ * which user is currently sharing their location and to offer a selection on whom to follow.
+ */
public class ActiveShareAdapter extends RecyclerView.Adapter {
+
+ /**
+ * Tag for debugging purposes.
+ */
private static final String TAG = "ActiveShareAdapter";
+ /**
+ * {@link BehaviorSubject} holding the ID of the currently selected user.
+ */
private final BehaviorSubject mCurrentlySelectedSubject = BehaviorSubject.createDefault("");
+ /**
+ * {@link List} of all currently sharing {@link User}s.
+ */
private final List mSharingUserList = new ArrayList<>();
+ /**
+ * A {@link WeakReference} to the calling {@link Context}.
+ */
private final WeakReference mContextRef;
+ /**
+ * List of all {@link View}s so the focus can be cleared again if another view is touched.
+ */
+ private final List mAllItems = new ArrayList<>();
+
+ /**
+ * C'Tor.
+ *
+ * @param context Calling context.
+ */
public ActiveShareAdapter(final Context context) {
mContextRef = new WeakReference<>(context);
}
@@ -43,6 +67,7 @@ public class ActiveShareAdapter extends RecyclerView.Adapter newUsers) {
mSharingUserList.clear();
mSharingUserList.addAll(newUsers);
+ mAllItems.clear();
notifyDataSetChanged();
}
+ /**
+ * Returns the {@link BehaviorSubject} holding the ID of the currently selected user.
+ *
+ * @return The {@link BehaviorSubject} holding the ID of the currently selected user.
+ */
public BehaviorSubject getCurrentlySelectedSubject() {
return mCurrentlySelectedSubject;
}
+ /**
+ * Helper method to clear the selected state of all views, when a new one is tapped.
+ */
+ private void clearFocusedView() {
+ for (final View view : mAllItems) {
+ view.setSelected(false);
+ }
+ }
+
+ /**
+ * {@link RecyclerView.ViewHolder} implementation for the {@link ActiveShareViewHolder}.
+ */
public class ActiveShareViewHolder extends RecyclerView.ViewHolder {
- private CircleImageView mProfilePicture;
+ /**
+ * The {@link CircleImageView} holding the profile picture of the user.
+ */
+ private final CircleImageView mProfilePicture;
- private TextView mName;
+ /**
+ * The {@link TextView} showing the name of the user.
+ */
+ private final TextView mName;
- private View mItemView;
+ /**
+ * The overall {@link View}.
+ */
+ private final View mItemView;
+ /**
+ * C'Tor.
+ *
+ * @param itemView The already inflated itemView.
+ */
public ActiveShareViewHolder(@NonNull final View itemView) {
super(itemView);
mProfilePicture = itemView.findViewById(R.id.active_share_profile_picture);
@@ -83,6 +144,11 @@ public class ActiveShareAdapter extends RecyclerView.Adapter {
Log.d(TAG, "setUserData: Clicked on [" + user + "]");
- mCurrentlySelectedSubject.onNext(user.getuId());
+ if (mItemView.isSelected()) {
+ mCurrentlySelectedSubject.onNext("");
+ clearFocusedView();
+ mItemView.setSelected(false);
+ } else {
+ mCurrentlySelectedSubject.onNext(user.getuId());
+ clearFocusedView();
+ mItemView.setSelected(true);
+ }
});
mName.setText(user.getDisplayName());
final Context context = mContextRef.get();
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/utils/CancelLocationSharingReceiver.java b/app/src/main/java/com/aldo/apps/familyhelpers/utils/CancelLocationSharingReceiver.java
deleted file mode 100644
index 671f2df..0000000
--- a/app/src/main/java/com/aldo/apps/familyhelpers/utils/CancelLocationSharingReceiver.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.aldo.apps.familyhelpers.utils;
-
-import static com.aldo.apps.familyhelpers.utils.GlobalConstants.SHARE_LOCATION_CANCEL_ACTION;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import com.aldo.apps.familyhelpers.workers.LocationHelper;
-
-/**
- * Broadcast received to cancel an ongoing sharing of location.
- */
-public class CancelLocationSharingReceiver extends BroadcastReceiver {
-
- /**
- * Tag for debugging purpose.
- */
- private static final String TAG = "CancelLocationSharingRe";
-
- /**
- * Empty C'tor.
- */
- public CancelLocationSharingReceiver() {
- // Empty C'tor.
- }
-
-
- @Override
- public void onReceive(final Context context, final Intent intent) {
- if (intent != null && SHARE_LOCATION_CANCEL_ACTION.equalsIgnoreCase(intent.getAction())) {
- Log.d(TAG, "onReceive: Notification cancelled, cancel location sharing");
- final LocationHelper locationHelper = LocationHelper.getInstance(context);
- locationHelper.stopLocationUpdates();
- }
- }
-}
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/utils/DevicePolicyManagerHelper.java b/app/src/main/java/com/aldo/apps/familyhelpers/utils/DevicePolicyManagerHelper.java
index 344d020..892dfe1 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/utils/DevicePolicyManagerHelper.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/utils/DevicePolicyManagerHelper.java
@@ -54,7 +54,6 @@ public final class DevicePolicyManagerHelper {
* Returns the singleton instance of the {@link DevicePolicyManagerHelper}.
*
* @param context The {@link Context} from where this was called.
- *
* @return the singleton instance of the {@link DevicePolicyManagerHelper}.
*/
public static DevicePolicyManagerHelper getInstance(final Context context) {
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/utils/GlobalConstants.java b/app/src/main/java/com/aldo/apps/familyhelpers/utils/GlobalConstants.java
index 5e6027a..a1ce84c 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/utils/GlobalConstants.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/utils/GlobalConstants.java
@@ -3,6 +3,7 @@ package com.aldo.apps.familyhelpers.utils;
import com.firebase.ui.auth.AuthUI;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -10,88 +11,75 @@ import java.util.List;
*/
public final class GlobalConstants {
- /**
- * Private C'tor to prevent instantiation.
- */
- private GlobalConstants() {}
-
/**
* ID of the NotificationChannel for the SleepTimer Notification.
*/
public static final String SLEEP_TIMER_CHANNEL_ID = "CountdownChannel";
-
/**
* ID of the NotificationChannel for the ShareLocation Notification.
*/
public static final String SHARE_LOCATION_CHANNEL_ID = "LocationShareChannel";
-
/**
* Factor to calculate seconds from milliseconds and vice versa.
*/
public static final int ONE_SECOND_IN_MILLIS = 1000;
-
/**
* Factor to calculate hours from minutes and vice versa.
*/
public static final int ONE_HOUR_IN_MINUTES = 60;
-
/**
* The NotificationID of the SleepTimer notification.
*/
public static final int SLEEP_TIMER_NOTIFICATION_ID = 1;
-
/**
* The NotificationID of the ShareLocation notification.
*/
public static final int SHARE_LOCATION_NOTIFICATION_ID = 2;
-
/**
* The action to be invoked when the sharing of location should be cancelled.
*/
public static final String SHARE_LOCATION_CANCEL_ACTION = "com.aldo.apps.familyhelpers.CANCEL_LOCATION_SHARING";
-
/**
* The key of the extra to be applied to the starting intent of the sleepTimer service,
* holding the initial duration in millis.
*/
public static final String SLEEP_TIMER_DURATION_MILLIS_EXTRA = "sleep_timer_duration";
-
/**
* Action to cancel an ongoing sleep timer.
*/
public static final String SLEEP_TIMER_CANCEL_ACTION = "SLEEP_TIMER_CANCEL";
-
/**
* Default minimum time interval between two location updates.
* Currently set to 5 Seconds.
*/
public static final int DEFAULT_MINIMUM_LOCATION_INTERVAL_MILLIS = 5000;
-
/**
* Default minimum distance interval between two location updates.
* Currently set to 5 Meters.
*/
public static final int DEFAULT_MINIMUM_LOCATION_INTERVAL_METERS = 5;
-
/**
* Conversion constants to convert m/s into km/h
*/
public static final double METER_PER_SECOND_TO_KMH_CONVERTER = 3.6;
-
/**
* Latitude of the default home (== Blaustein)
*/
public static final double DEFAULT_HOME_LATITUDE = 48.41965746149261;
-
/**
* Longitude of the default home (== Blaustein)
*/
public static final double DEFAULT_HOME_LONGITUDE = 9.909289365473684;
-
/**
* List of available Firebase signIn/Login providers.
*/
- public static final List SIGN_IN_PROVIDERS = Arrays.asList(
+ public static final List SIGN_IN_PROVIDERS = Collections.singletonList(
new AuthUI.IdpConfig.GoogleBuilder().build()
);
+
+ /**
+ * Private C'tor to prevent instantiation.
+ */
+ private GlobalConstants() {
+ }
}
diff --git a/app/src/main/java/com/aldo/apps/familyhelpers/workers/DatabaseHelper.java b/app/src/main/java/com/aldo/apps/familyhelpers/workers/DatabaseHelper.java
index 6c52c5f..aba3a90 100644
--- a/app/src/main/java/com/aldo/apps/familyhelpers/workers/DatabaseHelper.java
+++ b/app/src/main/java/com/aldo/apps/familyhelpers/workers/DatabaseHelper.java
@@ -2,22 +2,16 @@ package com.aldo.apps.familyhelpers.workers;
import static com.aldo.apps.familyhelpers.utils.DatabaseConstants.DB_COLL_LOCATION;
import static com.aldo.apps.familyhelpers.utils.DatabaseConstants.DB_COLL_USERS;
-import static com.aldo.apps.familyhelpers.utils.DatabaseConstants.DB_DOC_USER_ID;
import android.util.Log;
-import androidx.annotation.Nullable;
-
import com.aldo.apps.familyhelpers.model.LocationObject;
import com.aldo.apps.familyhelpers.model.User;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.DocumentSnapshot;
-import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
-import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.ListenerRegistration;
-import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import java.util.HashMap;
@@ -64,7 +58,7 @@ public class DatabaseHelper {
/**
* {@link Map} containing all users.
*/
- private Map mAllUserMap = new HashMap<>();
+ private final Map mAllUserMap = new HashMap<>();
/**
* C'tor.
@@ -119,6 +113,13 @@ public class DatabaseHelper {
return mAllUsers;
}
+ /**
+ * Returns a {@link User} object for the given ID.
+ *
+ * @param userId The identifier of the wanted user.
+ *
+ * @return The identified user or null of not existing.
+ */
public User getUserForId(final String userId) {
Log.d(TAG, "getUserForId() called with: userId = [" + userId + "]");
if (mAllUserMap.containsKey(userId)) {
@@ -162,25 +163,25 @@ public class DatabaseHelper {
mLocationUpdateListener = mDatabase.collection(DB_COLL_LOCATION)
.document(shareId)
.addSnapshotListener((value, error) -> {
- if (value == null) {
- Log.d(TAG, "onEvent: Location was deleted");
- mObservedLocation.onComplete();
- return;
- }
- final LocationObject updatedLocation = value.toObject(LocationObject.class);
- if (updatedLocation == null) {
- Log.w(TAG, "onEvent: Error while parsing, ignore");
- return;
- }
- mObservedLocation.onNext(updatedLocation);
- });
+ if (value == null) {
+ Log.d(TAG, "onEvent: Location was deleted");
+ mObservedLocation.onComplete();
+ return;
+ }
+ final LocationObject updatedLocation = value.toObject(LocationObject.class);
+ if (updatedLocation == null) {
+ Log.w(TAG, "onEvent: Error while parsing, ignore");
+ return;
+ }
+ mObservedLocation.onNext(updatedLocation);
+ });
}
/**
* Helper method to start listening for all available location sharings in progress.
*
* @return The {@link BehaviorSubject} containing a {@link Map} of all {@link LocationObject} matched
- * to the sharing ID.
+ * to the sharing ID.
*/
public BehaviorSubject