有没有办法只为Android 4.0.3禁用硬件加速?

Ald*_*yes 16 android android-4.0-ice-cream-sandwich

我最近偶然发现了android 4.0.3的问题,我在应用程序启动后立即得到以下异常(在其他Android版本上它工作正常):

java.lang.NullPointerException
at android.view.GLES20RecordingCanvas.drawPatch(GLES20RecordingCanvas.java:97)
at android.graphics.NinePatch.draw(NinePatch.java:125)
at android.graphics.drawable.NinePatchDrawable.draw(NinePatchDrawable.java:189)
at android.widget.ImageView.onDraw(ImageView.java:892)
at android.view.View.draw(View.java:10978)
at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.getDisplayList(View.java:10415)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597)
at android.view.View.getDisplayList(View.java:10380)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597)
at android.view.View.getDisplayList(View.java:10380)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597)
at android.view.View.getDisplayList(View.java:10380)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597)
at android.view.View.getDisplayList(View.java:10380)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:842)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:1910)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

这与启用硬件加速相关,只要我在清单上禁用它,应用程序就会开始正常工作.

通过搜索我在Romain Guy的一些对话中找到了一个日志(在doc中搜索"drawPatch"),在那里他讨论了一些可能导致这种情况的原因,虽然没有提出解决方法或修复,我想知道是否我应该只为这个版本的Android禁用硬件加速,或者是否有解决方法?

谢谢你的时间.

Joã*_*ete 24

您目前无法通过代码在窗口级别禁用硬件加速.

仅启用它.我建议您在清单中默认禁用它:

<application android:hardwareAccelerated="false">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>
Run Code Online (Sandbox Code Playgroud)

然后将其启用到所有其他版本:

if (Build.VERSION.SDK_INT != Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
            getWindow().setFlags(
                    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        }
Run Code Online (Sandbox Code Playgroud)

您可以使用以下代码在运行时禁用单个视图的硬件加速:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Run Code Online (Sandbox Code Playgroud)

此信息可在Android中使用 - 控制硬件加速


Phi*_*o99 16

我喜欢@sgarman链接的答案,因为它对代码的影响很小,并且易于维护.只是为了扩展这个链接,这就是我为Android v4.0.3禁用硬件加速所做的工作,仅针对某个活动而且它对我有用(记得在各种bool.xml文件中添加指定版本和编码的xml头文件) ,因为维基编辑不会让我粘贴它):

AndroidManifest.xml:识别托管违规视图的活动,并将其插入该活动:

<activity
    android:hardwareAccelerated="@bool/isNotIceCreamSandwich"
    ...
</activity>
Run Code Online (Sandbox Code Playgroud)

文件路径:res/values/bool.xml:

<resources>
    <bool name="isNotIceCreamSandwich">true</bool>
</resources>
Run Code Online (Sandbox Code Playgroud)

文件路径:res/values-v14/bool.xml:

<resources>
    <bool name="isNotIceCreamSandwich">false</bool>
</resources>
Run Code Online (Sandbox Code Playgroud)

文件路径:res/values-v16/bool.xml:

<resources>
    <bool name="isNotIceCreamSandwich">true</bool>
</resources>
Run Code Online (Sandbox Code Playgroud)


sga*_*man 8

因此AC在他的评论中提到了这一点,但让我详细说明.

您可以在值文件中创建一个布尔值并将其粘贴到正确的版本文件夹中.在你的清单下

看看这篇文章:https://plus.google.com/+AndroidDevelopers/posts/DcsFABkyuYM.

看起来你想要定位值-v15/bools.xml

http://developer.android.com/reference/android/os/Build.VERSION_CODES.html#ICE_CREAM_SANDWICH_MR1


Aar*_*ord 5

这是一个有趣的错误导致硬件加速工作(有时).在过去的几天里,我一直在寻找答案.它已在ICS中记录,但我在其中一款测试手机中发现了三星Galaxy S3运行4.1.2大多数人建议关闭硬件加速.我不想这样做因为硬件加速使我的动画如此柔滑.因此,我发现,如果我重写画()尝试捕捉空指针异常的硬件加速功能的工作(大部分时间),并足以让你永远也不会注意到它们不工作或抛出异常.在我的情况下,我正在做一个自定义视图,并有一些自定义绘图.对null的简单检查不起作用(canvas == null),这就是为什么这个bug很痛苦.所以我做的是这样的:

    @Override
public void draw(Canvas canvas) {
    try{
        super.draw(canvas);
        mCanvas=canvas;
    }catch(java.lang.NullPointerException e){
        Log.e("mytag","MyCustomView::draw():"+e);
    }
    if(mCanvas==null)
        return;     
...
Run Code Online (Sandbox Code Playgroud)

然后默默尝试并在个人绘制声明中捕获任何NPE.我第一次看到这个bug时,我在try和catch中包围了整个draw()代码.这适用于大多数手机,但在运行4.1.2的三星s3上却引起了闪烁.所以我使用了上面的方法,并在每次调用someObject.draw(mCanvas)时做了静音尝试catch,这解决了问题,完全消除了所有闪烁(硬件加速视图缓存和新画布之间的差异).希望这可以帮助!比关闭HWA更好!