iOS で特定のアプリがインストールされているかチェックする方法と、それに関する疑問点の調査結果を書いていきます。
インストール済みかチェック手順
Info.plist に Scheme を登録して、 canOpenURL
メソッドを実行するだけです。
例えば、 Twitter アプリがインストール済みかチェックするには下記の手順を行います。
1. Info.plist に Scheme 登録
LSApplicationQueriesSchemes
というキーで、 Type は Array
にして、 twitter
を登録します。
2. canOpenURL
を実行
Twitter のアプリがインストールをした状態で、 canOpenURL
を実行してみます。
if UIApplication.shared.canOpenURL(URL(string: "twitter://")!) {
print("Twitter インストール済み")
} else {
print("Twitter インストールされていない")
}
実行結果に Twitter インストール済み
が表示されました。
これで Twitter アプリがインストール済みか特定することができました。
参考: canOpenURL(_:) - UIApplication | Apple Developer Documentation
疑問点
Info.plist に書かずに canOpenURL
を実行したら?
false が返却されるだけで、 warning log やクラッシュはありませんでした。
Info.plist に書かずに特定のアプリを開こうとしたら?
アプリの Open はできるようです、下記のダイアログが表示されアプリを開くことができました。
LSApplicationQueriesSchemes
はアプリの存在確認に必要なだけで、開く場合はチェックなどは不要なようです。しかし、インストールされていないのにそのアプリを開こうとしても何も起きないので、チェックした上で開かないとユーザ体験がよくないですね。
let url = URL(string: "twitter://")!
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
iOS 10 以降でアプリを起動するメソッドが変わったようですね。
参考: [iOS 10] UIApplication の openURL: が Deprecated になりました | Developers.IO
このパターンはコメントで指摘いただきました、 @ktysne さんありがとうございます!
存在しない Scheme のアプリを開こうとしたら?
存在しない false
というアプリを開こうとしてみましたが、ログも何も出ず、何も起きませんでした。
let url = URL(string: "false://")!
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
Scheme が重複したらどうなる?
本家 Twitter アプリとは別に、 twitter
という scheme を持った別のサンプルアプリを作って実行してみたところ、 サンプルアプリが起動しました。
(後にインストールしたアプリが勝つ?)
セキュアな情報を渡していると、 scheme を重複させられて情報を引っこ抜かれる可能性がありますので注意が必要です。 canOpenURL
が true
だとしても自分の望むアプリかは不明なので、全幅の信頼を置くのはやめましょう。
アプリのアップデートが必須か?
Info.plist を変えるにははアプリのアップデートが必要で、つまり Apple の審査を通さねばなりません。
サーバから scheme をもらって動的に canOpenURL
の引数を変更はできません。
iOS8 までは canOpenURL
で他のアプリを調べ放題だったのですが、プライバシーへの配慮で iOS9 以降はこの仕様になったようです。
参考: iOS9でカスタムURLスキームの遷移に失敗するときの注意点 - Qiita
Universal Links でインストール済みか取れないか?
多分ダメ。(多分なのは実際には試していないので...)
Universal Links に対応するにはサーバ + アプリの両方で対応が必要であり、他所のアプリが Universal Links を利用してインストール済みかを取得できません。
また、URL を Safari で開こうすると Universal Links 対応かが自動で判定され、そのアプリが自動で立ち上がります。そのため、自アプリから他所のアプリがインストールされているかの確認はできません。
Universal Links は安全性や非公開性などの思想で設計されているため、これを Hack してインストール状況などは取得不可です。
- 参考
参考アプリ
Launcher - 通知センターウィジェット搭載ランチャー
アプリを開くだけならば Info.plist に書いておく必要はないため、一般的な Scheme をアプリ内に保持して、マイナーなアプリはカスタム Scheme としてユーザが手動で登録できそうです。
おわり
特定のアプリがインストール済みか調べたい場合、 Info.plist に scheme を登録して canOpenURL
メソッドを叩く以外にインストール状況の取得はできなさそうです。
あまり変なことをやろうとせずに、素直に Apple 様に従いましょう。