2013年5月27日月曜日

Google I/O 2013 - Android :Beyond the Blue Dot: New Features in Android Location

Beyond the Blue Dot: New Features in Android Location

我々がやってきたことについて紹介したい。
1つ目は新しいタイプのアプリが可能になるということについて。2つ目はロケーションを支える進化したテクノロジーについて。

Fused Location Provider
Geofence
Activity Recognition

最後に新しい Location API のポテンシャルが何かを見る機会をもうけたい。


Growing Importance of Location

有名なアプリのほとんどが位置情報を使っている。本当に世界中でたくさんのアプリが位置情報を使っている。
GoogleMap, Google+, Facebook, Twitter, Google Now, 著名なアプリケーションはみんな使ってる。

3つの質を改善する機会を与えたい
・Power(電池消費)
・Accuracy(正確さ)
・coverage(検出範囲)


New Type of App: Contextual Apps

Contextual App の例の1つが Google Now。
Google Now チームはカードを追加し続けているが、Google Now は全てのカードにおいてコンテキストに基づいている。
本質的に、深く位置情報に紐づいている。

多くの Contextual App ではこれが正しいと我々は思っている。
世界クラスの Contextual App を本当に作りたいなら、ハイクオリティな位置情報が必要だ。
しかし、問題がある。Google+ のような Contextual App が必要としているものは、Google Maps のようなアプリが必要としているものとは少し異なる。

Google Maps を使うときは情報をすぐに欲しいとき。タスク指向。Map を起動して何かを達成する。
Google Now はこれとは大きく異なる。Google Now は時々通知するし、ユーザーはときどき Google Now を引っ張りだして待ってたり、準備できてたりするものがあることを期待する。
使い方のモデルが異なる。
位置情報で必要としているものも違う。

例えば、電源消費について見てみると、スクリーンがオンのとき約350mW消費され、プロセッサーがオンのとき約300mW消費される。それと比較して、GPS は100mW消費する。画面をオンにしてマップを見ているとき、GPS は 13%, 14% くらいを消費している。
Google Now のようなものだと、常に100mWを消費すると電池はすぐに枯渇してしまう。
電池にはすごく注意しなければならない。

正確さについても見てみよう。Google Now のようなアプリでは常にすごく正確なものである必要はない。



ハイクオリティの位置情報モデルを構築するのはものすごく大変。

ハイクオリティの位置情報アプリを作るには4つのコンポーネントとやり取りする必要がある。
  • GPS
  • Wi-Fi
  • cell(基地局)
  • sensors(センサー)
それぞれのコンポーネントはことなる特徴がある。
GPS は電池消費が大きく100mW。一方 Wi-Fi は約30mW で 1/3。
しかし、正確さは GPS がすばらしい。Wi-Fi はときどきよくて、ときどきすごいだめ。
Coverage では GPU は屋内で使えない。
基地局は電池消費が少ないが正確さはよくない。1/2 マイル(=約800m)くらい。



複雑さの問題について

ハイクオリティの位置情報アプリを作るには3つの特徴 Power, Accuracy, Coverage を理解して、上図の複雑な処理を扱わなければならない。GPS から LocationProvider を取得し、Passive Location Provider も使いたいかもしれない。センサーともやりとりしないといけない。
開発者は単に位置情報を欲しいだけなのに、これらすべての面倒を見ないといけない。



ロケーションのドキュメント。複雑な処理のタイムラインにうんざりする。
この面倒な処理を我々は新しい API 内でやった。


センサーの重要性について

センサーはゲームだけじゃない。



センサーは位置情報の取得にも有用。Accelerometer は平行・側面の移動を、gyro は回転スピードを、コンパスと magnetometer はどっちの方角を向いているか、barometer は高さを検出できる。

センサーは電池消費を抑えるのにも使える。座っている状態なら位置情報をアップデートする必要はない。accelerometer を使えば座っているかどうかわかる。
どういう活動をしているか検出することもできる。運転しているならより頻繁に位置情報をアップデートしたほうがいい。
クオリティ、とくに屋内での正確性にも役立つ。

[モスコーニ内を移動したときの実際の位置と Fused Location Provider で検出した位置の遷移の動画デモ]

[WiFi だけで検出した場合も比較として動画デモ]

Goals of the Changes
  • 電池消費を抑える
  • 正確性を改善する(屋内でも十分な正確性をとれる)
  • APIs をよりシンプルにする(シンプルにしただけではない、より効果的になっている)
  • クールな新しい機能を提供する
  • ほとんどの Android デバイスで利用できるようにする


Fused Location Providero

上記の複雑な処理が Fused Location Provider を使うとこうなる。



この下で何をしているのか知りたいですよね?

[実際の位置と GPS の位置を遷移を示した動画]

GPS は屋内では全然使えなく、人が屋内からでてきたとき位置に少しジャンプがある

[実際の位置と WiFi の位置を遷移を示した動画]

Wi-Fi は屋外では全然ダメ、屋内では結構いい、また屋外にでると全然使えない

そこで Fused Location Provider では GPS, WiFi, Cell, sensors を組み合わせ利用している

[実際の位置と Fused Location Provider の位置を遷移を示した動画]

屋内でも屋外でも正確にトラッキングしている。

・Listeners vs Pending Intent
・Foreground vs Background

アプリがフォアグラウンドにいる場合、Listener を登録して、同期で位置情報を取得する方法は適している。
マップアプリやナビゲーションアプリなど。

Contextual Apps ではバックグラウンドで動作したい。アプリはロケーションプロセスと強く紐づく必要はない。そのために PendingIntent を使う。
PendingIntent とは何か?これはアプリからロケーションプロセスに渡すトークンで、ロケーションプロセスは必要なときにそれを使ってアプリを起動する。つまり、バックグラウンドで常に動いている必要さえないということ。
そのため電池消費を抑えられる。

  1. mLocationClient = new LocationClient(...);  
  2. mLocationClient.connect();  
  3.   
  4. // public void onConnected(Bundle bundle)  
  5.   
  6. // Get the latest known location. Useful when you need location quickly.  
  7. Location location = mLocationClient.getLastLocation();  
  8.   
  9. // Create location request.  
  10. LocationRequest locationRequest = LocationRequest.create()  
  11.   .setInterval(5000).setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);  
  12.   
  13. LocationListener mLocationListener = new LocationListener() {  
  14.   @Override  
  15.   public void onLocationChanged(Location location) {  
  16.     Log.i(TAG, "Received a new location " + location);  
  17.   }  
  18. };  
  19. // Request updates.  
  20. mLocationClient.requestLocationUpdates(locationRequest, mLocationListener);  
LocationClient のインスタンスを作って connect() を呼ぶ。そうするとコールバックの onConnected() が呼ばれる。getLastLocation() を呼ぶと、システムが管理している最新の位置情報がすぐに返ってくる。

プライオリティやインターバルをセットして位置情報のリクエストオブジェクトを作成し requestLocationUpdates() を呼ぶ。


PendingIntent の方法
  1. PendingIntent mIntent = PendingIntent.getService(...);  
  2.   
  3.   
  4. mLocationClient.requestLocationUpdates(locationRequest, mIntent);  
  5.   
  6. public void onHandleIntent(Intent intent) {  
  7.   String action = intent.getAction();  
  8.   if (ACTION_LOCATION.equals(action)) {  
  9.     Location location = intent.getParcelableExtra(...)  
  10.   }  
  11. }  
getService() を呼んで PendingIntent を作成し、requestLocationUpdate() を呼ぶ。LocationRequest の作成方法は Listener のときと同じ。

getLastLocation() はブラウザの検索のように、すぐに大ざっぱな現在地が知りたいときに使える。requestLocationUpdates() はマップアプリなどで使える。



Priority には3種類ある。
HIGH_ACCURACY は屋外では GPS を使い、屋内では Wi-Fi や cell を使う。典型的なインターバルは5秒。マップやナビゲーションアプリ向け。正確性が高いが電池も消費する。
BALANCED_POWER は GPS を使わない、Wi-Fi や cell を使う。典型的なインターバルは20秒。
NO_POWER は別のアプリのリクエストで取得した位置を取得するときに使える。正確性はそのときの状況に依存する。


Geofencing

ある領域を定義し、ユーザーがそこに入ったり出たりしたときに通知する。

[Geofencing のデモ]

アプリあたり100個の Geofence をサポートする。

[興味のある家をお気に入りに入れておくと、近くにいったときに通知してくれるアプリのデモ]

  1. mLocationClient = new LocationClient(...)  
  2. mLocationClient.connect(); // - Entry point for Location and Geofence APIs  
  3.   
  4. public void onConnected(Bundle bundle) {  
  5.   Geofence geofence = new Geofence.Builder().sentRequestId(stringId)  
  6.     .setTransitionTypes(transitionTypes)  
  7.     .setCircularRegion(getLatitude(), getLongitude(), getRadius())  
  8.     .setExpirationDuration(expiration).build();  
  9.   
  10.   mLocationClinet.addGeofences(List<geofences> geofences,  
  11.     PendingIntent intent, ...);  
  12. }  
  13. </geofences>  
geofenceId, transition type(範囲に入ったり出たりするときのトランジションについて), 領域のための latitude, longitude, radius(geofence は現在円形の範囲をサポートしている), geofence が無効になるまでの時間をセットする。
  1. public void onReceive(Context context, Intent intent) {  
  2.   String action = intent.getAction();  
  3.   if (GeofenceActivity.ACTION_GEOFENCE.equals(action)) {  
  4.     // This is an intent that indicates geofence transition.  
  5.     handleGeofenceCrossed(context, intent);  
  6.   }  
  7. }  
  8.   
  9. private void handleGeofenceCrossed(Context context, Intent intent) {  
  10.   int transition = LocationClient.getGeofenceTransition(intent);  
  11.   List<geofence> crossedGeofences = LocationClient.getTriggeringGeofences(intent);  
  12. }  
  13. </geofence>  
Geofence を横切るとコールバックが呼ばれる。


addProximitlyAlert API がすでにあったが、それと比較して Geofence は電池消費が 1/3 くらいになる。



例えばサンフランシスコにいてゴールデンゲートブリッジを楽しんでるとする。一方でハリウッドとロサンゼルスに Geofence がある。電話はどこにいるのか知っているので、geofence を横断したかどうかポーリングし続ける必要がない。
ユーザーが止まっていたり歩いていたりする。電話はそれを知っているので、それをポーリング間隔を調整するのに利用する。
我々はハードウェアでの処理にも移行したい。
geofence は基本的にバックグラウンドでの処理。つまりアプリケーションの処理担当は常に起きている必要は無い。geofence のモニタリングをハードウェアでできる。GPS のハードウェアのように、ハードウェアが我々に geofence に入ったよと伝えることができる。


Activity Recognition

スマホのセンサーを使って、ユーザーが車にのっているのか、歩いているのか、座っているのか、自転車に乗っているのか検出する。 多くの Acitivity データを集めて機械学習でクラス分けを行い、ユーザーが今していることがどのクラスのものなのかわかるようになった。



Endomondo というフィットネスアプリの例

Moves という 3rd-party の Activity トラッカーアプリの例

[エンジニアがポケットにスマホをいれて、ステージ上を歩いたり自転車に乗ったりして Activiy Recognition が動くかどうかのデモ]

Activity から Activity へ遷移しているときなどは TILTING という状態になる。
  1. ActivityRecognitionClient mActivityClient = new ActivityRecognitionClient(...);  
  2. mActivityClient.connect();  
  3.   
  4. // Called when a connection to the ActivityRecognitionService has been established.  
  5. public void onConnected(Bundle connectionHint) {  
  6.   mActivityClient.requestActivityUpdates(30000, callbackIntent);  
  7. }  
  8.   
  9. /** 
  10.  * public void requestActivityUpdates(long detectionIntervalMillis, 
  11.  *    PendingIntent callbackIntent) 
  12.  */  
ActivityRecognitionClient を作成し、connect() を呼ぶ、接続したら requestActivityUpdates() でアップデートを受けとる。
  1. protected void onHandleIntent(Intent intent) {  
  2.   if(ActivityRecognitionResult.hasResult(intent)) {  
  3.     ActivityRecognitionResult result =   
  4.       ActivityRecognitionResult.extractResult(intent);  
  5.     DetectedActivity activity = result.getMostProbableActivity());  
  6.   }  
  7. }  
  8.   
  9. // DetectedActivity - IN_VEHICLE, ON_BICYCLE, ON_FOOT, STILL, TILTING  
  10. // Detected Activities have associated probabilities.  
  11. // Apps would need to use new ACTIVITY_RECOGNITION permission  
新しい ACTIVITY_RECOGNITION パーミッションが必要。


Making It Available Everywhere

新しい API は今すぐ使える
・Fused Location Provider
・Activity Recognition
・Geofencing

・アプリは Cient library を一緒にビルドする



API を提供するのに Google Play Services を使う。
Google Play Services は Play Store からアップデートされる単一の apk。


なぜ Google Play Services なのか?
  • Backward compatible to Froyo
  • Google Data Models(屋内の位置検出など)
  • Shorter Release Cycle(プラットフォームのアップデート待つよりもっとずっと早く改善できる)



What's next

これからのこと。
1つ目は正確性の改善。GPS, Wi-Fi, cell, sensor に続く新しいコンテキスト。たとえば Bluetooth low energy が次バージョンでサポートされる。屋内での正確性をもっと改善したい。飛行時間を考慮することで Wi-Fi の位置のジャンプを取り除く 802.11v(?)のような基準がある(# この文ちょっと自身ない)。新しいテクノロジーでより位置情報を改善していく予定。開発者は何もする必要がない。表に新しいコンテキストが追加されるだけ。
屋内の floor plans(?)を使って正確性を改善できる。
geofence のときに言及したように多くのことをハードウェアでもできる。
すでにハードウェアベンダーと一緒に作業をしている。
Coverage も改善したい。本当に屋内で検出できるようにしたい。




QA

Q. geofence の制限の100個はアプリ全体に対してですか?それとも複数ユーザーがそれぞれ100個の geofence を使えますか?
A. ええと、ちょっとチェックします。
(Android の fireside chat で多分同じ人が質問していて、(なぜかというとセッションで質問したんだけど、、、と言っていたので)そこではアプリ毎に100個という回答だった)

Q. ADK の一部になる予定はありますか?
A. いろいろなオプションを考えているところないので、その質問には今すぐは答えられないです。

Q. デバイスをバックパックに入れている状態でもちゃんと Activity を認識しますか?
A. いろいろな異なるタイプのデータをテストしたので、パーフェクトではないですが、だいたいはうまく動きます。

Q. 現在のスピード、時速はとれますか?
A. ちょっとわからないや。チェックします。オフィスアワーにきてください。

Q. Activity が切り替わるときにラグタイムはどのくらいですか?
A. どういうトランジションをしているかによるけど、多くて30秒〜1分くらいかな。さっきここでデモしたときは歩きから自転車に変わるまで8秒だったよ。

Q. 車で移動しているときに運転しているのか、乗っているだけなのかわかりますか?
A. 今は出来ません。将来はできるかもね。





0 件のコメント:

コメントを投稿