0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】webViewの動画をシークさせる

Posted at

WebViewで動画をシークさせたい

Youtube等の動画サイトにはシークバーやスキップボタンがあり、再生位置の移動ができるような仕様になっていることが多いです。

普通はデフォルトの機能を使えばそれで十分だと思いますが、時にはシークボタンを自作して動画の再生位置を操作したい.....なんて思うことがあるかもしれません。
本記事では、WebView内で動画のシークボタンを実装するサンプルを紹介しようと思います

基本機能

  • WebView内で動画が再生されている時、独自で実装したシークボタンをタップすることで、ユーザーが動画の再生位置を調整できる

シークのためのJavaScript

webViewで再生位置を操作するにはJavaScriptが必要です。
まず、WebView内で動画を操作するためのJavaScriptをkotlinで作成します。以下のコードは、<video> または <audio> 要素を対象に、現在の再生位置から指定された時間だけ進めたり戻したりするためのスクリプトです。

object Script {
    fun seekToTime(seekTime: Double) =
        """
        (function() {
            const media = document.querySelector('video, audio');
            if (!media) {
                console.log('No media element found');
                return;
            }
            const currentTime = media.currentTime;
            media.currentTime = $seekTime + currentTime;
        })();
        """
}

webViewの実装

javascriptの実装が終わったら、webViewを実装していきます。
今回はwebViewの下にシークボタンを配置します。
シークボタンはSeekButtonで実装しています。
(サンプルなのでデザインは適当です......)

@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun BrowserWebView(url: String) {
    val isInspecting = LocalInspectionMode.current
    var webView: WebView? by remember { mutableStateOf(null) }
    Column {
        AndroidView(
            modifier = Modifier
                .weight(1f)
                .clipToBounds(),
            factory = {
                WebView(it).apply {
                    if (!isInspecting) {
                        settings.javaScriptEnabled = true
                        settings.domStorageEnabled = true
                    }
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    webViewClient = WebViewClient()
                    webChromeClient = WebChromeClient()
                    loadUrl(url)
                }
            },
            update = { newWebView ->
                if (isInspecting) return@AndroidView
                webView = newWebView
            }
        )
        
        // シークボタン
        Row(
            modifier = Modifier
                .height(80.dp)
                .fillMaxWidth()
                .background(Color.LightGray)
                .padding(horizontal = 10.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            // 1分戻す
            SeekButton(
                text = "<< 1m",
                seekTime = -60.0,
                webView = webView
            )
            // 10秒戻す
            SeekButton(
                text = "<< 10s",
                seekTime = -10.0,
                webView = webView
            )
            // 10秒進む
            SeekButton(
                text = ">> 10s",
                seekTime = 10.0,
                webView = webView
            )
            // 1分進む
            SeekButton(
                text = ">> 1m",
                seekTime = 60.0,
                webView = webView
            )
        }
    }
}

@Composable
private fun SeekButton(
    text: String,
    modifier: Modifier = Modifier,
    seekTime: Double,
    webView: WebView?,
) {
    Text(
        text = text,
        modifier = modifier
            .size(height = 40.dp, width = 70.dp)
            .background(Color.White, shape = RoundedCornerShape(20.dp))
            .padding(vertical = 10.dp)
            .clickable(
                // タップ時のリップルをなくす
                interactionSource = remember { MutableInteractionSource() },
                indication = null
            ) {
                webView?.evaluateJavascript(Script.seekToTime(seekTime), null)
            },
        textAlign = TextAlign.Center,
    )
}

これでYoutubeなどで動画を再生して、各ボタンを押すとシークします。

ちなみに、需要があるかわかりませんが、動画再生直後にあらかじめ指定した時間へ移動させることもできます。
WebViewClientdoUpdateVisitedHistory()をoverrideして、javascriptを実行することでできます。
onPageFinished()だとYoutubeではうまく動作しません。)

...
 webViewClient = object: WebViewClient() {
    override fun doUpdateVisitedHistory(
        view: WebView?,
        currentUrl: String?,
        isReload: Boolean,
    ) {
        super.doUpdateVisitedHistory(view, currentUrl, isReload)
        // 任意の時間をセットしておく
        view?.evaluateJavascript(Script.seekToTime(30.0), null)
    }
...

上のコードだと、動画を再生した直後に30秒のところに再生位置が移動します。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?