可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have recently stumbled upon an issue with android 4.0.3, where Im getting the following Exception as soon as the application starts (on other android versions it works fine):
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)
This is related to having hardware acceleration enabled, as soon as I disable it on the manifest the application starts working just fine.
By doing a search I found a log (inside that doc search for "drawPatch") on some conversation of Romain Guy, where he discuss a little bit of what could be causing this, although there is no workaround or fix proposed, I wonder if I should disable hardware acceleration only for this version of android, or if there is a workaround for it?
Thanks for your time.
回答1:
So A-C mentions this in his comment but let me elaborate.
You can create a boolean in a values file and stick it in the correct version folder. In your manifest under
Check out this post: https://plus.google.com/+AndroidDevelopers/posts/DcsFABkyuYM.
Looks like your going to want to target values-v15/bools.xml
http://developer.android.com/reference/android/os/Build.VERSION_CODES.html#ICE_CREAM_SANDWICH_MR1
回答2:
You currently cannot disable hardware acceleration at the window level by code.
Only enable it. I suggest you to Disable it by default in your manifest:
<application android:hardwareAccelerated="false">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
and then enable it to all the other versions:
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
You can disable hardware acceleration for an individual view at runtime with the following code:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
This info is available in Android - Controlling Hardware Acceleration
回答3:
I like the answer linked by @sgarman because it has minimal impact on the code and is easily maintainable. Just to expand on that link, here's what I did to disable hardware acceleration only for Android v4.0.3 and only for a certain activity and it worked for me (remember to add the xml headers specifying version and encoding to the various bool.xml files, as the wiki editor would not let me paste it in):
AndroidManifest.xml: identify the activity hosting the offending view, and insert this to that activity:
<activity
android:hardwareAccelerated="@bool/isNotIceCreamSandwich"
...
</activity>
file path: res/values/bool.xml:
<resources>
<bool name="isNotIceCreamSandwich">true</bool>
</resources>
file path: res/values-v14/bool.xml:
<resources>
<bool name="isNotIceCreamSandwich">false</bool>
</resources>
file path: res/values-v16/bool.xml:
<resources>
<bool name="isNotIceCreamSandwich">true</bool>
</resources>
回答4:
This is a funny bug cause hardware acceleration is working (sometimes). I've been searching for the answer to this for the last couple days. It’s documented in ICS but I have noticed it in one of my test phones a Samsung Galaxy S3 running 4.1.2 Most people suggest turning off hardware acceleration. I didn't want to do that cause hardware acceleration makes my animations so silky smooth. So what I found was if I override draw() try and catch the null pointer exception the hardware accelerated features work (most of the time) and enough for you to never notice they aren't working or throwing the exception.
In my case I was doing a custom view and had some custom drawing to do. The simple check for null doesn’t work (canvas==null) which is why this bug is a pain. So what I did was this:
@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;
...
then silently try and caught any NPE on individual draw statements. First time I saw this bug I surrounded the entire draw() code in a try and catch. That worked for most phones but on the samsung s3 running 4.1.2 it was causing a flickering. So I used the above method and did silent try catch's on each call to someObject.draw(mCanvas) and that solved the problem entirely removing all flickering (disparity between hardware accelerated view cache and new canvas). Hope this helps! Way better than turning HWA off!