Skip to content

Instantly share code, notes, and snippets.

View realdadfish's full-sized avatar

Thomas Keller realdadfish

View GitHub Profile
@realdadfish
realdadfish / build.gradle.kts
Last active February 27, 2023 07:22
Unmatched attributes issue and solution
val configuration = project.configurations.getByName("prodConsumerReleaseRuntimeClasspath")
val artifactType = Attribute.of("artifactType", String::class.java)
// Some plugin can only work with configurations, while the Android Gradle Plugin (AGP) has the newer "artifact view"
// paradigm implemented. This makes it impossible to resolve most of the created, variant-aware
// configurations from AGP "by hand" without getting unmatched attribute exceptions.
// We now pick one artifact that holds our dependencies and add a custom compatibility rule
// for it which basically accepts all incoming compatibility issues as long as the produced value
// on "the other side" is a JAR or AAR artifact.
configuration.attributes {
attribute(artifactType, "android-classes-directory")
@realdadfish
realdadfish / ScopeCancel.kt
Created February 7, 2023 11:53
Why does my shared flow subscription not complete after the scope it's shared in is canceled?
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.shareIn
@realdadfish
realdadfish / AndroidManifest.xml
Last active September 14, 2022 08:25
Enable / disable buttons in list
...
<application>
<activity
android:name="androidx.activity.ComponentActivity"
android:exported="false"/>
</application>
...
class HiltFragmentScenario<F : Fragment> private constructor(
private val fragmentClass: Class<F>,
val activityScenario: ActivityScenario<TestHiltActivity>
) {
@Suppress("UNCHECKED_CAST")
val fragment: F?
get() = activityScenario.getActivity()?.supportFragmentManager?.findFragmentByTag(FRAGMENT_TAG) as? F?
/**
* Moves Fragment state to a new state.
@realdadfish
realdadfish / ProgressIterator.kt
Created November 11, 2021 11:58
A trial to mimic "Type-driven design in Rust" (https://www.youtube.com/watch?v=bnnacleqg6k) with Kotlin
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
interface ExactSizeIterator<T> : Iterator<T> {
val length: UInt
}
fun <T> Collection<T>.exactSizeIterator() = object : ExactSizeIterator<T> {
private val inner = iterator()
override val length: UInt = size.toUInt()
override fun hasNext(): Boolean = inner.hasNext()
@realdadfish
realdadfish / ViewMatchers.java
Created October 29, 2014 07:44
Workaround for Espresso / Android Test Kit to "support" RecyclerView matching.
public class ViewMatchers
{
@SuppressWarnings("unchecked")
public static Matcher<View> withRecyclerView(@IdRes int viewId)
{
return allOf(isAssignableFrom(RecyclerView.class), withId(viewId));
}
@SuppressWarnings("unchecked")
public static ViewInteraction onRecyclerItemView(@IdRes int identifyingView, Matcher<View> identifyingMatcher, Matcher<View> childMatcher)
@realdadfish
realdadfish / MyDependencyResolver.kt
Last active February 5, 2021 21:55
Custom Dependency Resolver for Robolectric 4.2+
import com.google.auto.service.AutoService
import org.robolectric.internal.dependency.DependencyResolver
import org.robolectric.pluginapi.SdkProvider
import org.apache.maven.artifact.ant.DependenciesTask
import org.robolectric.internal.dependency.DependencyJar
import java.io.IOException
import java.nio.channels.FileLock
import java.nio.channels.FileChannel
import java.io.RandomAccessFile
import java.io.File
@realdadfish
realdadfish / LicenseReportPlugin.kt
Created January 28, 2021 15:35
Leveraging Gradle's ArtifactView
package some.package
import nl.javadude.gradle.plugins.license.DownloadLicensesExtension
import nl.javadude.gradle.plugins.license.DownloadLicensesReportExtension
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeCompatibilityRule
@realdadfish
realdadfish / Log.txt
Created March 5, 2019 09:18
AndroidX Orchestrator Failure
CoverageListener E Failed to generate Emma/JaCoCo coverage.
E java.lang.reflect.InvocationTargetException
E at java.lang.reflect.Method.invoke(Native Method)
E at androidx.test.internal.runner.listener.CoverageListener.generateCoverageReport(CoverageListener.java:101)
E at androidx.test.internal.runner.listener.CoverageListener.instrumentationRunFinished(CoverageListener.java:70)
E at androidx.test.internal.runner.TestExecutor.reportRunEnded(TestExecutor.java:92)
E at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:65)
E at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
E at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
E Caused by: java.io.FileNotFoundExcept
@realdadfish
realdadfish / gradle-4.7-with-remote-buildcache.log
Last active November 4, 2020 15:51
Slow buildSrc compilation Gradle 4.7 vs 4.8-milestone-1
[15:46:41] Welcome to Gradle 6.7!
[15:46:41]
[15:46:41] Here are the highlights of this release:
[15:46:41] - File system watching is ready for production use
[15:46:41] - Declare the version of Java your build requires
[15:46:41] - Java 15 support
[15:46:41]
[15:46:41] For more details see https://docs.gradle.org/6.7/release-notes.html
[15:46:41]
[15:46:41] To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/6.7/userguide/gradle_daemon.html.