Google Cloud Endpointsによる API構築

6,130 views

Published on

2014年2月15日、Osaka Innovation Hubで開催され「Innovation EGG 第二回」で発表した資料です。

Published in: Technology
0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,130
On SlideShare
0
From Embeds
0
Number of Embeds
46
Actions
Shares
0
Downloads
18
Comments
0
Likes
19
Embeds 0
No embeds

No notes for slide

Google Cloud Endpointsによる API構築

  1. 1. C-LIS CO., LTD.
  2. 2. C-LIS CO., LTD. Google Cloud Endpointsによる API構築
  3. 3. Who am I? • 有山 圭二(ありやまけいじ) 有限会社シーリス代表 • • Androidアプリ開発者 日本Androidの会 関西支部
  4. 4. サーバーは
 JSONを出し入れするもの 商品 ウォッチ クライアント ウォッチ JSON 通知 通知 サーバー
  5. 5. APIを作ろう! • 追加 • 一覧 • 詳細 • 変更 • 削除 etc…
  6. 6. プラットフォームごとに実装 JavaScript
  7. 7. APIに変更があった!
  8. 8. プラットフォーム×APIの 数だけ変更するんだ ユニットテストも書こうね!
  9. 9. 手で実装する必要あるの?
  10. 10. Google Cloud Endpoints
  11. 11. Google Cloud Endpoints AppEngine上にバックエンドを構築 クライアント用ライブラリを自動生成
  12. 12. さっそく使ってみよう
  13. 13. 準備 • Google App Engine Java SDK (1.7.5 or newer) • Java 7 • Apache Maven • You need to be familiar with development using Google App Engine and the Java runtime.
  14. 14. 手順 • Create your backend API project (using Maven to do this is the easiest method), then write your API backend code. • Annotate your API backend code, so classes and client libraries can be generated from it. (Alternatively, use the Google Plugin for Eclipse, which can annotate for you.) • Generate the client library using Maven, or alternatively, the endpoints.sh command line tool. (Another alternative is to use the Google Plugin for Eclipse to generate the client library.) • Write your client app, using the client library when making calls to the API backend.
  15. 15. 作るもの
  16. 16. ココネコ • 街にいる猫の写真を撮影して、
 位置情報と一緒に投稿するサービス • スマートフォンやブラウザ上で、
 猫の位置や写真を閲覧できる。
  17. 17. APIを作ろう • 猫の写真と位置情報を登録 • 猫の情報を一覧 • 付近の猫の情報を取得
  18. 18. APIを作ろう • 猫の写真と位置情報を登録 → insert • 猫の情報を一覧 → list • 付近の猫の情報を取得 → nyaaby
  19. 19. 写真データは外部 AppEngineにはURLのみ格納
  20. 20. 34.706781 135.494632
  21. 21. 34.706781 135.494632 ↓ xn0m7q008t18
  22. 22. xn0m7q008t18
  23. 23. xn0m7q008t18
  24. 24. xn0m7q008t18
  25. 25. Geohash http://www.tom-carden.co.uk/p5/geohashing/applet/Geohash.java
  26. 26. 準備(バックエンド)
  27. 27. AppEngineプロジェクト作成 $ cd coconeco $ mvn archetype:generate Choose a number or apply filter, com.google.appengine.archetypes:skeleton-archetype ! Choose com.google.appengine.archetypes:skeleton-archetype version: 2: 1.7.5 ! groupId: io.keiji.coconeco ! artifactId: coconeco ! version: ! padkage:
  28. 28. appengine-web.xmlを編集 <?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>coconeco</application> <version>${appengine.app.version}</version> <threadsafe>true</threadsafe> ! <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> </system-properties> </appengine-web-app> coconeco/src/main/java/webapp/WEB-INF/appengine-web.xml
  29. 29. pom.xmlを編集 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ! ! ! ! ! ! ! ! ! <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <groupId>io.keiji.coconeco</groupId> <artifactId>coconeco</artifactId> <properties> <appengine.app.version>1</appengine.app.version> <appengine.target.version>1.7.5</appengine.target.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Compile/runtime dependencies --> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-1.0-sdk</artifactId> <version>${appengine.target.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- Test Dependencies --> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-testing</artifactId> <version>${appengine.target.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-stubs</artifactId> <version>${appengine.target.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <version>2.5.1</version> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <archiveClasses>true</archiveClasses> <webResources> <!-- in order to interpolate version from pom into appengine-web.xml --> <resource> <directory>${basedir}/src/main/webapp/WEB-INF</directory> <filtering>true</filtering> <targetPath>WEB-INF</targetPath> </resource> </webResources> </configuration> </plugin> <plugin> <groupId>com.google.appengine</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>${appengine.target.version}</version> </plugin> </plugins> </build> </project> coconeco/pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ! ! ! <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <groupId>io.keiji.coconeco</groupId> <artifactId>coconeco</artifactId> <properties> <appengine.app.version>1</appengine.app.version> <appengine.target.version>1.8.9</ appengine.target.version> <project.build.sourceEncoding>UTF-8</ project.build.sourceEncoding> </properties> !
  30. 30. endpointsの依存を追加 <dependencies> <!-- Compile/runtime dependencies --> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-1.0-sdk</artifactId> <version>${appengine.target.version}</version> </dependency> … <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-endpoints</artifactId> <version>${appengine.target.version}</version> </dependency> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> <!-- Test Dependencies --> <dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-testing</artifactId> <version>${appengine.target.version}</version> <scope>test</scope> </dependency> … coconeco/pom.xml
  31. 31. プラグインを追加 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <webXml>${project.build.directory}/generated-sources/ appengine-endpoints/WEB-INF/web.xml</webXml> <webResources> <resource> <!-- this is relative to the pom.xml directory --> <directory>${project.build.directory}/ generated-sources/appengine-endpoints</directory> <!-- the list has a default value of ** --> <includes> <include>WEB-INF/*.discovery</include> <include>WEB-INF/*.api</include> </includes> </resource> </webResources> </configuration> </plugin> <plugin> <groupId>com.google.appengine</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>${appengine.target.version}</version> <configuration> <enableJarClasses>false</enableJarClasses> </configuration> <executions> <execution> <goals> <goal>endpoints_get_discovery_doc</goal> </goals> </execution> </executions> </plugin> coconeco/pom.xml
  32. 32. 初期処理 $ mvn install JDK 7でないとエラーが発生 Unsupported major.minor version 51.0 http://www.coderanch.com/t/624933/tools/Maven-dependency-mystery-Google-App
  33. 33. 実装(バックエンド)
  34. 34. package io.keiji.coconeco; ! public class Entry { public Double latitude; public Double longitude; public String geoHash; public String url; public String description; ! ! ! ! ! ! ! ! ! ! public Entry() { } public Entry(String url) { this.url = url; } public Double getLatitude() { return latitude; } public Double getLongitude() { return longitude; } public String getGeoHash() { return geoHash; } public void setLocation(Double lat, Double lon) { this.latitude = lat; this.longitude = lon; this.geoHash = Geohash.encode(lat, lon); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; }; } coconeco/src/main/java/io/keiji/coconeco/Entry.java
  35. 35. package io.keiji.coconeco; ! import java.util.ArrayList; ! public class EntryList { public static ArrayList<Entry> entries = new ArrayList<Entry>(); ! static { entries.add( new Entry("http://i.gzn.jp/img/2009/03/13/swimming_cat/ swimming_cat.jpg")); entries.add( new Entry("http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg")); } ! public Entry getEntryList(Integer id) { return entries.get(id); } } coconeco/src/main/java/io/keiji/coconeco/EntryList.java
  36. 36. package io.keiji.coconeco; ! import java.util.ArrayList; ! import javax.inject.Named; ! import com.google.api.server.spi.config.Api; ! @Api(name = "coconeco", version = "v1") public class EntryList { public static ArrayList<Entry> entries = new ArrayList<Entry>(); ! static { entries.add( new Entry("http://i.gzn.jp/img/2009/03/13/swimming_cat/ swimming_cat.jpg")); entries.add( new Entry("http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg")); } ! public Entry getEntryList(@Named("id") Integer id) { return entries.get(id); } } coconeco/src/main/java/io/keiji/coconeco/EntryList.java
  37. 37. package io.keiji.coconeco; ! // // // // // // // // http://www.tom-carden.co.uk/p5/geohashing/applet/Geohash.java Geohash.java Geohash library for Java ported from David Troy's Geohash library for Javascript - http://github.com/davetroy/geohash-js/tree/master (c) 2008 David Troy (c) 2008 Tom Carden Distributed under the MIT License ! public class Geohash { ! … coconeco/src/main/java/io/keiji/coconeco/Geohash.java
  38. 38. テストサーバーの起動 $ mvn appengine:devserver ! … ! [INFO] INFO: Started SelectChannelConnector@127.0.0.1:8080 [INFO] Feb 14, 2014 9:15:02 PM com.google.appengine.tools.development.JettyContainerService startHotDeployScanner [INFO] INFO: Full scan of the web app in place every 5s. [INFO] Feb 14, 2014 9:15:02 PM com.google.appengine.tools.development.AbstractModule startup [INFO] INFO: Module instance default is running at http://localhost:8080/ [INFO] Feb 14, 2014 9:15:02 PM com.google.appengine.tools.development.AbstractModule startup [INFO] INFO: The admin console is running at http://localhost:8080/_ah/admin [INFO] Feb 14, 2014 9:15:02 PM com.google.appengine.tools.development.DevAppServerImpl doStart [INFO] INFO: Dev App Server is now running
  39. 39. ブラウザでアクセス http://localhost:8080/_ah/api/explorer
  40. 40. ブラウザでアクセス http://localhost:8080/_ah/api/explorer しかし何も起こらなかった!
  41. 41. そもそも、localhostでアクセス出来ない 127.0.0.1ならアクセス出来る (MacOS X Marvericsの場合)
  42. 42. http://stackoverflow.com/questions/20345132/127-0-0-1-is-working-but-localhost-not-working
  43. 43. https://developers.google.com/appengine/docs/java/tools/maven?hl=ja
  44. 44. pom.xmlを編集 <plugin> <groupId>com.google.appengine</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>${appengine.target.version}</version> <configuration> <enableJarClasses>false</enableJarClasses> <address>0.0.0.0</address> <port>8888</port> </configuration> <executions> <execution> <goals> <goal>endpoints_get_discovery_doc</goal> </goals> </execution> </executions> </plugin> coconeco/pom.xml
  45. 45. ブラウザでアクセス http://localhost:8888/_ah/api/explorer
  46. 46. Discovery Based API
  47. 47. Google Cloud Endpoints AppEngine上にDiscovery Based APIに 準拠したバックエンドを構築
  48. 48. package io.keiji.coconeco; ! import java.util.ArrayList; ! import javax.inject.Named; ! import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; ! @Api(name = "coconeco", version = "v1") public class EntryList { public static ArrayList<Entry> entries = new ArrayList<Entry>(); ! static { entries.add(new Entry("http://i.gzn.jp/img/2009/03/13/swimming_cat/ swimming_cat.jpg")); entries.add(new Entry("http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg")); } ! ! ! public ArrayList<Entry> getEntryList() { return entries; } @ApiMethod(name = "get", httpMethod = "get") public Entry getEntry(@Named("id") Integer id) { return entries.get(id); } } coconeco/src/main/java/io/keiji/coconeco/EntryList.java
  49. 49. package io.keiji.coconeco; ! import java.util.ArrayList; ! import javax.inject.Named; ! import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; ! @Api(name = "coconeco", version = "v1") public class EntryList { public static ArrayList<Entry> entries = new ArrayList<Entry>(); ! static { entries.add(new Entry("http://i.gzn.jp/img/2009/03/13/swimming_cat/ swimming_cat.jpg")); entries.add(new Entry("http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg")); } ! // 略 ! ! @ApiMethod(name = "insert", httpMethod = "post") public Entry insertEntry( @Named("lat") Double lat, @Named("lng") Double lng, @Named("url") String url, @Named("desc") String description) { Entry entry = new Entry(); entry.setLocation(lat, lng); entry.setUrl(url); entry.setDescription(description); ! // 保存 entries.add(entry); ! ! return entry; } } coconeco/src/main/java/io/keiji/coconeco/EntryList.java
  50. 50. lat 34.697418 35.675595 lng 135.516559 139.767504 url http://i.gzn.jp/img/2009/03/13/ swimming_cat/swimming_cat.jpg http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C %AB_2008-4.jpg desc シーリス本社 シーリス東京オフィス
  51. 51. ! @ApiMethod(name = "insert", httpMethod = "post") public Entry insertEntry( @Named("lat") Double lat, @Named("lng") Double lng, @Named("url") String url, @Named("desc") String description) { Entry entry = new Entry(); entry.setLocation(lat, lng); entry.setUrl(url); entry.setDescription(description); ! public void setLocation(Double lat, Double lon) { this.latitude = lat; this.longitude = lon; this.geoHash = Geohash.encode(lat, lon); } coconeco/src/main/java/io/keiji/coconeco/Entry.java // 保存 entries.add(entry); ! return entry; } coconeco/src/main/java/io/keiji/coconeco/EntryList.java { "latitude": 34.697418, "longitude": 135.516559, "geoHash": "xn0m7u2phew2", "url": "http%3A%2F%2Fi.gzn.jp%2Fimg%2F2009%2F03%2F13%2Fswimming_cat%2Fswimming_cat.jpg", "description": "%E3%82%B7%E3%83%BC%E3%83%AA%E3%82%B9%E6%9C%AC%E7%A4%BE" }
  52. 52. package io.keiji.coconeco; ! import java.util.ArrayList; import java.net.URLEncoder; import java.io.UnsupportedEncodingException; ! import javax.inject.Named; ! import com.google.api.server.spi.config.Api; import com.google.api.server.spi.config.ApiMethod; @ApiMethod(name = "nyaaby", httpMethod = "get") public ArrayList<Entry> getEntry( @Named("lat") Double lat, @Named("lng") Double lng) { ! ! ! ArrayList<Entry> result = new ArrayList<Entry>(); String geoHash = Geohash.encode(lat, lng); // 検索条件 ! @Api(name = "coconeco", version = "v1") public class EntryList { public static ArrayList<Entry> entries = new ArrayList<Entry>(); ! private static final int GEO_THRESHOLD = 7; ! static { Entry entry1 = new Entry(); entry1.setLocation(34.697418, 135.516559); entry1.setUrl("http://i.gzn.jp/img/2009/03/13/swimming_cat/ swimming_cat.jpg"); try { entry1.setDescription( URLEncoder.encode("シーリス本社", "UTF-8")); ! entries.add(entry2); } catch (UnsupportedEncodingException e) {} } ! // 検索処理 search(entries, result, term); ! ! entries.add(entry1); } catch (UnsupportedEncodingException e) {} Entry entry2 = new Entry(); entry2.setLocation(35.675595, 139.767504); entry2.setUrl("http://upload.wikimedia.org/wikipedia/ja/ 1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg"); try { entry2.setDescription( URLEncoder.encode(”シーリス東京オフィス”, ”UTF-8”)); String term = geoHash.substring( 0, geoHash.length() - GEO_THRESHOLD); return result; } private static void search(ArrayList<Entry> from, ArrayList<Entry> to, String term) { for (Entry entry : from) { if (entry.getGeoHash().startsWith(term)) { to.add(entry); } } } } coconeco/src/main/java/io/keiji/coconeco/EntryList.java
  53. 53. desc 大阪天満宮 有楽町 lat 34.697211 35.6770686 lng 135.513215 139.7697867
  54. 54. { "items" : [ { "latitude" : 35.675595, "longitude" : 139.767504, "geoHash" : "xn76uqx96uut", "url" : "http://upload.wikimedia.org/wikipedia/ja/1/16/%E6%97%A5%E6%9C%AC%E7%8C%AB_2008-4.jpg", "description" : "%E3%82%B7%E3%83%BC%E3%83%AA%E3%82%B9%E6%9D%B1%E4%BA%AC%E3%82%AA %E3%83%95%E3%82%A3%E3%82%B9" } ] }
  55. 55. サーバーへのupload準備 <?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>stable-apogee-488</application> <version>1</version> <threadsafe>true</threadsafe> ! <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/ logging.properties"/> </system-properties> </appengine-web-app> coconeco/src/main/java/webapp/WEB-INF/appengine-web.xml
  56. 56. アップロード $ mvn appengine:update ! … ! Please enter code:
  57. 57. Beginning interaction for module default... 0% Created staging directory at: '/var/folders/tv/yr_x0jn163s4yr1gv77bk1mr0000gn/T/ appcfg4387737080071537979.tmp' 5% Scanning for jsp files. 20% Scanning files on local disk. 25% Initiating update. 28% Cloning 10 application files. 40% Uploading 6 files. 52% Uploaded 1 files. 61% Uploaded 2 files. 68% Uploaded 3 files. 73% Uploaded 4 files. 77% Uploaded 5 files. 80% Uploaded 6 files. 82% Initializing precompilation... 84% Sending batch containing 6 file(s) totaling 21KB. 90% Deploying new version. 99% Closing update: new version is ready to start serving. 99% Uploading index definitions. ! Update for module default completed successfully. Success. Cleaning up temporary files for module default... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1:00.795s [INFO] Finished at: Sat Feb 15 06:07:07 JST 2014 [INFO] Final Memory: 13M/245M [INFO] ------------------------------------------------------------------------
  58. 58. https://apis-explorer.appspot.com/apis-explorer/?base=https://stable-apogee-488.appspot.com/_ah/api#p/
  59. 59. Android用ライブラリ
  60. 60. クライアントライブラリの 生成 $ mvn appengine:endpoints_get_client_lib target/endpoints-client-libs/coconeco/target/coconeco-v1-1.17.0-rc-SNAPSHOT.jar
  61. 61. 依存ライブラリ山盛り • • • • • • • • • google-api-client-1.12.0-beta.jar google-api-client-android-1.12.0-beta.jar google-http-client-1.12.0-beta.jar google-http-client-android-1.12.0-beta.jar google-http-client-gson-1.12.0-beta.jar google-oauth-client-1.12.0-beta.jar gson-2.1.jar guava-jdk5-13.0.jar jsr305-1.3.9.jar https://developers.google.com/appengine/docs/java/endpoints/consume_android
  62. 62. pom.xmlに依存関係を追加 <dependencies> <dependency> <groupId>com.google.api-client</groupId> <artifactId>google-api-client</artifactId> <version>1.17.0-rc</version> </dependency> <dependency> <groupId>com.google.api-client</groupId> <artifactId>google-api-client-android</artifactId> <version>1.17.0-rc</version> </dependency> <dependency> <groupId>com.google.api-client</groupId> <artifactId>google-api-client-gson</artifactId> <version>1.17.0-rc</version> </dependency> </dependencies> ! <properties> <project.build.sourceEncoding>UTF-8</ project.build.sourceEncoding> </properties> </project> target/endpoints-client-libs/coconeco/pom.xml
  63. 63. 依存関係のファイルを取得 $ target/endpoints-client-libs/coconeco/ $ mvn dependency:copy-dependencies target/endpoints-client-libs/coconeco/target/dependency にダウンロード
  64. 64. Androidプロジェクトの作成 • Coconeco • io.keiji.coconeco.android
  65. 65. 依存ライブラリのコピー • プロジェクトの libs/ 以下にコピー
  66. 66. 表示する画面 <LinearLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" android:orientation="vertical"> ! ! <ImageView android:id="@+id/iv_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="読み込み中..." /> </LinearLayout> activity_main.xml
  67. 67. 表示する画面 package io.keiji.coconeco.android; ! public class MainActivity extends Activity { ! private ImageView mImage; private TextView mDescription; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImage = (ImageView) findViewById(R.id.iv_picture); mDescription = (TextView) findViewById(R.id.tv_description); // 付近の情報を取得 } NyaaByTask task = new NyaaByTask(); task.execute(new Void[0]); @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } ! ! ! ! ! MainActivity.java
  68. 68. 付近の情報を取得する処理 private class NyaaByTask extends AsyncTask<Void, Void, List<CoconecoEntry>> { @Override protected List<CoconecoEntry> doInBackground(Void... params) { } @Override protected void onPostExecute(List<CoconecoEntry> result) { super.onPostExecute(result); if (result.size() > 0) { CoconecoEntry entry = result.get(0); try { String desc = URLDecoder.decode(entry.getDescription(), "UTF-8"); mDescription.setText(desc); } catch (UnsupportedEncodingException e) { } } } ! ! ! ! Coconeco.Builder builder = new Coconeco.Builder( AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); Coconeco service = builder.build(); try { EntryCollection result = service.nyaaby(34.697211, 135.513215) .execute(); return result.getItems(); } catch (IOException e) { } return null; } ImageLoadTask task = new ImageLoadTask(); task.execute(new String[] { entry.getUrl() }); MainActivity.java
  69. 69. 画像を取得する処理 private class ImageLoadTask extends AsyncTask<String, Void, Bitmap> { @Override protected Bitmap doInBackground(String... params) { String url = params[0]; HttpGet request = new HttpGet(url); AndroidHttpClient client = AndroidHttpClient .newInstance("Coconeco"); } Bitmap bmp = null; InputStream is = null; try { HttpResponse response = client.execute(request); is = response.getEntity().getContent(); bmp = BitmapFactory.decodeStream(is); } catch (IOException e) { } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } client.getConnectionManager().shutdown(); } return bmp; } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); mImage.setImageBitmap(result); } ! ! ! ! MainActivity.java
  70. 70. 実行結果
  71. 71. 他のプラットフォームは… JavaScript https://developers.google.com/appengine/docs/java/endpoints/consume_js iOS https://developers.google.com/appengine/docs/java/endpoints/consume_ios
  72. 72. C-LIS CO., LTD. 本資料料は、有限会社シーリスの著作物であり、   クリエイティブコモンズの表⽰示-‐‑‒⾮非営利利-‐‑‒継承  3.0  Unported  ライセンスの元で公開しています。 各製品名・ブランド名、会社名などは、⼀一般に各社の商標または登録商標です。   本資料料中では、©、®、™を割愛しています。

×