小编Sea*_*ici的帖子

test 和 androidTest 之间共享 srcDirs,升级到 Android Studio Chipmunk 后未解析的引用 (IntelliJ 2021.2.1)

我刚刚从 Bumblebee 升级到 Chipmunk,并且在我的检测 androidTests 中遇到了多个依赖项解析问题。

这些是我的源集的样子:

sourceSets {
    test.java.srcDirs += 'src/testShared/kotlin'
    test.resources.srcDirs += 'src/testShared/resources'
    androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    androidTest.java.srcDirs += 'src/testShared/kotlin'
    androidTest.resources.srcDirs += 'src/testShared/resources'
}
Run Code Online (Sandbox Code Playgroud)

这个想法是在单元测试和仪器测试之间共享测试数据。请记住,测试可以构建并执行,但依赖项在 IDE 中显示为红色。另外,它可能不相关,但我引用的字符串资源(位于资源模块中)在 IDE 中也是红色的。

另外,当我注释掉指向 testShared 的单元测试源集时,IDE 错误会在我的 AndroidTests 中消失

这在以前版本的 Android Studio 中不是问题。我认为该问题与基本 IntelliJ IDE 平台有关。有谁知道如何解决这个问题,或者有任何解决方法?

编辑:这是一个基本示例项目,在 Chipmunk 及以上版本中运行时演示了该问题。在bumblebee中,androidTest中没有未解决的引用错误。另外,您可能需要调整 AGP 版本,因为我使用 Dolphin beta01 构建了这个项目,但 Chipmunk 中的问题是相同的 https://drive.google.com/file/d/1ZCcEwuqM-m4E5qe94vCn52yWMON8rd5P/view?usp=分享

android intellij-idea shared-resource android-studio source-sets

41
推荐指数
2
解决办法
5049
查看次数

如何禁用 Jetpack Compose 列表/列/行中多个项目的同时点击(开箱即用的反跳?)

我在 Jetpack Compose 中实现了一列按钮。我们意识到可以一次单击多个项目(例如用多个手指),并且我们想禁用此功能。

是否有一种开箱即用的方法可以通过使用父列修饰符来禁用对子可组合项的多个同时单击?

这是我的 UI 当前状态的示例,请注意有两个选定的项目和两个未选定的项目。

在此输入图像描述

这是一些如何实现的代码(精简)

Column(
    modifier = modifier
            .fillMaxSize()
            .verticalScroll(nestedScrollParams.childScrollState),
    ) {
        viewDataList.forEachIndexed { index, viewData ->
            Row(modifier = modifier.fillMaxWidth()
                        .height(dimensionResource(id = 48.dp)
                        .background(colorResource(id = R.color.large_button_background))
                        .clickable { onClick(viewData) },
                              verticalAlignment = Alignment.CenterVertically
    ) {
        //Internal composables, etc
    }
}
Run Code Online (Sandbox Code Playgroud)

android multi-touch multi-select kotlin android-jetpack-compose

28
推荐指数
3
解决办法
2万
查看次数

Espresso swipeUp()、swipeDown() 等不再适用于 API 33+ (Android 13)

因此,我正在使用针对 API 33 (Android 13) 的应用程序运行仪器测试。我注意到一些测试由于浓缩咖啡滑动功能无法正常工作而失败。

onView(withId(android.R.id.content)).perform(swipeUp())
Run Code Online (Sandbox Code Playgroud)

测试不会在此调用中失败,但稍后会失败,因为我的测试取决于评估 UI 的操作。

作为参考,这是 Espresso swipeUp 函数中的代码:

public static ViewAction swipeUp() {
return actionWithAssertions(
    new GeneralSwipeAction(
        Swipe.FAST,
        GeneralLocation.translate(GeneralLocation.BOTTOM_CENTER, 0, -EDGE_FUZZ_FACTOR),
        GeneralLocation.TOP_CENTER,
        Press.FINGER));
Run Code Online (Sandbox Code Playgroud)

}

我正在使用浓缩咖啡 3.3.0。在 API 33 模拟器上进行测试之前一切正常。

有其他人遇到过这个问题吗?如果没有,有解决方法吗?

android integration-testing android-testing android-espresso

11
推荐指数
2
解决办法
1860
查看次数

使用 navGraphViewModels 访问子 NavHostFragment 的图形范围的 ViewModel

我正在使用 Android Jetpack (2.2.0-alpha01) 的导航组件。

我希望使用嵌套在我的主 NavHostFragment 中的子 NavHostFragment,它配备了自己的子导航图。请查看以下图片了解上下文:

在此处输入图片说明

子导航主机在位于 MainNavHost 堆栈前端的片段中定义如下:

<fragment
    android:id="@+id/childNavHostFragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="false"
    app:navGraph="@navigation/child_graph" />
Run Code Online (Sandbox Code Playgroud)

在 CHILD Nav Host Fragment 前面的片段中,我尝试使用以下代码将 ViewModel 范围限定为 R.navigation.child_graph:

private val childGraphScopedViewModel: ChildGraphScopedViewModel by navGraphViewModels(R.navigation.child_graph) {
    viewModelFactory
}
Run Code Online (Sandbox Code Playgroud)

访问 childGraphScopedViewModel 时,我收到错误消息崩溃:

java.lang.IllegalArgumentException: No NavGraph with ID 2131689472 is on the NavController's back stack.
Run Code Online (Sandbox Code Playgroud)

我相信懒惰的 init 调用by navGraphViewModel()是在 mainGraph 中寻找导航图。

如何访问子 navHostFragment 范围的 ViewModel?感谢您的时间。

android viewmodel kotlin android-architecture-navigation android-navigation-graph

10
推荐指数
2
解决办法
4716
查看次数

Robolectric 单元测试仅在运行多模块单元测试运行配置时使用旧资源而不是二进制资源

我有一个多模块 android 项目。我在每个模块中有一堆单元测试,我总是能够使用这样的运行配置一次运行它们:

在此处输入图片说明

我的许多测试使用一个与 RobolectricTestRunner 一起运行的基类。这个基类看起来像这样:

@RunWith(RobolectricTestRunner::class)
@Config(application = AndroidTest.ApplicationStub::class,
        manifest = Config.NONE,
        sdk = [21])
abstract class AndroidTest {
    @Suppress("LeakingThis")
    @Rule @JvmField val injectMocks = InjectMocksRule.create(this@AndroidTest)

    fun application(): Application = ApplicationProvider.getApplicationContext()

    internal class ApplicationStub : Application()
}
Run Code Online (Sandbox Code Playgroud)

**使用上述配置运行这些测试时,出现错误**

[Robolectric] NOTICE: legacy resources mode is deprecated; see http://robolectric.org/migrating/#migrating-to-40
Run Code Online (Sandbox Code Playgroud)

这使我的许多测试因 ResourceNotFoundException 而失败

但是,当我仅在特定模块中运行测试时,一切都会过去。这是因为 Robolectric 现在使用二进制资源:

[Robolectric] sdk=21; resources=BINARY
Run Code Online (Sandbox Code Playgroud)

我遵循了每个模块的 build.gradle 文件中的迁移说明,在每个 android 块中添加了以下内容:

testOptions {
    unitTests {
        includeAndroidResources = true
        returnDefaultValues = true
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现但无法修复的一条线索是,当我运行 ALL UNIT TEST 任务时:

WARNING: …
Run Code Online (Sandbox Code Playgroud)

unit-testing robolectric android-resources android-studio

7
推荐指数
1
解决办法
384
查看次数

麦克风前台服务几乎总是被某些操作系统杀死

我根本不明白为什么我的手机会杀死我的前台服务。

相关代码

在 AndroidManifest 中:

    <service
        android:name=".recorder.RecorderService"
        android:exported="false"
        android:process=":Recorder"
        android:foregroundServiceType="microphone">
    </service>
Run Code Online (Sandbox Code Playgroud)

在我的服务启动器中

     ContextCompat.startForegroundService(application, Intent(application, RecorderService::class.java))
Run Code Online (Sandbox Code Playgroud)

实际服务里面

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO)

    val notification = buildRecordingNotification()
    startServiceWithNotification(notification)

    recordingJob = recordSounds.executeCancellable(Unit, serviceScope)

    return START_STICKY
}

private fun buildRecordingNotification(): Notification {
    val channelId = buildNotificationChannelId()
    val builder = NotificationCompat.Builder(this, channelId)
    return builder
        .setSmallIcon(R.drawable.ic_stat_notify)
        .setContentTitle("Recording...")
        .setWhen(0)
        .setChannelId(channelId)
        .build()
}

private fun buildNotificationChannelId() =
    NotificationChannelHelper.createChannel(this, NotificationChannelHelper.NOTIF_ID_RECORDER, NotificationManagerCompat.IMPORTANCE_LOW)

private fun startServiceWithNotification(notification: Notification) =
    try {
        startForeground(NOTIFICATION_ID, notification)
    } catch (e: …
Run Code Online (Sandbox Code Playgroud)

android microphone foreground-service

7
推荐指数
0
解决办法
601
查看次数

在主线程运行时对Cloud Firestore进行同步调用

我正在基于Android Clean Architecture Kotlin版本(https://github.com/android10/Android-CleanArchitecture-Kotlin)构建应用程序。

使用此架构,每次您要调用用例时,都会启动Kotlin协程并将结果发布在主线程中。这是通过以下代码实现的:

abstract class UseCase<out Type, in Params> where Type : Any {

abstract suspend fun run(params: Params): Either<Failure, Type>

fun execute(onResult: (Either<Failure, Type>) -> Unit, params: Params) {
    val job = async(CommonPool) { run(params) }
    launch(UI) { onResult.invoke(job.await()) }
}
Run Code Online (Sandbox Code Playgroud)

在他的示例架构中,Android10先生使用Retrofit在kotlin couroutine内部进行同步api调用。例如:

override fun movies(): Either<Failure, List<Movie>> {
            return when (networkHandler.isConnected) {
                true -> request(service.movies(), { it.map { it.toMovie() } }, emptyList())
                false, null -> Left(NetworkConnection())
            }
        }

private fun <T, R> request(call: Call<T>, …
Run Code Online (Sandbox Code Playgroud)

android coroutine kotlin firebase google-cloud-firestore

6
推荐指数
1
解决办法
1691
查看次数

Local CoroutineScope().launch { },创建的协程作用域在内存中存活多久?

我无法理解内存管理如何在 Android 上与本地创建的协程一起工作。这是一些代码:

 init {
    CoroutineScope(Dispatchers.Default).launch {
        val result = workerA.runSuspended(paramA)
        liveDataA.postValue(result)
    }
}
Run Code Online (Sandbox Code Playgroud)

对于短暂的挂起函数调用,我想启动一次协程,然后我不再需要作用域。我知道这样写时不能取消范围。但我的主要问题是:

  1. 工作完成后会发生什么?coroutineScope 是否被垃圾回收?
  2. 范围是否保证在作业完成之前保持活动状态?
  3. 如果 runSuspished 一直卡住会发生什么?如果父对象被垃圾回收,会不会出现内存泄漏?

android kotlin kotlin-coroutines coroutinescope

6
推荐指数
0
解决办法
455
查看次数

ConstraintLayout 链上下文菜单在 Android Studio 中不再可见

使用 Android Studio 3.4 Canary 9 和 10 ConstraintLayout 2.0.0.alpha3

我在 Android Studio 3.4 canary 9 的最新版本中遇到了约束布局问题。基本上,当您单击约束布局中的视图时,例如在链元素上,您应该能够看到小图标出现,允许您对视图执行某些操作。

带有上下文菜单按钮的约束布局

如您所见,每个视图下方都有 3 个按钮,可让您更改链设置。但是,当单击链中的元素时,这是我在 3.4.C09 上的布局编辑器中得到的结果:

3.4.C09 中缺少上下文菜单

他们有没有残疾或搬到别处?这是一个错误吗?我在 IDE 中到处寻找,但没有任何运气,尝试放大/缩小,更改主题,使缓存/重启无效,干净重建等。

感谢您提供的任何帮助!

android menu android-studio android-constraintlayout

5
推荐指数
1
解决办法
817
查看次数

从短数组中提取分贝,该数组源自 Android AudioRecord 的字节数组

我想获得一段时间内(比方说 1 秒)的平均分贝数。编辑:这是为了检测大声的噪音。

我有一个 ByteArray 音频,采样率为 16khz,深度为 16 位。

我将其转换为 ShortArray 以获取随时间变化的幅度,如下所示:

fun bytesToShort(byteArray: ByteArray): ShortArray {
    val shortOut = ShortArray(byteArray.size / 2)
    val byteBuffer: ByteBuffer = ByteBuffer.wrap(byteArray)
    byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shortOut)
    return shortOut
}
Run Code Online (Sandbox Code Playgroud)

据我所知,这是获取幅度的正确方法。

现在我的转换算法:

val amplitudeValues = bytesToShort(bytesForDecibels)
val rms = sqrt(amplitudeValues.sumOf { it * it } / amplitudeValues.size.toDouble())
val decibels = 20 * log10(rms)
Run Code Online (Sandbox Code Playgroud)

它会输出明显的分贝值。然而,我尝试录制一段我对着麦克风尖叫的录音,但平均声音无法达到 51 分贝以上。我的算法是否正确,麦克风根本无法拾取比 51db 更大的声音,或者算法是否不完整/不正确?

编辑:我没有提到我想检测大声的噪音。从 @GabeSechan 的评论中读到,我需要检查基线幅度上的幅度尖峰以检测大声的噪音。因此,我将根据麦克风活动设置基线,任何超过基线的大尖峰都是很大的噪音。

audio android decibel audiorecord

5
推荐指数
0
解决办法
317
查看次数