urlを開く時にAndroid標準ブラウザを自動指定する試行錯誤
はじめに
Androidで複数のブラウザアプリをいれていると、アプリ選択画面が出てしまいますが
でも一部の広告とかは、端末の標準ブラウザを指定せずとも自動的に開く みたいな事をしている物があります
そこら辺の実装が気になったのでちょっと調べてみました
Chrome Custom Tabs つかえばええやん。。。
と思われる方も多いと思うのですが、*1
あれの実体は、「アプリの皮をかぶったChrome」なので数点欠点があります
- target-15以上から
- 2/3系OSには使えない
- Intent連携の可能の余地が少ない
- Closeアイコン等もIntent指定モドキで指定できるが以下の制限があり
- https://material.io/icons/ のGoogle準拠のやつじゃないと基本弾かれる
- popupWindowが新しいTabのような形で開けない
- 一部のJSがエラーになる
3)4)に関しては 基本的にブラウザアプリでしか対処できない状態だったりします
参考
端末内の標準ブラウザというと
どうも端末ごとにメーカー独自でパッケージがバラバラみたいで中々厳しい状況だったりします
でも詳しくない一般ユーザ*3は、自分からChromeとかFirefoxとか入れないだろう というお話も
で 端末標準ブラウザ に限定できればテストの工数が削減されるみたいな話だったりも
実装の試行錯誤
2系端末で標準ブラウザで開くイメージ
- 昔のGoogleのサイトに乗っていたやつ。
- Emuratorとかであればこれで済みそうなんですけどね・・・
public boolean checkPackageName(String packageName) { PackageManager pm = getPackageManager(); try { pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); return true; } catch (NameNotFoundException e) { return false; } } private void showBrowser(String url) { if(TextUtils.isEmpty(url)) { return; } Uri uri = Uri.parse(url); try { //2系用標準ブラウザを明示的に指定する if(checkPackageName("com.android.browser")){ Intent intent = new Intent(Intent.ACTION_VIEW,uri); intent.setPackage("com.android.browser"); startActivity(intent); return; } } catch (Exception e) { } }
TextUtilsに関しては、id:sakura_bird1 さんのブログを参照
規程のアプリが指定されている時
private void showBrowser(String url) { //〜略〜 //デフォルトパッケージ名を指定する // => 規定で開く設定 をしている場合に実行される try { Intent browser = new Intent(Intent.ACTION_VIEW, uri); ResolveInfo defaultResInfo = getPackageManager().resolveActivity(browser, PackageManager.MATCH_DEFAULT_ONLY); if (defaultResInfo != null) { browser.setPackage(defaultResInfo.activityInfo.packageName); startActivity(browser); return; } } catch (Exception e) { }
参考
規程のアプリが指定されていない時
private void showBrowser(String url) { //〜略〜 List<ResolveInfo> resInfos = null; try { int flag; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { flag = PackageManager.MATCH_ALL; } else { flag = PackageManager.MATCH_DEFAULT_ONLY; } Intent intent = new Intent(Intent.ACTION_VIEW,uri); resInfos = getPackageManager().queryIntentActivities(intent, flag); //わからないときはOSまかせにする if(resInfos == null || resInfos.size() <= 1){ startActivity(intent); return; } } catch (Exception e) { }
参考
手動で著名なブラウザアプリを弾く
すごく泥臭い手法・・・
private void showBrowser(String url) { //〜略〜 //chorme,firefox,opera等を除く String[] excludeList ={ "chrome", "firefox", "opera", "yahoo", "dolphin" }; HashSet<ResolveInfo> runlist = new HashSet<>(); for (ResolveInfo resInfo : resInfos) { boolean found_f = false; for (String exclude : excludeList) { if(resInfo.activityInfo.packageName != null && resInfo.activityInfo.packageName.indexOf(exclude) != -1){ found_f = true; break; } } if(!found_f)runlist.add(resInfo); } //1つに絞り込めた if(runlist.size() == 1){ try { Intent intent = new Intent(Intent.ACTION_VIEW,uri); ResolveInfo resInfo = (ResolveInfo)(runlist.toArray()[0]); String packageName = resInfo.activityInfo.packageName; intent.setPackage(packageName); startActivity(intent); return; } catch (Exception e) { } }
これでも通過してしまう時は。。。
private void showBrowser(String url) { //〜略〜 //ブラウザアプリが複数入れられている場合は選ばせる Intent intent = new Intent(Intent.ACTION_VIEW,uri); startActivity(chooser); }
or
ココまで来たらあえてユーザーに恣意的に選ばせるとか・・
private void showBrowser(String url) { //〜略〜 //ブラウザアプリが複数入れられている場合は選ばせる Intent intent = new Intent(Intent.ACTION_VIEW,uri); final Intent chooser = Intent.createChooser(intent, "Browser"); startActivity(chooser); }
でもまあ、なんか微妙ですね・・・