強力なスキーム「android-app://」でサイト内リンクのクリックからIntentを自在に投げる

例えば, YouTubeのURLがあって,

http://www.youtube.com/watch?v=dQw4w9WgXcQ

WEBブラウザ向けにリンクを貼る場合

<a href="http://www.youtube.com/watch?v=dQw4w9WgXcQ">→ Go Movie</a>

と書く.

→ Go Movie

Android端末上では, これをクリックするとデフォルトのアプリ設定がされてない場合は暗黙的インテントが発行されて,

1. 該当アプリ選択ダイアログ

のあと,

2-a. ブラウザでYouTubeサイトの動画が表示される.
2-b. YouTubeアプリで動画が表示される.

となる.

ブラウザアプリとYouTubeアプリをインストールはほとんどの人ががインストールしているだろう.

20151015-083102

20151015-083210

そのリンク記述を

android-app://{package_id}[/{scheme}[/{host}[/{path}]]][#Intent;{...}]

の書式で書く. 書式内 {package_id} は必須.

<a href="android-app://com.google.android.youtube/http/www.youtube.com/watch?v=dQw4w9WgXcQ">→ Go Movie from android-app</a>

これをクリックすると, YouTubeアプリに対して明示的インテントが発行されて, 該当する動画が表示される.

→ Go Movie from android-app

これは以下をセットした明示的インテントを投げるのと等価.

Action:	 ACTION_VIEW
Data:    http://www.youtube.com/watch?v=dQw4w9WgXcQ
Package: com.google.android.youtube

もし YouTube アプリをインストールしていない場合は PlayStoreアプリが起動してYouTubeアプリの画面が表示されてそのままインストールすることができる.

20151015-084402

この書式を使うと

「該当アプリの選択」
「アプリのデフォルトの設定のクリア」

というユーザからみて煩わしい動作がなくなる上, 明示的インテントの

「該当するパッケージがみつからない」

という場合に対しての開発側の手間も省ける.

書式にあるようにこんな記述も可能.

<a href="android-app://com.example.app/
  #Intent;action=com.example.MY_ACTION;
  i.some_int=100;S.some_str=hello;end">...

これは以下明示的インンテントと等価.

Action:	 com.example.MY_ACTION
Package: com.example.app
Extras:	 some_int=(int)100
         some_str=(String)hello

便利だが, いつからこんなのあったんだ?

スキームはスキームなのかっ!?

注意: ブラウザ互換

Intent | Android Developers

Cross Reference: ../Intent.java


最近の「Android System WebView」で追加されている機能

少しWebViewのまわりの挙動が変化している気がしたので調べてみた.

これ.

20151011-142959

AndroidシステムのWebView - Google Play の Android アプリ

Android 5.0 以降に対して, コンポーネントとしてのWebViewを切り離してPlayStoreで更新していくというもの.

このパッケージを入れている場合と入れてない場合の WebView にどれくらい差がでてきているのか.

Android 5.1 実機で簡単に機能を比べる.

…
mWebView = (WebView) findViewById(R.id.web_view);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("https://html5test.com/");
…

HTML5test - How well does your browser support HTML5?

入れていない場合.

20151011-143135

入れている場合.

20151011-143336

10ポイント以上の差がある.

ポイントの大きなもの順に追加された機能をみる.

Service Workers (+10)

20151011-143539

Service Workers Nightly

Introduction to Service Worker: How to use Service Worker - HTML5 Rocks

Service Workerは、最近動きのあるブラウザテクノロジーの中で最もホットな新機能の一つです。ネットワークプロキシとしても働くService Workerは、従来のAppCacheの欠点を克服し、真のオフラインファーストを実現できる技術として期待されています。

そんな今大注目の Service Workerですが、実はAppCacheの代用用途だけでなくバックグラウンドのコンテンツ同期やプッシュ通知などの応用が検討されています。

Service WorkerとHTTP/2が切り開く新しいWeb Pushの世界 - ぼちぼち日記

Clipboard API and events (+5)

20151011-143855

Clipboard API and events

Readable streams (+3)

20151011-144101

Streams Standard

Content Security Policy 1.1 (+2)

20151011-144308

Content Security Policy Level 2

セキュリティ上の機能だけでなく, コンテンツ同期やプッシュ通知, クリップボードやストリーム配信関連機能などアプリ利用者に直接影響するものが追加されているようです.

多数のAndroidユーザーにも分かりやすい「入れておいたほうがいいアプリ」となってくるのだろうと思います.

AndroidシステムのWebView - Google Play の Android アプリ


「Move to iOS」で iPhone に何がどんだけ移行できるのか

今年秋の予定だそうです.

Apple、「iOS 9」にAndroidからの簡単移行ツール「Move to iOS」 - ITmedia ニュース

移行できるもの
- 連絡先
- メッセージ履歴
- カメラで撮影した写真・動画
- ブラウザのブックマーク
- メールアカウント
- カレンダー
- 壁紙
- DRMフリーの音楽・書籍

Android上でリソースにアクセスできるものは
「アプリ-アプリ間で」すべて移行できるようです.

これまでもすでに移行の方法はありましたが,
主として「PCを経由して」の方法でした.

fff0ee33c6f16e41f3db0f39e9c2a386

Android と iPhone 間のデータ移行の説明をながめる

これが「PCを経由」せずにスマホ同士で移行できるとなれば
便利っちゃあ便利だけども.

整理しながらコツコツ移行しようかな.


Chrome CustomTabs 使い方 バックグランド処理で高速に

nexus2cee_stuff_thumb

[I/O 2015] Chrome Custom Tabs Will Add Easy And Rich Web Content To Any App With Chrome Capabilities

サービス経由で「ウォームアップ」,「URL先読み」を行って
高速に開く.

公開されている Googleサンプルのうち利用するヘルパークラスなどは
前回エントリを参照.

 

1. バインド

ウォームアップも同時に行う.
アクテビティのライフサイクルに合わせて.

public class SampleActivity extends AppCompatActivity
        implements CustomTabActivityHelper.ConnectionCallback {

    private CustomTabActivityHelper mCustomTabActivityHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCustomTabActivityHelper = new CustomTabActivityHelper();
        mCustomTabActivityHelper.setConnectionCallback(this);

    }

    @Override
    protected void onStart() {
        super.onStart();
        mCustomTabActivityHelper.bindCustomTabsService(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mCustomTabActivityHelper.unbindCustomTabsService(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCustomTabActivityHelper.setConnectionCallback(null);
    }

    @Override
    public void onCustomTabsConnected() {
    }

    @Override
    public void onCustomTabsDisconnected() {
    }

}

 

2. プリフェッチ

開くであろうURLが確定した時点でバックグランドで先読み.

mCustomTabActivityHelper.mayLaunchUrl(uri, null, null);

 

3. 起動

前回とほぼ同じ.
タイトル, アニメーションを付けてなめらかな体感に.
R.anim.slide_* はサンプルのものを利用.

CustomTabsIntent customTabsIntent =
    new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession())
        .setShowTitle(true)
        .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
        .setExitAnimations(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right)
        .build();
CustomTabActivityHelper.openCustomTab(this, customTabsIntent, uri, new WebViewFallback());

 

以上をまとめてテンプレート的に

public class SampleActivity extends AppCompatActivity
        implements CustomTabActivityHelper.ConnectionCallback {

    private CustomTabActivityHelper mCustomTabActivityHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCustomTabActivityHelper = new CustomTabActivityHelper();
        mCustomTabActivityHelper.setConnectionCallback(this);

    }

    private void preFetchUrl(Uri uri) {
        mCustomTabActivityHelper.mayLaunchUrl(uri, null, null);
    }

    private void open(Uri uri) {
         CustomTabsIntent customTabsIntent = 
            new CustomTabsIntent.Builder(mCustomTabActivityHelper.getSession())
            .setShowTitle(true)
            .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
            .setExitAnimations(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right)
            .build();
         CustomTabActivityHelper.openCustomTab(this, customTabsIntent, uri, new WebViewFallback());
    }

    @Override
    protected void onStart() {
        super.onStart();
        mCustomTabActivityHelper.bindCustomTabsService(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mCustomTabActivityHelper.unbindCustomTabsService(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCustomTabActivityHelper.setConnectionCallback(null);
    }

    @Override
    public void onCustomTabsConnected() {
    }

    @Override
    public void onCustomTabsDisconnected() {
    }

}

イベントからプリフェッチしてからのオープンすればよい.

しかし「先読みのタイミング」て…

(つづく)

Chrome Custom Tabs を とりあえず数行で使う


Chrome Custom Tabs を とりあえず数行で使う

スマホでブラウザを起動する, っての最近では面倒.

LINEとかメッセージでリンクを送ってくる人とか.

20150910-215123

さりげなく開かずにテキトーな会話を続けたりします.

考えてみると「なんかブラウザって重いしトロい」から.

そこで, 最近登場したのが「Chrome Custom Tabs」というしくみ.

Chrome Custom Tabs - Google Chrome

performance

表示までが非常に高速化されてるようにに見える.

実装しようとサンプルをダウンロードしてみる.

GoogleChrome/custom-tabs-client

アプリ内モジュールやヘルパーやプロセス間の通信など
依存関係があるのでわかりづらい.

とりあえずシンプルにURLを渡すだけでで起動してみたいだけなので以下で.

build.gradle

compile 'com.android.support:customtabs:23.0.1'

サンプル内モジュール customtabs 以下は不要.

コピペするクラス

CustomTabsHelper
KeepAliveService
CustomTabActivityHelper
WebViewFallback

shared というモジュールは作らずベタクラスとしてコピペ.
アプリ内モジュール依存はなしで.

起動

...
Uri uri = Uri.parse("http://google.com/");
CustomTabsIntent customTabsIntent =
    new CustomTabsIntent.Builder().build();
CustomTabActivityHelper
    .openCustomTab(this, customTabsIntent, uri, new WebViewFallback());
...

UIカスタマイズはしない. するならここで.

WebViewFallback#openUri()

    ...
    //Intent intent = new Intent(activity, WebViewActivity.class);
    //intent.putExtra(WebActivity.EXTRA_URL, uri.toString());
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(uri);
    activity.startActivity(intent);
    ...

Chromeアプリ (stable/beta/dev) をインストールしてない場合は,
デフォルトブラウザなどに暗黙的に投げる.

で ?

起動はできる.
が, これだけでは恩恵にありつけない.

20150910-224352

サイト内検索などはできるようにはなるが
「なんかブラウザって重いしトロい」が解消せず.

以下の機能があるという.

Pre-warming of the Browser in the background, while avoiding stealing resources from the application.

Providing a likely URL in advance to the browser, which may perform speculative work, speeding up page load time.

これを使わないと意味ないな...

(つづく)