0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

簡単で安全な UriHandler の実装例と利用方法

Last updated at Posted at 2025-06-14

UriHandler とは

UriHandlerandroidx.compose.ui.platform が提供する、URI(Web ページ、ファイル、外部アプリなど)を開くためのインターフェースです。Composable 関数からは、以下のようにシンプルに呼び出せます。

@Composable
fun OpenUriButton(uri: String) {
    val uriHandler = LocalUriHandler.current
    Button(onClick = { uriHandler.openUri(uri) }) {
        Text(text = "Open URI")
    }
}

Android におけるデフォルトの UriHandler

LocalUriHandler.current で取得されるのは、各プラットフォームに応じた UriHandler の実装です。Android 環境では、デフォルトとして AndroidUriHandler が使用されます。

AndroidUriHandler では、URI に対応するアプリがインストールされていない場合や、URI の形式が無効な場合などに IllegalArgumentException が throw されます。そのため、呼び出し側ではクラッシュ(アプリの異常終了)を防ぐため、例外処理を行う必要があります。

AndroidUriHandler.android.kt 全文

https://cs.android.com/search?q=file:androidx/compose/ui/platform/AndroidUriHandler.android.kt+class:androidx.compose.ui.platform.AndroidUriHandler

/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.compose.ui.platform

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri

class AndroidUriHandler(private val context: Context) : UriHandler {

    /**
     * Open given URL in browser
     *
     * @throws IllegalArgumentException when given [uri] is invalid and/or can't be handled by the
     *   system
     */
    override fun openUri(uri: String) {
        try {
            context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(uri)))
        } catch (e: ActivityNotFoundException) {
            throw IllegalArgumentException("Can't open $uri.", e)
        }
    }
}

class AndroidUriHandler(private val context: Context) : UriHandler {
    override fun openUri(uri: String) {
        try {
            context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(uri)))
        } catch (e: ActivityNotFoundException) {
            throw IllegalArgumentException("Can't open $uri.", e)
        }
    }
}

簡単に安全に URI を開くために

記事中のリンクやお知らせなど、ユーザーに URI を開かせたいシーンは多々あります。ほとんどの場合では URI を開くのに失敗したときは、ユーザーにそのことを伝えれば十分です。

しかし、毎回呼び出し側で例外処理を実装するのは煩雑です。また、ライブラリや SDK 内で UriHandler を呼び出している場合は、例外処理を差し込むのが難しいケースもあります。

そこで、例外を throw する代わりに Toast を表示する独自の UriHandlerSafeUriHandler)を実装しました1CompositionLocalProvider を使用して LocalUriHandler を上書きすることで、以降の処理では LocalUriHandler.current を通じて SafeUriHandler を取得できます。これにより、アプリケーション全体で安全な URI オープン処理を適用することが可能です。

class SafeUriHandler(private val context: Context) : UriHandler {
    override fun openUri(uri: String) {
        try {
            context.startActivity(Intent(Intent.ACTION_VIEW, uri.toUri()))
        } catch (e: ActivityNotFoundException) {
            Toast.makeText(context, "Can't open $uri.", Toast.LENGTH_SHORT).show()
        }
    }
}
@Composable
fun MyApp() {
    val context = LocalContext.current
    val uriHandler = remember(context) { SafeUriHandler(context) }
    CompositionLocalProvider(
        LocalUriHandler provides uriHandler,
    ) {
        // ...
    }
}
URI を開ける場合 URI を開けない場合

まとめ

  • LocalUriHandler.current を使用すると、プラットフォーム標準の UriHandler を取得できます
  • デフォルトの AndroidUriHandler は、URI の起動に失敗した際に例外を throw し、アプリがクラッシュする可能性があります
  • SafeUriHandler のように例外を throw しない独自の UriHandler を実装することで、呼び出し側での例外処理が不要になります
  • CompositionLocalProvider を使って LocalUriHandler を上書きすることで、アプリ全体を通して独自処理利用できます

参考文献

  1. SafeUriHandler は簡易な通知手段として Toast を利用していますが、UI の状態に応じて Snackbar や Dialog を用いる方が適切な場合もあります。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?