Ответ 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.