使用带闪光灯的 web 视图时屏幕闪烁

Posted

技术标签:

【中文标题】使用带闪光灯的 web 视图时屏幕闪烁【英文标题】:Screen blinking when using a webview with flash 【发布时间】:2011-07-03 00:44:51 【问题描述】:

编辑:我做了一个演示apk,所以你可以理解我的意思:http://cl.ly/3g0s1p030j243y0p3m2F

对于我的应用程序,我想要在 android 平板电脑上使用所有 Android 优点、手势等进行某种“超级 Power Point”或主题演讲(商业团队将向他们的客户展示产品)。由于 Honeycomb 还没有准备好,而且我们在 3 月之前需要它,所以我们随机选择了一些 Froyo 平板电脑 (Archos 101),但我的问题是针对我尝试过的每一台平板电脑/手机。

我做了一个非常棒的应用程序,但是对于演示过程中的一些动画,客户想要使用 Flash 动画。因为我无法在 Android 中轻松编写动画(有点像小电影/动画图形),而且时间不够,所以这似乎是个好主意。

所以,在网上搜索了一番后,我使用了 webview 和这段代码:

    WebView mWebView1 = (WebView) findViewById(R.id.webview1);
    mWebView1.getSettings().setjavascriptEnabled(true);
    mWebView1.getSettings().setPluginsEnabled(true);
    mWebView1.loadUrl("file:///android_asset/graph_01.swf");

这项工作非常好,但在我尝试过的每台设备(Archos 101、Nexus One、Nexus S、Galaxy S、Xperia、Desire、HTC Hero 等等)上,每一个活动都带有 webview 闪烁,几毫秒的黑色屏幕,然后动画终于出现了。

PS:我的布局也很简单:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_
    >
<WebView android:id="@+id/webview1" android:layout_
            android:layout_></WebView>
</LinearLayout>

请帮助我,我无法想象我是唯一一个面临这个问题的人。

非常感谢您的帮助。你有我所有的代码和演示 apk。

【问题讨论】:

我在安卓浏览器上注意到了这种行为......我担心你可能需要等待很长时间才能修复它...... @Profete162 你能把你的项目文件分享给我吗... 【参考方案1】:

这个答案稍后添加:

所以问题是 Adob​​e 的 Flash Player 在 WebView 内创建了一个 SurfaceView,并且在 SurfaceView 出现和 Flash 引擎费心绘制任何内容之间存在延迟。在那个小间隙中,SurfaceView 看起来完全是黑色的。

我找到的解决方案是继承 WebView 并将自定义的 SurfaceView 添加到视图树。其次,抑制对 Adob​​e 视图的第一次 draw() 调用也很重要。我的子类 WebView 的代码如下:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.webkit.WebView;
import android.widget.AbsoluteLayout;

public class FixAdobeWebView extends WebView 

    View whiteView;
    private boolean eatenFirstFlashDraw;

    public FixAdobeWebView(Context context, AttributeSet attrs) 
        super(context, attrs);
        whiteView = new WhiteSurfaceView(context);
        whiteView.setLayoutParams(new AbsoluteLayout.LayoutParams(800, 480, 0, 0));
        addView(whiteView);
    


    private class WhiteSurfaceView extends SurfaceView implements SurfaceHolder.Callback 
        public WhiteSurfaceView(Context context) 
            super(context);
            getHolder().addCallback(this);
        
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
            Canvas canvas = holder.lockCanvas();
            if (canvas != null) 
                canvas.drawColor(Color.WHITE);
                holder.unlockCanvasAndPost(canvas);
            
        
        @Override
        public void surfaceCreated(SurfaceHolder holder)  
        @Override
        public void surfaceDestroyed(SurfaceHolder holder)  
    


    //
    // Override drawChild to eat the first draw of the FlashPaintSurface
    //
    @Override 
    protected boolean drawChild (Canvas canvas, View child, long drawingTime) 
             if (!eatenFirstFlashDraw && child.getClass().getName().equals("com.adobe.flashplayer.FlashPaintSurface")) 
                 eatenFirstFlashDraw = true;
                 return true;
             
        return super.drawChild(canvas, child, drawingTime);
    

布局 XML 应该声明这个类的一个实例,即:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_
    android:background="@android:color/white"
    >
<org.test.FixAdobeWebView android:id="@+id/webview1" 
    android:layout_
    android:layout_
    />
</LinearLayout>

在我运行 CM6.1 的 Nexus One 上,这非常有效,因为在 Flash SurfaceView 开始绘图之前,WebView 显示为纯白色。您可能需要对其进行一些调整,例如摆脱硬编码的 800x480 尺寸,并在不再需要时销毁白色 SurfaceView。

原始(错误)答案:

看起来 Adob​​e 应该为此负责。

到目前为止,我发现的最不糟糕的解决方法是:

    将 WebView 父级的背景设为兼容颜色(即白色)。 最初隐藏 WebView。 等到您获得页面加载事件,然后在一秒延迟后排队运行可显示 WebView。

这意味着您在看到任何东西之前肯定会延迟一秒钟,但它比可怕的黑色闪光 afaik 更不刺耳。

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_
    android:background="@android:color/white"
    >
<WebView android:id="@+id/webview1" 
    android:layout_
    android:layout_
    android:visibility="invisible"    
    />
</LinearLayout>

代码:

    final Handler handler = new Handler();
    ...
    final WebView mWebView1 = (WebView) findViewById(R.id.webview1);
    mWebView1.getSettings().setJavaScriptEnabled(true);
    mWebView1.getSettings().setPluginsEnabled(true);
    mWebView1.setWebViewClient(new WebViewClient() 
        @Override 
        public void onPageFinished(WebView view, String url) 
            handler.postDelayed(new Runnable() 
                @Override
                public void run() 
                    mWebView1.setVisibility(View.VISIBLE);                      
                
            , 1000);
        
    );
    mWebView1.loadUrl("file:///android_asset/graph_01.swf");        

可能有更好的方法,尽管这样可以消除对固定延迟的需求......

我已经有一段时间没有用 Flash 做任何事情了,但我似乎记得 Flash 控件有一种方法可以使用浏览器的 Javascript 引擎(快速 Google 会找到 Flex Ajax Bridge,这似乎很可能)。

您可以做的是,通过上述桥接器,使用 ActionScript 调用执行 alert() 的 Javascript 函数。在您的 Java 代码中,您可以将 mWebView1 连接到实现 onJsAlert()WebChromeClient。在该函数中,您可以使 WebView 可见。

【讨论】:

刚刚尝试了你的代码,这似乎做了它应该做的事情(我等了一秒钟才看到东西)但是黑色的闪光仍然出现......我也尝试了 10 秒的延迟,但是黑色在 webview 仍然不可见时,flash 会在片刻后出现 诅咒,有时它确实不起作用......似乎正在创建一个SurfaceView,并且在正在创建的表面和决定绘制任何东西的Flash引擎之间发生了黑色闪光。我们需要的是在隐藏 webview 方面更聪明一点...... @Profete162 我没有忘记这个问题,并计划在今天晚些时候或明天重新讨论。希望能给你一些好消息,但没有承诺。 你好 Reuben,我接受了你的回答,并投票赞成给你我承诺的所有赏金。不幸的是,正如我在第一篇文章中所说的那样,这个问题并没有解决。非常感谢您的帮助,即使我对修复感到非常悲观,我也会祈祷。 @Profete162。我已经做到了!我很快就会更新我的答案 v...简而言之,您需要在 Flash 上粘贴另一个 SurfaceView...

以上是关于使用带闪光灯的 web 视图时屏幕闪烁的主要内容,如果未能解决你的问题,请参考以下文章

uiscrollview 缩放时,内容视图刷新但首先闪烁屏幕

iOS - 来自后台时上一个屏幕闪烁

CSS3 转换导致屏幕闪烁或字体别名

切换到新屏幕时白色闪烁且背景为深色?

在屏幕之间切换时边缘闪烁ios7

批处理脚本 |命令运行时闪烁屏幕