musicLineアプリ開発日記

作曲を誰でも楽しく簡単に♪

リンク先のページ情報を取得する

今回はリンク先のページ情報(タイトル、詳細、サムネイル)を取得する話。

ページ情報の表示



はじめに

musicLineではコミュニティでユーザー同士が会話するためのチャット機能があります。以前までそのチャットにYouTubeのURLを載せるとアプリ内で動画を再生できるように実装していましたが、そのライブラリのサポートが終了して機能しなくなりました。


今後はWeb技術のiFrameを使うことでYouTubeの埋め込みを実現する方法もあるようですが、これを機会にURLをコメントに送信したときの挙動を再検討しました。

そもそも今まではYouTube以外のURLを送っても、リンク先ページの情報がわからなく、URLテキストのみを表示する仕様になってました。

URL先ページ情報なし


しかし、この仕様ではリンク先のページに飛ばないと内容がわからなく、会話の中でリンク先を送ることに躊躇してしまうことがあると思います。
そこでYouTubeに限らずURLをコメントで送ることで、リンク先ページの情報を取得して、表示できるように改良しました。



ページ情報の取得

OGP (Open Graph Protcol)

WebページはHTMLで書かれていますが、特にリンクをシェアした時に使用してほしい文書や画像はOGP (Open Graph Protcol)に基づいて設定されます。

↑このリンクバーもOGPを元に情報を取得しているはず

具体的には、Webから以下のようなHTMLドキュメントを取得するので、ogメタタグの要素を確認すると情報を取得できます。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta property="og:title" content="タイトル" />
        <meta property="og:image" content="画像のURL" />
        <meta property="og:description" content="ページの説明" />
        ...

    </head>
    <body>
        ...
    </body>
</html>
プロパティ 内容
og:title タイトル
og:image 画像のURL
og:description ページの説明


実装

下記のページを元にAndroid+Kotlinでリンク先のページ情報を取得するように実装しました。


基本的にはJsoupライブラリでHTMLのURLを指定するだけで、要素の内容を取得できます。

val doc = Jsoup.connect(url).get()
val headEls = doc.head().children()
for (v in headEls) {
    val prop = v.attr("property")
    val content = v.attr("content")
    println("プロパティ:$prop、内容:$content")
}


ただ、メインスレッドでJsoup.connect(url)にてWebからHTMLをダウンロードすると例外が発生するため、ダウンロードする際はサブスレッドで行います。
ViewModelで処理を行っている場合は、viewModelScopeを使用するといいでしょう。

viewModelScope.launch(Dispatchers.Main) {
    
    // サブスレッドでHTMLを取得
    val doc = withContext(Dispatchers.IO) {
        try {
            Jsoup.connect(url).get()
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }
    ...
}


全コードを表示

viewModelScope.launch(Dispatchers.Main) {
    
    // サブスレッドでHTMLを取得
    val doc = withContext(Dispatchers.IO) {
        try {
            Jsoup.connect(url).get()
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }
    doc?.let {
        val headEls = it.head().children()
        for (v in headEls) {
            val prop = v.attr("property")
            val content = v.attr("content")
            when (prop) {
                "og:title" -> {
                    // Webページのタイトル
                }
                "og:description" -> {
                    // Webページの説明
                }
                "og:image" -> {
                    // WebページのサムネイルURL
                }
            }
        }
    }
}




おわりに

今回の実装でリンク先のイメージや詳細がわかるようになりました。

リンク先の詳細を表示


ちなみにYouTubeやニコニコのURLは検出して、再生マークを付けてます。
YouTubeのアプリ内再生は非対応となりましたが、タップでYouTubeに飛べるため、アプリ内で再生しなくても良いかと思います。

動画URLの再生マーク