読者です 読者をやめる 読者になる 読者になる

どくぴーの備忘録

真面目なことを書こうとする情報系大学生カッコカリのブログ。いつ投げ捨てられるのかは不明

#wakate2016 第49回情報科学若手の会に参加してきました

TL;DR

エモかった

去年の

e10dokup.hateblo.jp

何をしてたの

9/17 - 9/19の間,伊東市の山喜旅館にて行われる情報科学若手の会に参加してきました.

個人的には特に話すネタを一切用意していなかったのですが,前日に偶然ポケモンGO Plusを入手することに成功してしまった(発売日がその日であることすら知らなかった)ため,とりあえずおもむろにAndroidからBLEの中身を見るアプリを使ってどんなサービスがあるんかなー,どんなふうに動いてるんかなーって感じのLTをしてきました.模造品を作らせない努力を垣間見ました.

セッション

去年とはまた違った方向に多岐にわたった分野の発表があった気がしました

  • 機械学習
  • HCI
  • Java 8の ' String.format() ' の話
  • ロボット(ロボカップとかおっちゃんに使ってもらう話とか)
  • 通信系(LoRa)
  • 小型ドローン(Phenox)
  • 電子決済と個人間送金
  • 株と為替の話
  • キャリア
  • 蚊をRESTfulに殺す
  • 海外で就活とかする話

などなど,本当に多岐にわたる発表があったのですが,何よりキャリアに関する発表が エモかった です.言葉では表せないくらいのいい話でとにかく エモかった です.最高.

あとHCI界隈はPV(?)に凄いアゲ↑アゲ↑なBGMを使ってて,すごいクラウドファウンディングな感じがしました(実際そうではない)

交流イベント

去年はパスタを使ってマシュマロを出来る限り高い高度に持ち上げるマシュマロ・チャレンジだったのですが,今年は何が起きたのかLANケーブル作成競争でした.しかもクイズに答えられないと部材も機材も手に入らないという.難易度の高い問題を引き続けるあまり幹事の方から「好きな数字の問題えらんでいいよ!w」的なご容赦が飛んできましたがなんとかLANケーブルは3本くらい作れて,問題は全部消化しました.一杯回答スルーした気がするけど気にしてはいけない.

ちなみに勝者の商品の一部ですが,らん(?)とけーぶる(?)でした

f:id:e10dokup:20160917220719j:plain

ナイトセッション

ここに居ないと知らないような話が大量にあって,なんというか エモさのラスボス みたいな感じでした.ドローン飛ばしたのを見てたり,本当にここでしか聞けないレベルの話を聞いたり,色々とヤバい(すごい)という記憶しか残っておりませんが,本当に楽しかったです.

他に何をしてたのかというと,「君の名は。」の話をしてたりピングーの話でひとしきり笑ってたりロボカップでつかうロボットを見せていただいたりしました.ついでにルータ芸人 ( id;puhitaku )の撮影会が執り行われました

この時撮影した写真は見事クロージングにて使われました.やったね(?)

無事に帰ってきて

実は今年は「んおおおおお行くかなぁどうしようかなぁ」ってなっていたのですが,行ってよかったなぁって思います.毎年違うエモさが襲い掛かってきて最高って感じなのでこれからも行けるのであればぜひ行きたいなぁ.って思いました.

最後になりましたが,幹事の方々,本当にありがとうございました.お疲れ様でした!!!! :bow: :bow:

ポートフォリオサイトを作った

すごい今更感しか無いですが,ポートフォリオサイトを作りました.

e10dokup's portfolio

なんで作ろうと思ったの

ちなみに,研究室の先生に見られた時の反応は

「えっ?なんでこんな時期に?」 です.当たり前ですよね.

やってみたこと

  • デザインよくわからないけどbootstrapは使いたくなかったのでMaterial Design Lightの導入
  • ムダにアカウントのアイコンにアニメーションをぶっこんでみる
  • アイコン部分とかを独自に書いてみたりしたのでその部分をレスポンシブっぽく(というか画面幅が狭くなったら横並びを縦並びになるように)した
  • gulp.jsを使ってみる
    • よくわからないなりに便利でした

ちなみに,画面幅対応はこの本を参考にしてみたり

gulp.jsの使い方はLIG.incの記事を参考にしてみたりしてました

liginc.co.jp

ちなみにgithub pages上にデプロイしてます.簡単お手軽って感じで楽ちんでした.

感想

  • 難しい
    • 純粋に勉強しないとなと思いました
  • なんだかんだポートフォリオサイトが完成すると嬉しい気分になる
    • ちゃんと更新していかないと行けない

わからないなりに楽しめて,勉強になったのできっかけ作りとしては良かったかなぁって思っています.もっと頑張っていこう💪

kosen10s LTに初参加して考えたこと

大阪に来たので初参加してきました.kosen10s LT.

kosen10s.doorkeeper.jp

なにげにしれっとkosen10s slackには居たり,kosen10s有志で「大阪会場もあるのに」わざわざSPAJAMの東京A予選に参加したりしてはいたんですけど,LT会に関してはお金と日程的な関係で断念し続けてました.TOEIC前日に参加とか無理でしょ(白目)

何話したの

僕が個人として話したのは,kosen10s LT恒例らしい自己紹介と近況LTと,後おまけとしてAndroidでBLEビーコンで遊ぶ記事を書きました.SPAJAMで作ったアプリで一体何してたのか,って感じの内容です.

www.slideshare.net

一応スライドはあるにはあるんですがほとんどコード見ながら話をしていたのでこのスライドからじゃ一体何の話なのか全くわからない感じになっています.申し訳

皆のお話

やはり 「ぶっ飛んでんな」 というのが感想でした.カップル向けアプリを紹介したり,(幼少の)教育のお話だったり,(授業に使う)婚姻届持ってきたり,いつもどおりのルータ芸だったり,シェル芸だったり,E/D問題だったり,多岐に渡ってんなぁ…っていうすごい小並感レベルですが感心ばかりの内容でした.同じ同期の高専生っていっても本当にいろんな人種が居るんだなぁってつくづく思い知らされる感じです.

買い出し

僭越ながら買い出しに行ってきました.最初は「絶対おにぎりとサンドイッチ買うぞ」みたいな感じだったのですが,気づいたらお菓子とジュースしか買っていませんでした.なんかくっそ時間がかかっていたのは思ったより会場からスーパーが遠かったのとジュースとお菓子が別フロアで別々に会計済ませないといけなかったのと行きにうなすけくんがブランコ警察していたからです,うなすけくん本人曰く 「あれはΔtだから!!」 とのことですが多分あれで3分くらい食ってました.食った時間以上に面白かったので多分大丈夫でしょう(?)

kosen10sに思うこと

一言でいうと, 高専特有のぬるま湯の様な居心地と失われた語彙力 って感じです.別に皆一緒の何らかの目標があるわけでも何でもなく,個々が好きなときに好きな話題とイベントを持ってくる.そこにたまたま同調した人がやいのやいのしだす,そんな集団じゃないのかなぁ,って思います.僕は意識が低いので「皆でなんかでっかいことするチーム作ろうぜ」みたいな雰囲気よりはその場で自然発火して各位のたまたまの反応で鎮火したり爆発したりするそういう雰囲気が大好きです.語彙力は完全に消え去ってます.大体文字が書いてあるemojiで対応したり,とりあえず人物っぽいemojiの左右に筋肉をつけたりするあたり察しがつくかと思います.

f:id:e10dokup:20160509002237p:plain

僕の印象としてはそんな感じなんです.ただこの妙な(いい意味の)グダグダ感が好きなんです.高専に懐かしみを感じたり…ってわけでは無いんですが,ただでさえ全国的に少ない高専の同期がどんな感じでいまほげほげしてるんだろうか,っていうゆるーい繋がりでダラダラ会話をしていて,時々妙な刺激を受けてなんかよくわからないけどモチベーションが湧いてくる,そういうのもまたいいんじゃないかなって思います.ズブズブな関係になると流石に…って感じにはなってしまうとは思うんですけどその時はその時なんじゃないかな,って.あまりに適当ですけど

最後に

なんか 「おうお前何悟ったこと言ってるんだよ」 みたいな感じになっていますが, 深夜テンションなだけ ですすいません.多分僕はkosen10s界隈の中では意識低い部類に入ってると思うのでもっと語彙力の無い感じでなんかあったらお手伝い〜みたいな感じでやっていこうと思います.ありがとうございました

高専カンファレンスlolに行ってきた.発表もしてきた

1年ぶりだと思ってたんですが,昨年度の高専祭に行っていたので,半年ぶりに明石高専に帰ってきました.これです

kosenconf.me

100に続いて,三回目の高専カンファレンスです.今回は一般発表枠の「トリ」でした.つらかった.ちなみに前回の100カンファの記事はこちら.

e10dokup.hateblo.jp

ちなみに,今回の発表内容はこちらです.前回と全く趣向が別ですね()

www.slideshare.net

なんでこんな発表をしてしまったのか

2月にTwitterでアンケートを取ってみたのですが,図ったように「説教と自分語り」がトップでした.

というわけで作った結果がアレになったのですが…

「完全にブーメランじゃねぇか」と.まぁそうですよね.なんでこんな発表してしまったんだと.

どっちかというと僕があの時話した内容というのはすでに「やらかした」「反省したい」「後悔している」点なので,これからの自分の反面教師にしたいと思って作ったのが1つです.ですが別にこれを今後背負って超意識高い人間になろうとかそういう気持ちは一切ありません

結局最後のオチがいろいろ持って行ったので「こいつ何言ってたんだっけ」ってなっている方も多いと思いますがつまるところ「自分のことは自分で考えられる分は考えよう」って話です.後は不言実行の筋肉をつけようなってだけです💪

僕はできてないのでダラダラ頑張っていこうと思っています.

僕のブログとTwitterが「神大 クソメガネ」で検索すると1番上に出てくるのをいいことにスライドに書いたらフォロワーが27人くらいガッツリ増えました.びっくりです.普段はもっと語彙力のない感じで生きてるので優しくしてください.

他の発表

今回は一般発表が結構専門に振れた内容でもない話が多かった(研究,教職,就活とか)ので,LTが結構話の内容的にも振れ幅が大きかったなぁ,知らない話多かったなぁって感じでした.カレーメシ先輩( id:nwpct1 )の発表が見るたびに洗練されているの見てすごいなーって小並感もびっくりの感想出してました.

あとブース発表が新規にやってました.GitHubのブースで大量にステッカーを配布してたり,カップル向けアプリを(作ったわけではないけど)紹介していたり,ルータを走らせたり,いろいろふっとんだことしてたなぁと.走るルータの動画はTwitterで検索すれば多分すぐ出てくるので探してみてください.

面白かったのでぜひ次の会でもやってたらなぁ…って思ってました.ブース発表担当の運営の人お疲れ様です.

最後に

100につづいての高専カンファですが,100とは違った面白さがあってとても良かったなぁと思います.しばらく会ってなかった人に会ったし,Twitterの中でアイコンしか知らない人に会ったり.個人的には発表がウケたのでびっくらぽんです.自虐ネタってやっぱりウケるんですかね.slideshareに上げたスライドは一部ページを削除してあるのですが,その付近で明石高専生と思しき高専生が「あっ…」って顔をしていました.黒歴史を生み出して本当にごめんなさい()

あと,スライドのデザインに関してちょっと言及をもらったので嬉しかったです.もっと綺麗なスライド作れるように意識していこうと思います.デザインとかほんとうに難しい.

本当に楽しかったのでこれからも発表の機会があればなんか発表できたらな〜〜〜〜〜〜〜,なんて考えています.今回のアレは個人的には意識な内容に振ったので「あぁ〜〜〜〜つらい!意識高く見られそうでつらい!」って感じだったのでもっと意識低い内容で出したいなぁ,と

運営の方々,発表を聞いていただいた方々,本当にありがとうございました!お疲れ様でした!

おまけ

kosen10sという,「2010年度入学の高専生がやんややんやする会」のLT会が翌日にありました.その話はまた別ということで…,ちなみに2日連続で飲みに行ったのでその翌日はなんか予想以上に気だるくて大変なことになりました.飲み会は計画的に.

神戸大に編入して1年がたった

なっちゃんid:marin72_com )の記事の便乗です.すいませんすいません.

marin72.hatenablog.com

なんかいろいろあったような気もしますが,神戸大学工学部情報知能工学科に編入して1年がたち,3年生が終わっていました.ちなみにもう一度3年生をやるかどうかはまだ判明しておりません.

編入してからの話

あくまで「神戸大学工学部情報知能工学科」の話です.他学科については分かりかねるので,ご了承ください

単位認定

ここ重要.…って言いたいんですが,弊学弊学部弊学科に関してだけは「認定単位数固定」です.一応シラバス等の提出義務はありますが,認定単位に編入前での履修科目を割り当てるための判断基準のためだと思います.僕の代は69単位固定で,

  • 教養原論は必要最低限を認定.そのため3年生での履修は不可
  • 専門科目は1,2年生の開講科目から一部を認定.必修科目が一部認定不可

という内訳でした.情報系学科以外の学科からの編入でもそれは変わりませんでした.来年度からはクォーター制とかいうのが始まり,単位数がややこしくなるのでどうなるかは確証がありません.

ここで重要なのが「認定単位は一部申し立てによる変更が可能」ということです.学期開始から多少の猶予が認められたので,僕たちは編入生の先輩に講義の雰囲気を伺って「この科目に認定を切り替えて,この科目を履修しよう」ということをしていました.

履修科目決定

正直,ここが一番悩ましかったです.進級要件,卒業要件と照らしあわせて履修科目を決定します.具体的な値は抜きとして

  • 数理系科目
  • 専門基礎系科目
  • 計算機科学系科目
  • 情報科学系科目
  • システム科学系科目

の5分野から選択科目を決定するのですが,それぞれに進級要件がしかれていて,割りかし選択肢はありません.さらに「CAP」という,年間履修単位数上限があり,保険に各分野に1科目余分に履修しておくということを考えるとすぐに上限に引っかかります.学生便覧とひたすらにらめっこをして編入生と話し合い,計算しながら履修科目を決定することになると思います.

ちなみに履修単位を把握するためのツールとしてこんなのがあるそうです.後期も年明けになって内部生の人に教えてもらいました.噂によるとどうやら教員謹製とかなんとか…

留年防止サービス

専門科目の講義

高専の復習になる部分はやはりそれなりにあります.分野としては

  • プログラミング,ソフトウェア工学と言った計算機科学
  • 画像工学,通信工学等の情報科学
  • 古典制御,近代制御といったシステム科学,ロボット工学

という感じになるので,電気系だった,情報系だった,という高専生であれば,少なくとも復習になる科目はありますが,やはり新しい科目も勉強します.複数科目でフーリエ変換ニューラルネットワークが同時並行で出てきたりします.

不思議な事に,ちゃんと出席してちゃんと課題を出していればテストで0点をとっても可が返ってくるなんてことがあるので,ちゃんと出席してちゃんと期日までに課題を出すことを心がけましょう.

専門科目の演習,実験

前期に演習,実験があります.演習ではC(OpenMP)とJava(Swing)を,実験では回路シミュレーションやOPアンプとPICによるマイコンプログラミングといった内容でした.ちゃんと高専での基礎ができていればよほどでないかぎり無双できます.特にレポートの書き方とかは,高専での実験レポート,卒論でメッタメタにされた過去を思い浮かべながらゴリゴリかけば周りよりやけにページ数が多いレポートになったりします.そうでなくてもとりあえずハンダゴテとオシロスコープが満足に使えればなんとかなると思います.

後期になると幾つかのグループ別れて所属することになります.僕の代では

  • PICでロボットを作るといった実験的なグループ
  • 機械学習や画像認識をする演習的なグループ(複数
  • WebアプリやAndroidアプリを作るグループ

などがありました.僕は一番下のグループに入ってペアで作業するところを一人でもそもそ作業していました.ぼっちが加速するぅぅぅ.

ちなみにこの活動による産物がすらこん!です.

e10dokup.hateblo.jp

研究室配属

3年生中には一切研究室配属は行われません.が,どうにも3年生での成績(GPかな?)で優先配属順が決まるようです.編入生には別の計算式になるようですが,何もかも噂でしか無いのでとりあえず「できるだけ多くの科目でいい成績を取ろう」くらいしかいえません….

内部生に友達はできるのか

怪しいです.編入生と「みんなで頑張って進級しような!」って雰囲気作りが真っ先です(?)

僕はサークル活動は一切してない(というかやろうと思ったけどバイトと被ってやめた)ので,そういう活動をしていればまた違ったのかなと思いますが,後期にもなると実験,演習等でなんだかんだ内部生にも話す人は出来ます.きっと.…僕は一応出来ましたよ?

あと,微妙に関係ないですが最初のうちは編入生は「得体が知れない=もしかしてガチ勢なのでは」と思われる(らしい)です.すぐにボロ出ますけどね.更にはTwitterで荒ぶってたら余裕でアカウントが特定されます.特定したら是非フォローして欲しいです.よろしくお願いします

アルバイト

学業とのトレードオフですが,バイトは出来ます.というか掛け持ちくらいは出来ます.僕は前期は平日の放課後を全日使っていましたが,今はだいぶ絞っています.せっかく専門的な学習をしているのだから,専門的なバイトをして学校の外でも力をつけても良いのではないのかなーと思ったり.ただ,本分はやはり学業なので,おろそかにすることがないように….

課外活動

長期休みの期間が長いことや,前期に頑張って取れるだけ履修しておけば後期は多少暇ができることもあって,高専本科に居た頃と比べると課外活動がしやすくなっている感じはあります.僕の課外活動を振り返ってみると

と,なんだかんだコンスタントに課外活動をしています.アルバイトもそうですが,課外活動を通して学校の外でも力をつけれるいい機会だと思って,精力的に参加していました.ただ,繰り返しですが,本分はやはり学業です.

以上,まとめるとこんな感じになりますが,なんだかんだで神戸大学に編入して楽しかったなと思います.高専では会えなかったタイプの人(ウェイ系なのかどうなのかは別として)に会えたりしますし,何より雰囲気が違います.ですがいい意味で大学に編入しても「高専生である」という感覚は消えないなぁと思っています.高専カンファなんかにも出たりしてますしね.

ただ,何処の大学でも単位貧乏に陥るのはどうやら必然っぽいので,勉強大変だったなーと思っていますし,課外活動,アルバイトと組み合わせて勉強を頑張ってほしいなーとも思っています.

所謂「エンジニア逆求人系」イベントを開催している3社のイベントにいろいろあってここ二ヶ月で全部参加した話

1/17に,ジースタイラス社開催の「ITエンジニアプレミア逆求人」というイベントがあったので参加しました.

どんなイベント

www.studenthunting.com

所謂「逆求人系」イベントという,企業との面談を行えるイベント.最近増えてきた気がします.マイナビとかでよくある企業の説明会というと,企業がブースを構えていて,学生が行きたいとこに行く.という形を取ると思うのですが,学生がプレゼン資料とかを構えて企業の側が「お話したい」という学生をその中で回る,という意味で「逆」ということだと思います.

今回参加した「プレミア逆求人」は,同社が今年度中に開催した各イベントで全体的に良い評価を受けた学生が参加できるとかなんとかだそうです.ちなみに誰かが言った「プ求人」という略称が妙に気に入ってるのでこれ以降使っていきます.

どんな話するの

学生次第なところがありますが,就活とかそんな話が主と思いきや.逆求人系イベントはエンジニアの方々(CTOの方の場合もある)が来てくれるので,技術の話や,果てはキャリア等人生相談までできる,なんてこともあります.と言うかソッチのほうが長くなったりします.自己PRのスライドからフィードバックをもらったりもします.多分.

感想

あまり就活就活した雰囲気がなく,自身としても就活就活したものを用意してなかったので,企業さん自体のお話以外でも技術に関する雑談や人生相談がはかどりました.後述しますが自分としては逆求人系イベントには就活と同じくらい「一度会ってみたかった企業さんに会える」ことに重点をおいているので ,個人的にはとても良かったのかなと思います.

タイトルに戻る

「エンジニア逆求人系」イベントを開催している企業さんは,今回のプ求人のジースタイラス社以外に,サポーターズ社やキャリアセレクトという就活支援サイトを運営しているローカルイノベーション社等あります.僕はなんやかんやあって,その3社の開催しているイベントに参加しました.どうやら二ヶ月間の間でだそうです..

なんか違ったの

微妙には違います.良し悪しとか言う点ではないので大丈夫です.イベントによっていらっしゃる企業さんの範囲が変わったりするのもありますが…

  • ジースタイラス社:Skype等で通話によるプロフィールやプレゼン資料の添削がある.企業さんからのアクションが「メッセージ」という形でくる.お話した企業からフィードバックが仕組みとしてある.開催しているイベントは(見える限りは)説明会やセミナー.
  • サポーターズ社:プロフィールを読んだ企業から「スカウト」という形で直接面談やイベント等のお誘いが来たりする.更新頻度が多い.フィードバックは仕組みとしては無い.学校に来てセミナー等のイベントをやったりしていることもある.京都にオフィスがあるので関西でイベントが開かれることが多め
  • ローカルイノベーション社:キャリアアドバイザーにプロフィール等の添削をしてもらえる.フィードバックが仕組みとしてある.開催しているイベントは(見える限りは)説明会とかセミナー.企業さんからのアクションは特に無いがイベントリストにはセミナーに加えハッカソンなども.

と,このような感じです.ちなみにどのイベントを選択しても交通費は出してもらえます.交通費の算出方法は違いますが….ジースタイラス社の「逆求人のしおみさん」などが高専界隈でずば抜けて有名なので,ジースタイラス社のイベントに出ると高専生が多いような気がします.

全部参加したらいいの?

全部参加すると少なくともダブる企業さんが出るので,「あっ,お久しぶりです」とかそんなやり取りをする回数が増えてきます.時期が合ってるものを選ぶという考えでも十分ありかなと思います.

プ求人に出て思ったこと

多少は必要ですが,就活という意思でガチガチに固めていく必要なんて全然ないなと思いました.お話するのはエンジニアの方,ということもあるので,技術の話もしたりするので,すごい好きな話をできるというのもあると思います.企業さんを知る,考えるきっかけづくりというスタンスになるとすごい気持ちを楽にして臨めるかな…?また,企業の方との会話もそうですが他の参加者の学生さんとの会話からも刺激をえられるので,そういう意味でも良いイベントかなと思います.ただ,連続して出ると話すネタがなくなったりするし,単純に疲れる(1回の参加でも結構疲れる)ので気をつけましょう.

終わり.

Retrofit 2 + Google Maps API v2 for Android + Google Places API Web Serviceを使って指定座標付近のスポットを検索する

PlacePickerというものがある

https://developers.google.com/places/android-api/placepicker?hl=ja

PlacePicker には、地理的住所やローカル ビジネスに一致するプレイスを含むインタラクティブなマップや近隣のプレイスの一覧を表示する UI ダイアログが用意されています。ユーザーがプレイスを選択すると、アプリでそのプレイスの詳細を取得できます。

ということで,intentで専用のダイアログに飛ばして,その選択結果(1件のみ)を forActivityResult() で受け取って処理したりするのだが,わざわざ検索で別の画面に飛ばして選択させて帰ってこさせるのがなんか回りくどいと思ったのと,一度に複数件アプリ側のMap上にスポットのピンを立てたい!ということで,直接WebAPIの方を叩けば周辺nメートルのスポットを検索できたりするので,今回試してみることに

まずはじめに

兎にも角にも.Google Maps API v2 for AndroidGoogle Places API Web ServiceをGoogle Developer Consoleで有効にしましょう.Google Maps APIにはAndroidキーが,Google Places APIには(恐らく直接RESTでAPIを叩くため)ブラウザキーが必要です.

有効化ができたら.app側のbuild.gradleのdependenciesに次の記述を追加して,okhttpとretrofit,google play servicesを導入します.

dependencies {
    compile "com.squareup.okhttp:okhttp:2.4.0"
    compile "com.squareup.okhttp:okhttp-urlconnection:2.4.0"

    compile "com.squareup.retrofit:retrofit:2.0.0-beta2"
    compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

    compile 'com.google.android.gms:play-services:8.1.0'
}

その後,AndroidManifest.xmlパーミッションを追加します

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

また,Google Maps APIを使うためのmeta-dataをapplicationタグ内に追加したりします

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

Responseの受け皿となるPOJOクラスを用意する

Google Places API Web Serviceのレスポンス例は公式サイトで確認できます.

developers.google.com

ということで,これを受け取るためのPOJOクラスを作成します.今回は,後述しますがGsonConverterを使うので,各クラスのメンバには"m"はつけず,レスポンスのJSONの属性名に合わせます.例えば,nameであれば,mNameとするのではなく,nameのままで記述します.

まず,一番深いところにあるLocation.java

public class Location {
    private static final String TAG = Location.class.getSimpleName();
    private final Location self = this;

    private double lat;
    private double lng;

    public Location(double lat, double lng) {
        this.lat = lat;
        this.lng = lng;
    }

    public double getLat() {
        return lat;
    }

    public void setLat(double lat) {
        this.lat = lat;
    }

    public double getLng() {
        return lng;
    }

    public void setLng(double lng) {
        this.lng = lng;
    }
}

続いて,その外側にあるGeometory.java

public class Geometry {
    private static final String TAG = Geometry.class.getSimpleName();
    private final Geometry self = this;

    private Location location;

    public Geometry(Location location) {
        this.location = location;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }
}

更に外側にあるResult.java

public class Result {
    private static final String TAG = Result.class.getSimpleName();
    private final Result self = this;

    private Geometry geometry;
    private String icon;
    private String id;
    private String name;
    private String place_id;
    private String rating;
    private String reference;
    private String[] types;
    private String vicinity;

    public Result(Geometry geometry, String icon, String id, String name, String place_id, String rating, String reference, String[] types, String vicinity) {
        this.geometry = geometry;
        this.icon = icon;
        this.id = id;
        this.name = name;
        this.place_id = place_id;
        this.rating = rating;
        this.reference = reference;
        this.types = types;
        this.vicinity = vicinity;
    }

    public Geometry getGeometry() {
        return geometry;
    }

    public void setGeometry(Geometry geometry) {
        this.geometry = geometry;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPlace_id() {
        return place_id;
    }

    public void setPlace_id(String place_id) {
        this.place_id = place_id;
    }

    public String getRating() {
        return rating;
    }

    public void setRating(String rating) {
        this.rating = rating;
    }

    public String getReference() {
        return reference;
    }

    public void setReference(String reference) {
        this.reference = reference;
    }

    public String[] getTypes() {
        return types;
    }

    public void setTypes(String[] types) {
        this.types = types;
    }

    public String getVicinity() {
        return vicinity;
    }

    public void setVicinity(String vicinity) {
        this.vicinity = vicinity;
    }
}

最後に,一番外側のResponse.java

public class Response {
    private static final String TAG = Response.class.getSimpleName();
    private final Response self = this;

    private List<Result> results;

    public Response(List<Result> results) {
        this.results = results;
    }

    public List<Result> getResults() {
        return results;
    }

    public void setResults(List<Result> results) {
        this.results = results;
    }
}

このように記述することで,ネストしているJSONレスポンスでもGsonConverterでうまいことパースしてくれるようになります.

RetrofitでAPIを叩く仕組みを作る

まず,使うAPIを記述したServiceのInterfaceを記述します.

/**
 * URL Sample:
 * https://maps.googleapis.com/maps/api/place/search/json
 * ?types=cafe
 * &location=37.787930,-122.4074990
 * &radius=5000
 * &sensor=false
 * &key=YOUR_API_KEY
 */
public interface PlaceApiService {
    @Headers("Accept-Language: ja")
    @GET("/maps/api/place/search/json")
    Call<Response> requestPlaces(@Query("types") String types,
                                     @Query("location") String location,
                                     @Query("radius") String radius,
                                     @Query("sensor") String sensor,
                                     @Query("key") String key);
}

そして,このServiceを利用してPlaces APIにアクセスするためのクラスを用意します.

public class PlacesApiHelper {
    private static final String TAG = PlacesApiHelper.class.getSimpleName();
    private final PlacesApiHelper self = this;

    private Context mContext;

    public PlacesApiHelper(Context context) {
        mContext = context;
    }

    public void requestPlaces(String types, LatLng latLng, int radius, Callback<Response> callback) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(mContext.getString(R.string.places_api_url))
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        PlaceApiService service = retrofit.create(PlaceApiService.class);

        Call<Response> call = service.requestPlaces(types,
                String.valueOf(latLng.latitude) + "," + String.valueOf(latLng.longitude),
                String.valueOf(radius),
                "false",
                mContext.getString(R.string.google_maps_key_browser));
        call.enqueue(callback);
    }
}

R.string.places_api_url にはPlaces APIのURL(https://maps.googleapis.com)を,R.string.google_maps_key_browser にはDeveloper Consoleで取得したブラウザキーを記述しておきましょう.

ActivityにGoogle Mapを表示させ,ボタンをクリックしたらスポット検索させるようにする.

次のようなLayoutを用意します. SupportMapFragment を利用します.EditTextがありますが今回は使わなかったりします.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_search_word"
        android:layout_toStartOf="@+id/btn_search"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Search"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:id="@+id/btn_search"/>

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/map"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_below="@+id/edit_search_word"
              android:layout_marginTop="5dp"
              android:name="com.google.android.gms.maps.SupportMapFragment"/>

</RelativeLayout>

そしてMainActivityを記述します.今回は始点の座標は決め打ちです.

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
    private static final String TAG = PasteActivity.class.getSimpleName();
    private final PasteActivity self = this;

    EditText mSearchEdit;
    Button mSearchButton;

    PlacesApiHelper mHelper;

    private GoogleMap mGoogleMap;
    private SupportMapFragment mMapFragment;
    private LatLng mCurrentLatLng;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSearchEdit = (EditText) findViewById(R.id.edit_search_word);
        mSearchButton = (Button) findViewById(R.id.btn_search);
        mSearchButton.setOnClickListener(mOnSearchButtonClickListener);

        mHelper = new PlacesApiHelper(this);

        mMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mMapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
    }

    private View.OnClickListener mOnSearchButtonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mCurrentLatLng = new LatLng(34.694487, 135.19517);
            // Places APIへリクエスト.5000は現在位置からの半径(m)
            mHelper.requestPlaces("food", mCurrentLatLng, 5000, mResultCallback);
        }
    };

    // レスポンスの処理
    private Callback<Response> mResultCallback = new Callback<Response>() {
        @Override
        public void onResponse(retrofit.Response<Response> response, Retrofit retrofit) {
            mGoogleMap.clear();
            // レスポンスからResultのリストを取得
            List<Result> results = response.body().getResults();
            // Resultの数だけピンを立てる
            for(Result r : results) {
                Location location = r.getGeometry().getLocation();
                LatLng latLng = new LatLng(location.getLat(), location.getLng());
                String name = r.getName();
                mGoogleMap.addMarker(new MarkerOptions().position(latLng).title(name));
            }
            mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mCurrentLatLng, 15));
        }

        @Override
        public void onFailure(Throwable t) {
            t.printStackTrace();
        }
    };
}

と,ここまでやれば地図に周辺の検索数だけピンを打てるようになります.