Android の WebView は仕様をよく理解していないと、ネイティブ実装よりも大変なケースに遭遇します(しました)。
WebView から Web ページが表示されて一息ついていたら、YouTube が見れないという問題が発生しましたので、その解決方法をメモしておきます。
老婆心ながら、くれぐれもアプリのユーザーエージェントを、あまりにもユニークなものに書き換えたりしないでください。
ユーザーエージェントが大きく変わると、今回の方法でどう頑張っても YouTube は再生できません。これで人生の貴重な3日間を棒に振りました。。。
それではどうぞ。
目次
- AndroidManifest の設定
- MainActivity -> WebView の設定
- MainActivity -> WebChromeClient 拡張クラス
- MainActivity の全コード
- レイアウトファイル
AndroidManifest の設定
application の android:hardwareAccelerated を true にします。
AndroidManifest.xml
[code]
[/code]
MainActivity -> WebView の設定
WebView の設定を以下のようにし、WebChromeClient の拡張クラス(後述)をセットします。
MainActivity.java -> protected void onCreate
[code]
myWebView = (WebView) findViewById(R.id.webView);
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAppCacheEnabled(true);
myWebView.setWebChromeClient(new CustomWebChromeClient());
[/code]
MainActivity -> WebChromeClient 拡張クラス
WebChromeClient の拡張クラスが必要な理由は YouTube のフルスクリーン表示に対応するためです。
フルスクリーン表示になったとき、 WebVeiw を非表示にしカスタムビューと背景(黒)を表示、フルスクリーンが解除された時に WebVeiw を表示し、カスタムビューと背景(黒)を非表示にする、といった処理を書く必要があります。
WebChromeClient の拡張クラスでオーバーライドするメソッドは次の2つです。
- public void onShowCustomView
- public void onHideCustomView
WebChromeClient の拡張クラス CustomWebChromeClient は以下のようになります。
MainActivity.java
[code]
class CustomWebChromeClient extends WebChromeClient {
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (videoCustomView != null) {
callback.onCustomViewHidden();
return;
}
final FrameLayout frame = ((FrameLayout) view);
final View v1 = frame.getChildAt(0);
view.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER));
v1.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
onHideCustomView();
return true;
}
return false;
}
});
videoCustomView = view;
customViewContainer.setVisibility(View.VISIBLE);
customViewContainer.setBackgroundColor(Color.BLACK);
customViewContainer.bringToFront();
myWebView.setVisibility(View.GONE);
customViewContainer.addView(videoCustomView);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
customViewContainer.removeView(videoCustomView);
videoCustomView = null;
customViewContainer.setVisibility(View.INVISIBLE);
myWebView.setVisibility(View.VISIBLE);
}
}
[/code]
MainActivity の全コード
完成した MainActivity は以下となります。
MainActivity.java
[code]
public class MainActivity extends Activity {
private WebView myWebView;
private View containerView;
private FrameLayout customViewContainer;
private View videoCustomView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = (WebView)findViewById(R.id.myWebView);
customViewContainer = (FrameLayout) findViewById(R.id.customView_frame);
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAppCacheEnabled(true);
myWebView.setWebChromeClient(new CustomWebChromeClient());
myWebView.loadUrl(“”);
}
class CustomWebChromeClient extends WebChromeClient {
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (videoCustomView != null) {
callback.onCustomViewHidden();
return;
}
final FrameLayout frame = ((FrameLayout) view);
final View v1 = frame.getChildAt(0);
view.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER));
v1.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
onHideCustomView();
return true;
}
return false;
}
});
videoCustomView = view;
customViewContainer.setVisibility(View.VISIBLE);
customViewContainer.setBackgroundColor(Color.BLACK);
customViewContainer.bringToFront();
myWebView.setVisibility(View.GONE);
customViewContainer.addView(videoCustomView);
}
@Override
public void onHideCustomView() {
super.onHideCustomView();
customViewContainer.removeView(videoCustomView);
videoCustomView = null;
customViewContainer.setVisibility(View.INVISIBLE);
myWebView.setVisibility(View.VISIBLE);
}
}
}
[/code]
レイアウトファイル
おまけに layout ファイルも載せておきます。
activity_main.xml
[code]
[/code]
まとめ
Android も YouTube も同じ Google なのに、なぜここまでやらなければ WebView から YouTube が再生できないんでしょうか。
今回のソースコードは Android 4.0 以降をターゲットに YouTube の再生に特化したソースコードですが、ここに WebViewClient、ジェスチャー、Android OS の後方互換を考慮した場合、相当カオスなソースコードになります。
Android の WebView の取り扱いにはくれぐれもご注意を。
この記事がみなさんのお役に立ちましたら、下記「Share it」よりブックマークやSNSで共有していただければ幸いです。