为 AppBarLayout 设置 elevation/StateListAnimator 时 Android JNI 崩溃

标签 android java-native-interface android-support-library android-appbarlayout android-elevation

我正在尝试将 AppBarLayout 的高度设置为 0(然后返回到默认值)。它在 API 21(>= 22 等工作正常)上有时(不总是)和崩溃。

我正在使用 StateListAnimator,如下面的链接所述(因为这是自 support-lib 24.0.0 以来设置高度的“官方”方式):

https://stackoverflow.com/a/37992366/2170109


我的实际方法是这样的:

public void setAppBarElevation(final boolean visible) {
  if (appBar != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    appBar.setStateListAnimator(AnimatorInflater.loadStateListAnimator(this, (visible) ? R.animator.appbar_elevated : R.animator.appbar_not_elevated));
  }
}

连同两个 XML 文件(另一个是设置 android:valueTo="0"):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <objectAnimator android:propertyName="elevation"
                    android:valueTo="@dimen/default_appbar_elevation"
                    android:valueType="floatType"/>
  </item>
</selector>

我已经测试了一些具有不同 Android 版本(API 19、21、23、24、25)的设备,它只在 21 时崩溃。

日志显示设置高度时出现一些 JNI 错误(我认为来自 StateListAnimator):

   --------- beginning of system
JNI DETECTED ERROR IN APPLICATION: cant call void android.view.View.setElevation(float) on null object
    in call to CallVoidMethodV
    from void android.animation.PropertyValuesHolder.nCallFloatMethod(java.lang.Object, long, float)
"main" prio=5 tid=1 Runnable
  | group="main" sCount=0 dsCount=0 obj=0x72fc2000 self=0xf421c500
  | sysTid=20172 nice=0 cgrp=apps sched=0/0 handle=0xf77de160
  | state=R schedstat=( 3803514732 320072004 1563 ) utm=340 stm=40 core=0 HZ=100
  | stack=0xff6fb000-0xff6fd000 stackSize=8MB
  | held mutexes= "mutator lock"(shared held)
  native: #00 pc 00005b13  /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+83)
  native: #01 pc 00002e92  /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+34)
  native: #02 pc 003c8f68  /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+136)
  native: #03 pc 00391f8d  /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+285)
  native: #04 pc 001006b0  /system/lib/libart.so (art::JniAbort(char const*, char const*)+1024)
  native: #05 pc 0010125f  /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+111)
  native: #06 pc 001016b2  /system/lib/libart.so (art::ScopedCheck::CheckVirtualMethod(_jobject*, _jmethodID*)+514)
  native: #07 pc 00112340  /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, char*)+144)
  native: #08 pc 000776ca  /system/lib/libandroid_runtime.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+42)
  native: #09 pc 00123ecb  /system/lib/libandroid_runtime.so (???)
  native: #10 pc 00089596  /data/dalvik-cache/x86/system@framework@boot.oat (Java_android_animation_PropertyValuesHolder_nCallFloatMethod__Ljava_lang_Object_2JF+174)
  at android.animation.PropertyValuesHolder.nCallFloatMethod(Native method)
  at android.animation.PropertyValuesHolder.access$400(PropertyValuesHolder.java:38)
  at android.animation.PropertyValuesHolder$FloatPropertyValuesHolder.setAnimatedValue(PropertyValuesHolder.java:1296)
  at android.animation.ObjectAnimator.animateValue(ObjectAnimator.java:952)
  at android.animation.ValueAnimator.animationFrame(ValueAnimator.java:1207)
  at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1248)
  at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:659)
  at android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:682)
  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
  at android.view.Choreographer.doCallbacks(Choreographer.java:580)
  at android.view.Choreographer.doFrame(Choreographer.java:549)
  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
  at android.os.Handler.handleCallback(Handler.java:739)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:135)
  at android.app.ActivityThread.main(ActivityThread.java:5219)
  at java.lang.reflect.Method.invoke!(Native method)
  at java.lang.reflect.Method.invoke(Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

有什么方法可以使用当前的支持库隐藏 AppBar 的影子(并重新启用它)(我现在使用的是 25.0.0,但它会在 24.0 时崩溃。 x.x,也是)?

最佳答案

你可以试试android:stateListAnimator="@null"来隐藏

关于为 AppBarLayout 设置 elevation/StateListAnimator 时 Android JNI 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40404009/

相关文章:

java - 禁用单击 SwipeRefreshLayout 内的 RecyclerView

android - 有没有办法在 webview 应用程序的软键盘中显示表情符号按钮?

kotlin - 如何从 Kotlin 调用静态 JNI 函数?

android - getChildFragmentManager 在 4.0.3 设备上引发 NoSuchMethod 异常,但在 4.2.2 上没有

java.lang.NoClassDefFoundError : android. support.v4.preferencefragment.R$layout

java - 使用 JNI 代替 JNA 调用原生代码?

android - Android listview打开手势的实现方法

android - Android XWalkView 或 WebView 中隐藏在键盘下方的文本框

android - 何时使用 MutableLiveData 和 LiveData

java - FileSystem.list 的 JVM 实现