Skip to content

Commit

Permalink
Merge pull request #13 from tiritea/master
Browse files Browse the repository at this point in the history
Update to ODK Collect v2024.2.4 release
  • Loading branch information
tiritea authored Oct 24, 2024
2 parents 5d12063 + c668aeb commit bce76e7
Show file tree
Hide file tree
Showing 862 changed files with 21,592 additions and 9,128 deletions.
15 changes: 8 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ references:
android_config: &android_config
working_directory: ~/work
docker:
- image: cimg/android:2023.10.1
- image: cimg/android:2024.01
resource_class: medium+

jobs:
Expand All @@ -17,7 +17,7 @@ jobs:
- checkout
- run:
name: Generate combined build.gradle file for cache key
command: cat build.gradle */build.gradle .circleci/gradle.properties .circleci/config.yml buildSrc/src/main/java/dependencies/Dependencies.kt buildSrc/src/main/java/dependencies/Versions.kt > deps.txt
command: cat build.gradle */build.gradle */build.gradle.kts .circleci/gradle.properties .circleci/config.yml buildSrc/src/main/java/dependencies/Dependencies.kt buildSrc/src/main/java/dependencies/Versions.kt > deps.txt
- restore_cache:
keys:
- compile-deps-{{ checksum "deps.txt" }}
Expand Down Expand Up @@ -230,8 +230,8 @@ jobs:
command: ./gradlew assembleSelfSignedRelease

- run:
name: Check APK size isn't larger than 10.6MB
command: if [ $(ls -l collect_app/build/outputs/apk/selfSignedRelease/*.apk | awk '{print $5}') -gt 10600000 ]; then exit 1; fi
name: Check APK size isn't larger than 11.5MB
command: ./check-size.sh

- run:
name: Copy APK to predictable path for artifact storage
Expand Down Expand Up @@ -282,7 +282,7 @@ jobs:
--type instrumentation \
--app collect_app/build/outputs/apk/debug/*.apk \
--test collect_app/build/outputs/apk/androidTest/debug/*.apk \
--device model=MediumPhone.arm,version=30,locale=en,orientation=portrait \
--device model=MediumPhone.arm,version=34,locale=en,orientation=portrait \
--results-bucket opendatakit-collect-test-results \
--directories-to-pull /sdcard --timeout 20m \
--test-targets "package org.odk.collect.android.feature.smoke"
Expand Down Expand Up @@ -333,9 +333,10 @@ jobs:
--num-uniform-shards=25 \
--app collect_app/build/outputs/apk/debug/*.apk \
--test collect_app/build/outputs/apk/androidTest/debug/*.apk \
--device model=MediumPhone.arm,version=30,locale=en,orientation=portrait \
--device model=MediumPhone.arm,version=34,locale=en,orientation=portrait \
--results-bucket opendatakit-collect-test-results \
--directories-to-pull /sdcard --timeout 20m
--directories-to-pull /sdcard --timeout 20m \
--test-targets "notPackage org.odk.collect.android.regression"
fi
no_output_timeout: 25m

Expand Down
8 changes: 5 additions & 3 deletions .circleci/test_modules.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
shared
formstest
forms-test
androidshared
async
strings
audioclips
audiorecorder
audio-clips
audio-recorder
projects
location
geo
Expand All @@ -21,3 +21,5 @@ metadata
selfie-camera
draw
printer
lists
web-page
23 changes: 23 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
root = true

[*.{kt,kts}]
ktlint_standard_no-blank-lines-in-chained-method-calls = disabled
ktlint_standard_trailing-comma-on-call-site = disabled
ktlint_standard_trailing-comma-on-declaration-site = disabled
ktlint_standard_function-signature = disabled
ktlint_standard_no-empty-first-line-in-class-body = disabled
ktlint_standard_argument-list-wrapping = disabled
ktlint_standard_parameter-list-wrapping = disabled
ktlint_standard_multiline-expression-wrapping = disabled
ktlint_standard_max-line-length = disabled
ktlint_standard_string-template-indent = disabled
ktlint_standard_annotation = disabled
ktlint_standard_value-parameter-comment = disabled
ktlint_standard_property-naming = disabled
ktlint_standard_value-argument-comment = disabled
ktlint_standard_blank-line-before-declaration = disabled
ktlint_standard_no-consecutive-comments = disabled
ktlint_standard_enum-wrapping = disabled
ktlint_standard_statement-wrapping = disabled
ktlint_standard_try-catch-finally-spacing = disabled
ktlint_standard_wrapping = disabled
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ https://github.com/getodk/collect/blob/master/docs/CONTRIBUTING.md
- [ ] added or modified tests for any new or changed behavior
- [ ] run `./gradlew connectedAndroidTest` (or `./gradlew testLab`) and confirmed all checks still pass
- [ ] added a comment above any new strings describing it for translators
- [ ] added any new strings with date formatting to `DateFormatsTest`
- [ ] verified that any code or assets from external sources are properly credited in comments and/or in the [about file](https://github.com/getodk/collect/blob/master/collect_app/src/main/assets/open_source_licenses.html).
- [ ] verified that any new UI elements use theme colors. [UI Components Style guidelines](https://github.com/getodk/collect/blob/master/docs/CODE-GUIDELINES.md#ui-components-style-guidelines)
4 changes: 1 addition & 3 deletions analytics/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,5 @@ dependencies {
implementation(Dependencies.kotlin_stdlib)
implementation(Dependencies.androidx_core_ktx)
implementation(Dependencies.firebase_crashlytics)
implementation(Dependencies.firebase_analytics) {
exclude(group = "com.google.guava")
}
implementation(Dependencies.firebase_analytics)
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ interface Analytics {
fun setParam(key: String, value: String) {
params[key] = value
}

fun setUserProperty(name: String, value: String) {
instance.setUserProperty(name, value)
}
}
}
1 change: 1 addition & 0 deletions androidshared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ dependencies {
implementation(Dependencies.play_services_location)

testImplementation(project(":test-shared"))
testImplementation(project(":androidtest"))
testImplementation(Dependencies.junit)
testImplementation(Dependencies.androidx_test_ext_junit)
testImplementation(Dependencies.androidx_test_espresso_core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ class ImageCompressorTest {
ExifInterface.TAG_GPS_SATELLITES to "8",
ExifInterface.TAG_GPS_STATUS to "A",
ExifInterface.TAG_ORIENTATION to "1",

// unsupported exif tags
ExifInterface.TAG_THUMBNAIL_IMAGE_LENGTH to "5",
ExifInterface.TAG_DNG_VERSION to "100"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.odk.collect.androidshared.async
import org.odk.collect.androidshared.livedata.MutableNonNullLiveData
import org.odk.collect.androidshared.livedata.NonNullLiveData
import org.odk.collect.async.Scheduler
import java.util.concurrent.atomic.AtomicInteger
import java.util.function.Consumer
import java.util.function.Supplier

Expand All @@ -11,10 +12,15 @@ class TrackableWorker(private val scheduler: Scheduler) {
private val _isWorking = MutableNonNullLiveData(false)
val isWorking: NonNullLiveData<Boolean> = _isWorking

private var activeBackgroundJobsCounter = AtomicInteger(0)

fun <T> immediate(background: Supplier<T>, foreground: Consumer<T>) {
activeBackgroundJobsCounter.incrementAndGet()
_isWorking.value = true
scheduler.immediate(background) { result ->
_isWorking.value = false
if (activeBackgroundJobsCounter.decrementAndGet() == 0) {
_isWorking.value = false
}
foreground.accept(result)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ object ImageFileUtils {
}
if (sourceFileExif == null ||
!EXIF_ORIENTATION_ROTATIONS.contains(
sourceFileExif
.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
)
)
sourceFileExif
.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
)
)
) {
// Source Image doesn't have any EXIF Rotations, so a normal file copy will suffice
sourceFile.copyTo(destFile, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow

/**
* [AppState] can be used as a shared store of state that lives at an "app"/"in-memory" level
Expand Down Expand Up @@ -50,6 +52,10 @@ class AppState {
return get(key, MutableLiveData(default))
}

fun <T> getFlow(key: String, default: T): Flow<T> {
return get(key, MutableStateFlow(default))
}

fun set(key: String, value: Any?) {
map[key] = value
}
Expand All @@ -58,6 +64,16 @@ class AppState {
get(key, MutableLiveData<T>()).postValue(value)
}

fun <T> setFlow(key: String, value: T) {
get<MutableStateFlow<T>>(key).let {
if (it != null) {
it.value = value
} else {
map[key] = MutableStateFlow(value)
}
}
}

fun clear() {
map.clear()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.odk.collect.androidshared.data

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData

/**
* Useful for values that are read multiple times but only used
* once (like an error that shows a dialog once).
Expand All @@ -16,3 +19,12 @@ data class Consumable<T>(val value: T) {
consumed = true
}
}

fun <T> LiveData<Consumable<T>>.consume(lifecycleOwner: LifecycleOwner, consumer: (T) -> Unit) {
observe(lifecycleOwner) { consumable ->
if (!consumable.isConsumed()) {
consumable.consume()
consumer(consumable.value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.function.Consumer;
import java.util.function.Function;

import kotlin.Pair;
import kotlin.Triple;

public class LiveDataUtils {
Expand Down Expand Up @@ -54,6 +55,13 @@ public static <T> LiveData<T> liveDataOf(T value) {
return new MutableLiveData<>(value);
}

public static <T, U> LiveData<Pair<T, U>> zip(LiveData<T> one, LiveData<U> two) {
return new ZippedLiveData<>(
new LiveData[]{one, two},
values -> new Pair<>((T) values[0], (U) values[1])
);
}

public static <T, U, V> LiveData<Triple<T, U, V>> zip3(LiveData<T> one, LiveData<U> two, LiveData<V> three) {
return new ZippedLiveData<>(
new LiveData[]{one, two, three},
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.odk.collect.androidshared.system

import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import android.webkit.MimeTypeMap
import androidx.core.net.toFile
import java.io.File
import java.io.FileOutputStream

fun Uri.copyToFile(context: Context, dest: File) {
try {
context.contentResolver.openInputStream(this)?.use { inputStream ->
FileOutputStream(dest).use { outputStream ->
inputStream.copyTo(outputStream)
}
}
} catch (e: Exception) {
// ignore
}
}

fun Uri.getFileExtension(context: Context): String? {
var extension = getFileName(context)?.substringAfterLast(".", "")

if (extension.isNullOrEmpty()) {
val mimeType = context.contentResolver.getType(this)

extension = if (scheme == ContentResolver.SCHEME_CONTENT) {
MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
} else {
MimeTypeMap.getFileExtensionFromUrl(toString())
}

if (extension.isNullOrEmpty()) {
extension = mimeType?.substringAfterLast("/", "")
}
}

return if (extension.isNullOrEmpty()) {
null
} else {
".$extension"
}
}

fun Uri.getFileName(context: Context): String? {
var fileName: String? = null

try {
when (scheme) {
ContentResolver.SCHEME_FILE -> fileName = toFile().name
ContentResolver.SCHEME_CONTENT -> {
val cursor = context.contentResolver.query(this, null, null, null, null)
cursor?.use {
if (it.moveToFirst()) {
val fileNameColumnIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (fileNameColumnIndex != -1) {
fileName = it.getString(fileNameColumnIndex)
}
}
}
}
ContentResolver.SCHEME_ANDROID_RESOURCE -> {
// for uris like [android.resource://com.example.app/1234567890]
val resourceId = lastPathSegment?.toIntOrNull()
if (resourceId != null) {
fileName = context.resources.getResourceName(resourceId)
} else {
// for uris like [android.resource://com.example.app/raw/sample]
val packageName = authority
if (pathSegments.size >= 2) {
val resourceType = pathSegments[0]
val resourceEntryName = pathSegments[1]
val resId = context.resources.getIdentifier(resourceEntryName, resourceType, packageName)
if (resId != 0) {
fileName = context.resources.getResourceName(resId)
}
}
}
}
}

if (fileName == null) {
fileName = path?.substringAfterLast("/")
}
} catch (e: Exception) {
// ignore
}

return fileName
}
Loading

0 comments on commit bce76e7

Please sign in to comment.