Подтвердить что ты не робот

Экран мигает при использовании веб-просмотра со вспышкой

Изменить: я сделал демо apk, так что вы можете понять, что я имею в виду: http://cl.ly/3g0s1p030j243y0p3m2F

Для моего приложения я хочу своего рода "Super Power Point" или ключевую часть (коммерческая команда представит продукт своим клиентам), используя все Android-приложения, жесты и т.д. на планшете Android. Поскольку Honeycomb еще не готов, и потому что мы нуждаемся в нем перед маршем, мы выбираем какой-то случайный планшет Froyo (Archos 101), но моя проблема для каждого планшетов/телефонов, которые я пробовал.

Я сделал отличное приложение, но для некоторых анимаций во время презентации клиент хотел использовать флеш-анимацию. Поскольку я не мог кодировать анимации (вроде маленьких фильмов/анимированных графических изображений), которые легко в 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_width="fill_parent"
    android:layout_height="fill_parent"
    >
<WebView android:id="@+id/webview1" android:layout_height="fill_parent"
            android:layout_width="fill_parent"></WebView>
</LinearLayout>

Пожалуйста, помогите мне, я не могу себе представить, что я единственный, кто столкнулся с этой проблемой.

Большое спасибо за любую помощь. У вас есть все мой код и демонстрационная версия.

4b9b3361

Ответ 1

НАСТОЯЩИЙ ОТВЕТ ДОСТАТОЧНО:

Таким образом, проблема заключается в том, что Adobe Flash Player создает SurfaceView внутри WebView, и есть задержка между появлением SurfaceView и движком Flash, пытающимся нарисовать что-либо. В этом маленьком промежутке SurfaceView выглядит полностью черным.

Решение, которое я нашел, - это подкласс WebView и добавление настраиваемого SurfaceView в дерево представлений. Во-вторых, важно также подавить первый вызов draw() для представления Adobe. Код для моего подкласса 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_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/white"
    >
<org.test.FixAdobeWebView android:id="@+id/webview1" 
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />
</LinearLayout>

На моем Nexus One, работающем на CM6.1, это отлично работает в том смысле, что WebView выглядит сплошным белым до тех пор, пока Flash SurfaceView не начнет рисовать. Вам, вероятно, придется немного приспособить его, например. избавиться от жестко заданных размеров 800x480, а также уничтожить белый SurfaceView, когда он больше не понадобится.

ОРИГИНАЛЬНЫЙ (НЕПРАВИЛЬНЫЙ) ОТВЕТ:

Похоже, Adobe виновата в этом.

Самое ужасное обходное решение, которое я нашел до сих пор, заключается в следующем:

  • Сделайте фон родителя WebView совместимым цветом (то есть белым).
  • Сначала скройте WebView.
  • Подождите, пока вы не получите событие, загруженное страницей, а затем поставите в очередь runnable, чтобы показать WebView после одной секунды задержки.

Это означает, что вы получите гарантированную за одну секунду задержку, прежде чем сможете что-либо увидеть, но она менее резкая, чем эта ужасная черная вспышка afaik.

Разметка:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/white"
    >
<WebView android:id="@+id/webview1" 
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    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 для вызова функции Javascript, которая делает alert(). В вашем коде Java вы подключите свой mWebView1 до WebChromeClient, который реализует onJsAlert(). В этой функции вы должны сделать видимым WebView.