Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add allow-mock-accuracy for non-default geopoint and geoshape/geotrace #4857

Merged
merged 44 commits into from
Oct 22, 2021
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2ae0ef9
Push previousState down to subclasses as it's use is differnet in dif…
seadowg Sep 28, 2021
58cab49
Remove extra permission check from geo activities
seadowg Sep 28, 2021
1278d90
Remove unneeded super class
seadowg Sep 28, 2021
51fe955
Separate GeoPointMapActivity from CollectAbstractActivity
seadowg Sep 28, 2021
98ed778
Decouple GeoPointMapActivity from MapPreferencesFragment
seadowg Sep 30, 2021
0931da8
Extract interface for creating map fragments
seadowg Oct 12, 2021
9066129
Move maps interfaces to geo module
seadowg Oct 12, 2021
394e48c
Move activity extras constants to geo package
seadowg Oct 12, 2021
01b9714
Move GeoPointMapActivity to geo package
seadowg Oct 12, 2021
bd5b19b
Fix test imports
seadowg Oct 13, 2021
2a99e73
use fake MapFragment to test GeoPointMapActivity instead of real frag…
seadowg Oct 13, 2021
9882f67
Move to using ActivityScenario in GeoPointMapActivityTest
seadowg Oct 13, 2021
76a28b1
Move GeoPointMapActivityTest to geo module
seadowg Oct 13, 2021
f0eade7
Add pass-through setter for retain mock accuracy
seadowg Oct 13, 2021
c0eac92
Support retaining mock accuracy in GeoPointMapActivity
seadowg Oct 13, 2021
83d136c
Use same location sanitizer code for mapbox as everything else
seadowg Oct 13, 2021
542949f
Support retaining mock accuracy in MapboxMapFragment
seadowg Oct 13, 2021
5aa42ef
Add note to dagger setup
seadowg Oct 13, 2021
b9f73da
Remove dependency on CollectAbstractActivity from GeoPolyActivity
seadowg Oct 13, 2021
f27c4dd
Move dialog fragment helpers to androidshared
seadowg Oct 13, 2021
8384454
Move GeoPolySettingsDialogFragment to geo module
seadowg Oct 13, 2021
0e531be
Move GeoPolyActivity to geo module
seadowg Oct 13, 2021
0cf4c5b
Revise GeoPolyActivityTest to focus on LocationTracker rather than Lo…
seadowg Oct 13, 2021
de63d19
Use ActivityScenario for GeoPolyActivityTest
seadowg Oct 13, 2021
e3a6892
Move GeoPolyActivityTest to geo module
seadowg Oct 13, 2021
4456584
Send retain mock accuracy when starting GeoPolyActivity
seadowg Oct 14, 2021
5eddf8d
Support retain mock accuracy in GeoPolyActivity
seadowg Oct 14, 2021
cf8e9f7
Correct test name
seadowg Oct 19, 2021
1ac2d6e
Extract shared test fake
seadowg Oct 19, 2021
e1523ee
Optimize imports
seadowg Oct 19, 2021
5a242f9
Make sure test won't pass incorrectly
seadowg Oct 20, 2021
75b99e8
Move PermissionsChecker and rearrange packages in androidshared
seadowg Oct 20, 2021
95d83a4
Add permission checks back into geo Activity objects
seadowg Oct 20, 2021
9d5abb3
Grant permissions in tests
seadowg Oct 20, 2021
4484c53
Extract helper for returning single values from external app/activity
seadowg Oct 20, 2021
8532d95
Use external app helper to pull value out in tests
seadowg Oct 20, 2021
75254a8
Deprecate ANSWER_KEY constant
seadowg Oct 20, 2021
23d7b58
Add comment to ExternalAppUtils
seadowg Oct 20, 2021
f4ff908
Remove unused pro guard file
seadowg Oct 20, 2021
fa33b62
Remove unused desugaring
seadowg Oct 20, 2021
0004a36
Use singelton MapProvider instead of new one each time
seadowg Oct 21, 2021
4019f19
Don't inject dependency module dependencies in application object
seadowg Oct 21, 2021
3cc60f1
Add note about MapProvider needing to be a singleton
seadowg Oct 21, 2021
f0298d7
Optimize imports
seadowg Oct 21, 2021
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
1 change: 1 addition & 0 deletions androidshared/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dependencies {
implementation Dependencies.androidx_lifecycle_livedata_ktx
implementation Dependencies.android_material
implementation Dependencies.androidx_fragment_ktx
implementation Dependencies.timber

testImplementation project(':testshared')
testImplementation Dependencies.junit
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.odk.collect.androidshared.system

import android.content.Context
import android.util.TypedValue
import androidx.annotation.AttrRes

object ContextUtils {

@JvmStatic
fun getThemeAttributeValue(context: Context, @AttrRes resId: Int): Int {
val outValue = TypedValue()
context.theme.resolveAttribute(resId, outValue, true)
return outValue.data
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.odk.collect.androidshared.utils
package org.odk.collect.androidshared.system

import android.content.Context
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.odk.collect.android.permissions;
package org.odk.collect.androidshared.system;

import android.content.Context;
import android.content.pm.PackageManager;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.odk.collect.androidshared.ui

import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import timber.log.Timber

object DialogFragmentUtils {

@JvmStatic
fun <T : DialogFragment> showIfNotShowing(
dialogClass: Class<T>,
fragmentManager: FragmentManager
) {
showIfNotShowing(dialogClass, null, fragmentManager)
}

@JvmStatic
fun <T : DialogFragment> showIfNotShowing(
dialogClass: Class<T>,
args: Bundle?,
fragmentManager: FragmentManager
) {
showIfNotShowing(createNewInstance(dialogClass, args), dialogClass, fragmentManager)
}

@JvmStatic
fun <T : DialogFragment> showIfNotShowing(
newDialog: T,
dialogClass: Class<T>,
fragmentManager: FragmentManager
) {
if (fragmentManager.isStateSaved) {
return
}
val tag = dialogClass.name
val existingDialog = fragmentManager.findFragmentByTag(tag) as T?
if (existingDialog == null) {
newDialog.show(fragmentManager.beginTransaction(), tag)

// We need to execute this transaction. Otherwise a follow up call to this method
// could happen before the Fragment exists in the Fragment Manager and so the
// call to findFragmentByTag would return null and result in second dialog being show.
try {
fragmentManager.executePendingTransactions()
} catch (e: IllegalStateException) {
Timber.w(e)
}
}
}

@JvmStatic
fun dismissDialog(dialogClazz: Class<*>, fragmentManager: FragmentManager) {
val existingDialog = fragmentManager.findFragmentByTag(dialogClazz.name) as DialogFragment?
if (existingDialog != null) {
existingDialog.dismissAllowingStateLoss()

// We need to execute this transaction. Otherwise a next attempt to display a dialog
// could happen before the Fragment is dismissed in Fragment Manager and so the
// call to findFragmentByTag would return something (not null) and as a result the
// next dialog won't be displayed.
try {
fragmentManager.executePendingTransactions()
} catch (e: IllegalStateException) {
Timber.w(e)
}
}
}

private fun <T : DialogFragment> createNewInstance(dialogClass: Class<T>, args: Bundle?): T {
return try {
val instance = dialogClass.newInstance()
instance.arguments = args
instance
} catch (e: IllegalAccessException) {
// These would mean we have a non zero arg constructor for a Fragment
throw RuntimeException(e)
} catch (e: InstantiationException) {
throw RuntimeException(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.odk.collect.androidshared.utils
package org.odk.collect.androidshared.ui

import android.app.Activity
import android.app.Application
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
package org.odk.collect.android.utilities;
package org.odk.collect.androidshared.utils;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import android.os.Bundle;

Expand All @@ -10,47 +13,44 @@

import org.junit.Test;
import org.junit.runner.RunWith;
import org.odk.collect.androidshared.ui.DialogFragmentUtils;
import org.robolectric.Robolectric;
import org.robolectric.android.controller.ActivityController;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.odk.collect.android.support.CollectHelpers.buildThemedActivity;
import static org.odk.collect.android.support.CollectHelpers.createThemedActivity;

@RunWith(AndroidJUnit4.class)
public class DialogUtilsTest {
public class DialogFragmentUtilsTest {

@Test
public void showIfNotShowing_onlyEverOpensOneDialog() {
FragmentActivity activity = createThemedActivity(FragmentActivity.class);
FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class);
FragmentManager fragmentManager = activity.getSupportFragmentManager();

DialogUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
DialogFragmentUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
assertThat(fragmentManager.getFragments().size(), equalTo(1));
Fragment dialog1 = fragmentManager.getFragments().get(0);

DialogUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
DialogFragmentUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
assertThat(fragmentManager.getFragments().size(), equalTo(1));
assertThat(fragmentManager.getFragments().get(0), equalTo(dialog1));
}

@Test
public void showIfNotShowing_whenActivitySavedState_doesNotShowDialog() {
ActivityController<FragmentActivity> activityController = buildThemedActivity(FragmentActivity.class).setup();
ActivityController<FragmentActivity> activityController = Robolectric.buildActivity(FragmentActivity.class).setup();
activityController.pause().stop().saveInstanceState(new Bundle());

FragmentManager fragmentManager = activityController.get().getSupportFragmentManager();
DialogUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
DialogFragmentUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
assertThat(fragmentManager.getFragments().size(), equalTo(0));
}

@Test
public void showIfNotShowing_whenActivityDestroyed_doesNotShowDialog() {
ActivityController<FragmentActivity> activityController = buildThemedActivity(FragmentActivity.class).setup();
ActivityController<FragmentActivity> activityController = Robolectric.buildActivity(FragmentActivity.class).setup();
activityController.pause().stop().destroy();

FragmentManager fragmentManager = activityController.get().getSupportFragmentManager();
DialogUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
DialogFragmentUtils.showIfNotShowing(DialogFragment.class, fragmentManager);
assertThat(fragmentManager.getFragments().size(), equalTo(0));
}
}
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ buildscript {
classpath 'com.google.gms:google-services:4.3.5'
classpath 'org.jacoco:org.jacoco.core:0.8.7'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.1.0"
classpath "com.github.ben-manes:gradle-versions-plugin:0.39.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.junit.runner.RunWith;
import org.odk.collect.android.R;
import org.odk.collect.android.listeners.PermissionListener;
import org.odk.collect.android.permissions.PermissionsChecker;
import org.odk.collect.androidshared.system.PermissionsChecker;
import org.odk.collect.android.permissions.PermissionsProvider;
import org.odk.collect.android.storage.StorageSubdirectory;
import org.odk.collect.android.support.CollectTestRule;
Expand Down
12 changes: 9 additions & 3 deletions collect_app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,15 @@ the specific language governing permissions and limitations under the License.
<activity
android:name="org.odk.collect.geo.GeoPointActivity"
android:theme="@style/Theme.Collect"
tools:replace="android:theme"/>
<activity android:name=".activities.GeoPointMapActivity" />
<activity android:name=".activities.GeoPolyActivity" />
tools:replace="android:theme" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is it for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's need so that the build tools now which android:theme to use. Otherwise, there is a conflict between the geo and the collect_app manifests.

<activity
android:name="org.odk.collect.geo.GeoPointMapActivity"
android:theme="@style/Theme.Collect"
tools:replace="android:theme" />
<activity
android:name="org.odk.collect.geo.GeoPolyActivity"
android:theme="@style/Theme.Collect"
tools:replace="android:theme" />
<activity android:name=".activities.FormMapActivity" />
<activity android:name=".activities.BearingActivity" />
<activity
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import org.odk.collect.android.R;
import org.odk.collect.android.fragments.Camera2Fragment;
import org.odk.collect.androidshared.utils.ToastUtils;
import org.odk.collect.androidshared.ui.ToastUtils;

public class CaptureSelfieActivity extends CollectAbstractActivity {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import org.odk.collect.android.R;
import org.odk.collect.android.fragments.Camera2VideoFragment;
import org.odk.collect.androidshared.utils.ToastUtils;
import org.odk.collect.androidshared.ui.ToastUtils;

public class CaptureSelfieVideoActivity extends CollectAbstractActivity {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
import org.odk.collect.android.projects.CurrentProjectProvider;
import org.odk.collect.android.tasks.FormSyncTask;
import org.odk.collect.android.utilities.ApplicationConstants;
import org.odk.collect.android.utilities.DialogUtils;
import org.odk.collect.android.utilities.MultiClickGuard;
import org.odk.collect.android.views.ObviousProgressBar;
import org.odk.collect.androidshared.ui.DialogFragmentUtils;

import javax.inject.Inject;

Expand Down Expand Up @@ -99,9 +99,9 @@ public void onCreate(Bundle savedInstanceState) {

blankFormsListViewModel.isAuthenticationRequired().observe(this, authenticationRequired -> {
if (authenticationRequired) {
DialogUtils.showIfNotShowing(ServerAuthDialogFragment.class, getSupportFragmentManager());
DialogFragmentUtils.showIfNotShowing(ServerAuthDialogFragment.class, getSupportFragmentManager());
} else {
DialogUtils.dismissDialog(ServerAuthDialogFragment.class, getSupportFragmentManager());
DialogFragmentUtils.dismissDialog(ServerAuthDialogFragment.class, getSupportFragmentManager());
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import org.odk.collect.android.projects.CurrentProjectProvider
import org.odk.collect.android.projects.ManualProjectCreatorDialog
import org.odk.collect.android.projects.ProjectImporter
import org.odk.collect.android.projects.QrCodeProjectCreatorDialog
import org.odk.collect.android.utilities.DialogUtils
import org.odk.collect.android.utilities.ThemeUtils
import org.odk.collect.android.version.VersionInformation
import org.odk.collect.androidshared.ui.DialogFragmentUtils
import org.odk.collect.projects.Project
import javax.inject.Inject

Expand All @@ -38,11 +38,17 @@ class FirstLaunchActivity : CollectAbstractActivity() {
DaggerUtils.getComponent(this).inject(this)

binding.configureViaQrButton.setOnClickListener {
DialogUtils.showIfNotShowing(QrCodeProjectCreatorDialog::class.java, supportFragmentManager)
DialogFragmentUtils.showIfNotShowing(
QrCodeProjectCreatorDialog::class.java,
supportFragmentManager
)
}

binding.configureManuallyButton.setOnClickListener {
DialogUtils.showIfNotShowing(ManualProjectCreatorDialog::class.java, supportFragmentManager)
DialogFragmentUtils.showIfNotShowing(
ManualProjectCreatorDialog::class.java,
supportFragmentManager
)
}

binding.appName.text = String.format(
Expand Down
Loading