投稿

ラベル(Android Coding Tips)が付いた投稿を表示しています

AmazonのAppStoreで位置情報を使うアプリの対応端末を増やす方法

イメージ
最近AmazonのAppStoreはパーミッションに関する制約が厳しくなり、これまで何も言われなかったアプリが警告扱いになり、ついに非対応ということになってしまった。 問題のアプリは位置情報を扱うアプリなのだが、Amazonの端末はGPSを搭載している端末が少ないので、このままでは対応端末が非常に限られてしまう。 改善すべきはAndroidManifest.xmlに設定しているパーミッションの指定。現在、位置情報関連のパーミッションは次の2つ。 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> アプリの性質上、GPSほどの高い精度の位置情報は必要無いので、初めはACCESS_FINE_LOCATIONを消してみた。これでGPSを使わないようになるのではと考えたからだ。 これで対応端末は増えたが、ACCESS_COARSE_LOCATIONだけではキロ単位のズレが発生してしまうことが分かった。これはさすがにまずい^^; エラーの内容をよく見ると、「android.hardware.location.gps」がダメだと言っている。 ということは、「GPSは必須でない」という設定があるはず。ドキュメントを見ると <uses-feature> | Android Developers 「android.hardware.location.gps」というプロパティーがあった。そこで、このように指定することにした。 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <...

ionicでcrosswalkのビルド後のapkがarmv7とx86に分かれた件

最新版のionicでは、crosswalkのビルド後のapkがarmv7とx86に分かれるようになった。 これによって、armv7とx86両対応のために40MB以上になっていたアプリサイズが20MB程度まで軽量化された。 喜ばしい事ではあるけれど、リリース時にとても混乱してしまった。 リリーススクリプトを書いているのだけど、これまでは一つのapkにサインすればよかったものが二つのapkにサインする必要がでてきて、スクリプトがまともに動かなくなってしまったからだ。 しかし、このことに気づいた後は特に問題は無かった。 Google Playでは、すでに一つのリリースで複数のapkをアップロードできるようになっているので全く心配は無い。

ionicでインストールするcrosswalkを選択できない件

追記15.07.11 :最新版のionic(1.6.1)では「ionic browser add crosswalk@バージョン」で指定通りインストールできるようになった。この記事も合わせて読むとionicの更新に依存することなくcrosswalkの最新版をインストールできるようになる。 琴線探査: ionicで最新版のcrosswalkをインストールする方法 ---- 最近ionicのCLIが1.5.0にバージョンアップしたのだが、その後platform/androidを削除してcrosswalkを再インストールしたら、localStorageに保存したはずの値がアプリの再起動時に保存前の状態に戻っているという動作になってしまった。 ChromeのDevToolsでは、crosswalkのバージョンは42.0.2311.135となっている。以前のバージョンが何だったのかは覚えていないが、このバグが出る前は確か41系だったような気がする。 「ionic browser ls」でインストールできるcrosswalkを見ると、crosswalk-liteが増えていたりするので多分アップデートされたと思う。 幸いなことに、 ionicはcrosswalkのインストール時にバージョンを指定できる ので、stableで一番古いものをインストールして実行し、再びDevToolsでバージョンを確認すると…全く変わっていない! 何かおかしい。ネットで調べると、どうやらcrosswalk-liteもインストールできないという話。 cordova - How to build android with Crosswalk lite using ionic-cli? - Stack Overflow このページを参考に、「ionic browser add」で何をやっているのかソースを見てみることにした。場所としてはここ。 /usr/local/lib/node_modules/ionic/node_modules/ionic-app-lib/lib/browser.js 問題の場所はこの11行目だとわかった。 cordova 5.0.xがインストールされていると「Browser.installCordovaCrosswalk(appDi...

ionicプロジェクトのsplash.pngを自動でリサイズしながら9-patchする「make-9patched-splash-ionic」

先日、nodejsで9-patch画像を自動生成する方法について書いた。 琴線探査: nodejsで9-patch画像を自動生成する「FourSide1px9patcher」 その後、このコードを使いやすいようにnodeモジュール化した。 junkoro/four-sides-1px-9patcher ここからが本番。ionicプロジェクトでsplash.pngを自動的にリサイズしつつ9-patchするコードを書くときがキタ(・∀・)!! すでにnodeモジュール化して公開済み。 junkoro/make-9patched-splash-ionic インストール方法やコード内容についてはgithubに譲るとして、ここでは開発時に困ったことについて書いておきたいと思う。 9-patchについては開発済みだったので何の問題も無かったが、画像のリサイズが困った。node-canvasでもリサイズはできるのだが、リサイズ後の画像のクオリティーがとても使えたものではないのだ(´・ω・`) この問題はブラウザ上のJSでも同じで、以前に研究したことがあった。 琴線探査: HTML5 Canvasで画像のリサイズするならコレ!「JS-Image-Resizer」 というわけで、再びこの「JS-Image-Resizer」を使わせていただくことにした。結果は上々だ。 ただ、「JS-Image-Resizer」はブラウザ用のJSコードなので、node用に多少変更する必要があった。と言っても、「modules.exports」行の追加とエラーになる部分(WebWorker部)をコメントするくらいだったが。 これでこの件にコメントすることができるようになった。 Bad splashscreen ratio with Android using CLI new feature - ionic - Ionic この件は自分も困っていたが、他にも多くの人が困っているようなので、このコードが助けになればと思う。

nodejsで9-patch画像を自動生成する「FourSide1px9patcher」

イメージ
追記15.05.05 :使いやすいようにnodeモジュール化した。 junkoro/four-sides-1px-9patcher 9-patchツールの現状 〜 開発意図 前から9-patchを作るのは面倒だし問題だと思っていた。そこで改めて現状を調べてみたが、やはり9-patchを作るには ・Android SDKのdraw9patch ・Android Asset Studio - Simple Nine-patch Generator ・Eclipseプラグイン「 Draw 9-patch Tool 」 ・Fireworksなど汎用の画像編集ソフトを使う という感じ。nodejsで、特にgulpで9-patchを自動化できるツールが無いか探したが、これくらい。 gulp-9-patch このツールはスケーリングしたり非9-patch化する機能しかなく、画像を9-patch仕様に加工することはできない。 開発要件 やはり独自開発するしかないか…もう我慢ならん!こんな ('A`)マンドクセ-ことイチイチやってられるかっての! ただ、なぜこのような状況なのかは理解できる。9-patchは柔軟性が高く、画像によってパッチすべき場所は変わる。これが自動化ツールが存在しない理由なのだろう。 しかし、画像を作る側が9-patchしやすい条件を作ればどうだろう?たとえばこんな画像で、単純に4辺の周辺1ピクセルを画面にあわせて伸ばすように9-patchすることを考える。 画像はionicのデフォルトスプラッシュスクリーン用の画像 この条件を満たすケースは意外と多いのではないかと。自分的には自動化するためにデザインを犠牲にする覚悟である(^^); このようなことをしてくれるCLIツールを、後々ionicなどgulpやgruntをビルドシステムとして使っているようなものに組み込むことを考えて、nodejsで開発する。 nodejsでの画像処理をどうする? 〜 技術調査 調べると、みんなよくimagemagickとかを使ってやっているようだが、できればコマンドラインツールに依存するような形にしたくない。 というわけで、前から名前だけは知っていたけれど、よく調べたことがなかったこれを使ってみよう。 ...

CordovaのAndroidアプリを動かすまで(MacOS XとAndroid Studioにて)

イメージ
Android Studioのインストール 従来ならeclipseをインストールするところだが、ナウなヤングはAndroid Studioにしよう。 eclipseのADTプラグインはもう開発が停止しているようで、これから新しく始めるならこちらの方がいいと薦められている。 Android SDK | Android Developers Get Android Studio Beta Android Studio is a new IDE powered by IntelliJ that provides new features and improvements over ADT. It's currently in beta but will be the official Android IDE once it's ready. If you're a new Android developer, you should consider starting with Android Studio, because the ADT plugin for Eclipse is no longer in active development. また、eclipseよりAndroid開発に特化しているので扱いやすいというメリットもある。例えば、Android SDKは「Android Studio.app」の中に内蔵されているので、必要なファイルがバラけなくていい。 こちらからdmgをダウンロードして解凍する。 Android Studio | Android Developers インストールは「Android Studio.app」をアプリケーションフォルダなどに放り込むだけだ。 Android SDK Managerで必要なパッケージをインストール Android Studio.appを起動して適当なプロジェクトを作る。 ツールバーにこのようなアイコンがあるので、クリックしてSDK Managerを起動する。 Android SDK Build-Toolsは最新のものに入れ替えた。 Android 5.0(API 21)はインストールが初期選択。Android 4.4.2(AP...

GCMで「Canonical Registration ID」が取れるようになったら古い「Registration ID」は即無効になるのか?

先ほど、Google Cloud Messaging(以下GCM)で「Canonical Registration ID」(以下canonicalRegId)を発生させる方法を書いた。 琴線探査: GCMで「Canonical Registration ID」を出すには? ところで、canonicalRegIdが取れるようになったら、古い「Registration ID」(以下regId)は即無効になるのだろうか? 試したところ、無効にならない。 ある程度タイムラグがあるのかもしれないと思い、1時間後に無効になっているかどうか試したが無効になっていない。つまり、古いregIdを使ってもメッセージを送れる。 しかし、ドキュメントには「使用していた ID はいずれ動作しなくなる」とあるので、いつかは使えなくなるのだろうけれど、そのタイミングはGoogleのみぞ知るというところだろう。 原文: GCM Advanced Topics | Android Developers 訳文: 4. GCM 上級者向けトピックス - ソフトウェア技術ドキュメントを勝手に翻訳

GCMで「Canonical Registration ID」を出すには?

Google Cloud Messaging(以下GCM)で「Canonical Registration ID」(以下canonicalRegId)を出すにはどうしたらいいのか? ドキュメントによると、「アプリケーションのアップデート」や「バックアップとリストア」などにより、GCMサーバーに同じデバイスで複数のRegistration ID(以下regId)が割り振られる場合があり、その場合にcanonicalRegIdが出るようなんだけど・・・ 原文: GCM Advanced Topics | Android Developers 訳文: 4. GCM 上級者向けトピックス - ソフトウェア技術ドキュメントを勝手に翻訳 「バックアップとリストア」というのはOSのことだろうと思うので簡単に試すことはできない。 一方、開発中に「アプリケーションのアップデート」は何度もしているが、regIdが変わったことはない。アプリをアンインストールして再インストールした時もregIdが変わったことはない。 じゃあ、いつ変わるのか? アプリでGCMRegistrar.unregister()した後、GCMRegistrar.register()するとregIdが変わる。 その後、コンテンツサーバー側で次のようにするとcanonicalRegIdが取れる。 Result result = sender.send(message, regId, 5); String canonicalRegId = result.getCanonicalRegistrationId(); 琴線探査: GCMで「Canonical Registration ID」が取れるようになったら古い「Registration ID」は即無効になるのか?

AndroidのAdMobを使ってるプロジェクトでProGuardを使ってリリースビルドを作る時に出るエラーの対処

AndroidのAdMobを使ってるプロジェクトでProGuardを使ってリリースビルドを作るとこんなエラーが出る。 Proguard returned with error code 1. See console Warning: com.google.ads.m: can't find referenced class com.google.ads.internal.state.AdState Warning: com.google.ads.m: can't find referenced class com.google.ads.internal.state.AdState You should check if you need to specify additional program jars. Warning: there were 2 unresolved references to classes or interfaces. You may need to specify additional library jars (using '-libraryjars'). java.io.IOException: Please correct the above warnings first. at proguard.Initializer.execute(Initializer.java:321) at proguard.ProGuard.initialize(ProGuard.java:211) at proguard.ProGuard.execute(ProGuard.java:86) at proguard.ProGuard.main(ProGuard.java:492) ここ で議論されているように、proguard-project.txtに次の行を加えるとエラーを回避できる。 -dontwarn com.google.ads.** どうやらこの問題の原因は、AdMobがすでにProGuard化済であることによるらしい。 ProGuard problem on Android AdMob SDK 6.2.0 - Google グループ

Nexus7だとダウンロードマネージャでダウンロード中のノーティフィケーションをタップしてもブロードキャストインテントが飛んでこないみたい・・・

ダウンロードマネージャで画像をダウンロードして、ダウンロード中のノーティフィケーションをタップしたらダウンロードマネージャを表示する、このようなBroadcastRecieverをマニフェストに登録している。 @Override public void onReceive(Context context, Intent intent) { // アクションによって処理を変える String action = intent.getAction(); // ダウンロード完了の場合 if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { //何かする } // ノーティフィケーションがクリックされた場合 else if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) { showDownloadManager(context); } } // END onReceive() API Level 17, 16, 15, 14, 10のエミュレータ(全てGoogle APIs仕様)と、Galaxy Tab、Galaxy Nexus、Nexus7でテストした。 その結果、Nexus7だけ、ダウンロード中のノーティフィケーションをタップしてもブロードキャストインテントが飛んでこないということが分かった。 ダウンロード完了のブロードキャストインテントは飛んでくるのに・・・ 機体の調子が悪いのかと思って再起動したものの、変化なし。 原因不明_| ̄|○

AndroidでMockitoを使ってDefaultHttpClientのモックを作る時の注意点

AndroidでMockitoを使ってDefaultHttpClientのモックを作るのにエライ苦労したのでまとめておきたいと思う。 ポイントはMockitoはfinalの付いているメソッドをモックすることはできないということだ。 なので、DefualtHttpClient.execute(HttpUriRequest req)メソッドはfinalなのでmockitoでモックすることができない。 そこで、まだfinalになっていないスーパークラスのAbstractHttpClient(implements HttpClient)を使ってモックする。 実際のテストコードはこんな感じだ。 // サーバーが返すべきJSON String json = "{\"responseCode\":500,\"key\":\"EApBAu\"}"; StringBufferInputStream sbis = new StringBufferInputStream(json); // サーバーが返すべきJSONを返すHttpEntitiyをモック HttpEntity mockHttpEntity = Mockito.mock(HttpEntity.class); Mockito.when(mockHttpEntity.getContent()).thenReturn(sbis); // サーバーが返すHTTPステータスを500と仮定したStatusLineをモック StatusLine mockStatusLine = Mockito.mock(StatusLine.class); Mockito.when(mockStatusLine.getStatusCode()).thenReturn(500); // HttpEntityとStatusLineのモックを返すHttpResponseをモック HttpResponse mockResponse = Mockito.mock(HttpResponse.class); Mockito.when(mockResponse.getStatusLine()).thenReturn(mockStatusLine); Mockito....

Androidでブロードキャストレシーバーやサービスを一時的に無効にするには?

Androidでブロードキャストレシーバーやサービスを一時的に無効にするにはどうしたらいいだろう。 PackageManager にsetComponentEnabledSetting()というメソッドがあるので、例えばこんな風にできる。 /** * 各種コンポーネント(ブロードキャストレシーバーやサービス)を無効・有効にする * * @param cxt コンテキスト * @param cls 無効(有効)にしたいクラス * @param disabled 無効にするかどうか */ public static void disableComponent(Context cxt, Class<?> cls, boolean disabled) { int newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED; if (!disabled) { newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; } ComponentName compName = new ComponentName(cxt, cls); PackageManager pm = cxt.getPackageManager(); pm.setComponentEnabledSetting(compName, newState, PackageManager.DONT_KILL_APP); }

Androidアプリのテスト関連で役に立ったリンクたち

Androidのテスト関連で役に立ったリンクをまとめておこう。 まずはもちろん、本家のこちら。 Testing | Android Developers 本家のページは実例が少なく、少しやっていくとすぐに行き詰まる。本家をひと通り読んだ後にまず行くべきはこちら。ただし、一部の内容はすでに古い。 連載インデックス「Androidアプリ開発テスト入門」 - @IT この連載は何人かの方によって書かれているけれど、始めの方の記事を書いておられるアンドロイドテスト部、部長の宮田友美氏が中心となって書かれたっぽい本もつい最近出た。 Amazon.co.jp: Androidアプリテスト技法: 生路 茂太, 井芹 洋輝, 神原 健一, 長谷川 孝二, 松木 晋祐, 宮田 友美, 吉澤 毅: 本 前半はAndroidに限らない一般的なテスト技法の話で、Androidに関しては後半のみ。全てAndroidが良かったなあと思うけど、世界的に見てもAndroidのテスト関連の書籍は珍しいようなので、日本でこういった書籍が出たということは大いに意義があると思う。 モック関連としてmockitoの参考。 モヒートの飲み方 - Just posted a blog Androidでmockitoを使ってActivityをテストする | アライドアーキテクツ エンジニアブログ テストそのものが分かってきたらこちら。 第5回 ゼロから始める継続的なAndroidアプリケーション開発のしくみ:mixiエンジニアがおくるソーシャルアプリ開発実践講座|gihyo.jp … 技術評論社 今のところはこんな感じ。

AndroidでAdmob用のデバイスIDを取得するには?

AndroidでAdmobを使う時に、デバッグ時のインプレッションをカウントしないようにするためには「ads:testDevices」プロパティーにデバイスIDをセットすればいいけれど、そのデバイスIDを取得するにはどうしたらいいのか? まず、実機を接続してAdmobが表示されるActivityをデバッグ実行する。 LogCatを「All messages(no filters)」にする。 「addTestDevices」でフィルターする。 すると「To get test ads on this device, call adRequest.addTestDevice("XXXXXX");」という行が見つかる。この「XXXXXX」の部分がデバイスIDだ。 なので、このIDをこんな感じで加えていけばいい。 ads:testDevices="TEST_EMULATOR, XXXXXX_1, XXXXXX_2, XXXXXX_?・・・"

Androidでテキストとアイコンがあるボタンを作るには?

イメージ
Androidでテキストとアイコンがあるボタンを作るにはどうしたらいいだろう? <Button android:id="@+id/btnKeyReissue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_blue" android:drawableLeft="@drawable/key_reissue" android:onClick="onClickKeyReissue" android:padding="8sp" android:text="再発行" android:textColor="#FFFFFF" android:textSize="18sp" android:textStyle="bold" android:typeface="sans" /> drawableLeftにアイコンの画像をセットすればいい。しかし、この方法ではlayout_widthが伸びた時に問題が出てくる。 アイコンがボタンの左端の方に寄ってしまうのだ。文字列のすぐ左横にアイコンを表示して全体としてセンタリングされるのが望む表示なのだけど。。。 何とかなりそうなプロパティーとしてdrawableStart(API Level 17以上)があるのだけど、これに画像をセットしても表示されなかった。 TextView | Android Developers まあ、これで表示されたとしてもAPI Level 17以上では使いようがないのだけど。さて、どうしたものか。 Androidでは表示オブジェクトをクリッカブルにするのに、必ずしもButtonを使う必要はない。LinearLayoutだってクリッカブルにはできる。そこで、こうした。 <LinearLayout android:id=...

Androidのダウンロードマネージャで画像をダウンロードして完了を通知し、その通知をタップしたらその画像をギャラリーで開くには?

Androidのダウンロードマネージャで画像をダウンロードして完了を通知して、その通知をタップしたらその画像をギャラリーで開くにはどうしたらいいだろう? この一連の流れを実現するのに色々と紆余曲折したのでまとめておこうと思う。 Androidのダウンロードマネージャで画像のダウンロードが完了すると、完了通知がブロードキャストインテントで飛んでくるので、これをすかさずキャッチ! DownloadManagerBroadcastReceiverクラスの抜粋 /* * ブロードキャスト受信時 * * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) */ @Override public void onReceive(Context context, Intent intent) { //アクションによって処理を変える String action = intent.getAction(); //ダウンロード完了の場合 if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { //ダウンロードキューのID long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); //ダウンロードマネージャから各種情報を取得 DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(id); DownloadManager dlman = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); Cursor cur = dlman.query(query); if (!cur.moveToFirst()) { Log.v(TAG, "ダウンロードマネージャでダウンロードがキャンセルされた...

AndroidではとりあえずExternalStoragePublicDirectoryにファイル保存しとけば大丈夫?

Androidのダウンロードマネージャで画像をダウンロードする時の保存先の話。 例えば、このようにしてギャラリーなどで開けるようにパブリックな領域に保存するパスを得るとする。 String basePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath(); ここで「ExternalStorage」というところが気になって・・・具体的にはどういったファイルパスに保存するのか? 例えば、Nexus7などは外部記憶、つまりSDカードを差す場所など元から無いわけで。この場合は? /storage/emulated/0/Pictures/ なるほど。外部記憶を内部的にエミュレートして、結局、内部記憶に保存するのね。 逆に例えば、Galaxy TabなどはSDカードを挿す場所があるけど、挿してる場合と挿してない場合ではどう変わるのか? SDカードあり /mnt/sdcard/Pictures/ SDカードなし /mnt/sdcard/Pictures/ つまり、SDカードを挿していようと挿していまいと同じパスに保存することになってた。 ちなみにSDカードを挿すと /mnt/sdcard/external_sd にSDカードがマウントされた。sdcardの配下に外部SDカードをマウントするという(^^); というわけで、AndroidではとりあえずExternalStoragePublicDirectoryにファイル保存しとけば大丈夫そうだ。

AndroidでMediaScannerにACTION_MEDIA_SCANNER_SCAN_FILEを投げてもACTION_MEDIA_SCANNER_FINISHEDを投げ返してくれないのですが(^^);

BroadcastRecieverでMediaScannerConnection.scanFile()を呼べない ので、MediaScannerサービスにブロードキャストでメディアスキャンをリクエストした。 context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); スキャン完了次第、Intent.ACTION_MEDIA_SCANNER_FINISHEDがブロードキャストされるだろうと思ってこんなBroadcastReceiverクラスを書く。 public class MediaScannerBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)) { Log.v(getTag(), "メディアスキャナー終了"); } } // END onReceive() } // END class さらに、このクラスを使えるようにするために、AndroidManifest.xmlにこのような定義を追加した。(「file」のdataスキームを追加することがポイント) <!-- メディアスキャナーからのブロードキャストインテントを受信するレシーバ --> <receiver android:name=".MediaScannerBroadcastReceiver" > <intent-filter> <data android:scheme="file" /> <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" /> ...

MediaScannerConnection.scanFile()はBroadcastRecieverから呼び出せない件

DownloadManagerで画像をダウンロードした後、BroadcastRecieverで完了通知を受け取ってすぐにコンテンツURI(content://)を得るために、MediaScannerConnection.scanFile()を呼んだらエラーになる。 01-26 13:28:00.159: E/AndroidRuntime(11034): FATAL EXCEPTION: main 01-26 13:28:00.159: E/AndroidRuntime(11034): java.lang.RuntimeException: Unable to start receiver com.example.DownloadManagerBroadcastReceiver: android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to bind to services BroadcastRecieverからサービスを呼び出すことは許されていない、とな。実際、そのようだ。 BroadcastReceiver | Android Developers In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service. その代わり、サービスに何かさせたいならIntentを使え!と。 そうだ。そうだったんだよ。これは前にも試してたんだ。

GCMの端末登録でAPI Level 15以上ならGoogleアカウントは必須ではないというのは本当か?

Google Cloud Messaging(GCM)のドキュメントにこんな事が書いてある。 GCM Architectural Overview | Android Developers … It requires devices running Android 2.2 or higher that also have the Google Play Store application installed, or or an emulator running Android 2.2 with Google APIs. (GCMは2.2以降でかつGoogle Play Storeがインストールされている必要があります。もしくは、2.2以降のGoogle APIがサポートされているエミュレーターが必要です。) … It uses an existing connection for Google services. For pre-3.0 devices, this requires users to set up their Google account on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher. (GCMはすでにあるGoogleサービスのコネクションを使用します。3.0以前のデバイスではGoogleアカウントをセットアップしておく必要があります。4.0.4以降のデバイスではGoogleアカウントは必須ではありません。) … かなり混乱した。API Levelでひとつひとつ分解すると・・・ 実機でGCMを動作させるにはAPI Level 8以降が必要 エミュでGCMを動作させるにはAPI Level 8以降でGoogle APIサポートが必要 API Level 8, 10, 11, 12, 13, 14では予めGoogleアカウントを端末に追加しておく必要がある API Level 15, 16, 17ではGoogleアカウントは必要ない ここで、特に4に注目した。API Level 15以上ならGoogleアカウントは必須ではないというのは本当か? ...