æè¿ãã¢ããªã±ãŒã·ã§ã³ã®Googleãããã«2ã€ã®ãã€ã³ãéã®ã«ãŒãã衚瀺ããå¿
èŠããããŸããã Habréã«ã¯ããã®ããŒãã«é¢ããåºçç©ããã§ã«ãããŸããã ããšãã°ã
ãAndroidã¢ããªã±ãŒã·ã§ã³ã§ã®Googleãããã®ã«ãŒãã ã ãããããããã®è³æã¯ãã§ã«é·ãéæºè¶³ããŠãããæ°ããæ©äŒãå©çšããŠããŸããã ã«ãŒããæç»ããå¥ã®æ¹æ³ã瀺ãããã®ã§ããã誰ãã«åœ¹ç«ã€ãããããŸããã
Googleããããã¢ããªã±ãŒã·ã§ã³ã«çµ±åããããã»ã¹ã¯çç¥ããŸããèå³ã®ããæ¹ã¯ã
Googleã®è©³çŽ°ã¬ã€ãã§ãã¹ãŠã®æ
å ±ãèŠã€ããããšãã§ããŸãã ã«ãŒãã衚瀺ããããã»ã¹å
šäœã¯ãããã€ãã®æ®µéã§æ§æãããŠããŸãã
- ã«ãŒãã«é¢ããæ
å ±ãååŸããŸãã
- åä¿¡ããå¿çã®åŠçã
- å°å³ã«ã«ãŒããæããŸãã
ãããã®æé ãæ€èšããŠãã ããã
ã«ãŒããååŸãã
ã«ãŒãæ
å ±ãååŸããã«ã¯ãGoogleã«ãŒããµãŒãã¹ãžã®ãªã¯ãšã¹ããå®äºããå¿
èŠããããŸãã ã¯ãšãªãšè¿ãããã¯ãšãªã®è©³çŽ°ãªèª¬æã¯ã
Googleã§å
¥æã§ã
ãŸã ã ã«ãŒããååŸããã«ã¯ã次ã®åœ¢åŒã®ã¯ãšãªãå®è¡ããå¿
èŠãããããšã«æ³šæããŠãã ããã
https://maps.googleapis.com/maps/api/directions/output?parameters
åºåãšããŠ
ã XMLãŸãã¯ïŒãã®å Žåã¯ïŒJSONãéžæã§ããŸãã å¿
é ãã©ã¡ãŒã¿ã«ã¯ã
åºçºå°ãš
ç®çå°ãå«ãŸããŸãããããã¯ãäœæã®ããã¹ãè¡šçŸãšããŠããŸãã¯ã³ã³ãã§åºåããã緯床ãšçµåºŠã®å€ãšããŠæå®ã§ããŸãã 3çªç®ã®å¿
é ãã©ã¡ãŒã¿ãŒ
sensorã¯ãèŠæ±ãäœçœ®ã»ã³ãµãŒãåããããã€ã¹ããã®ãã®ãã©ããã瀺ã
ãŸã ããã®å Žåãåžžã«
trueã«ãªã
ãŸã ã
ãªã¯ãšã¹ãã®åœ¢åŒã決å®ããããGoogleã«ãŒããµãŒãã¹ãžã®ãªã¯ãšã¹ããåŠçããŠå¿çãåãåãæ¹æ³ãéžæããå¿
èŠããããŸãã
Retrofitã©ã€ãã©ãªã䜿çšããŸããããã«ãããRESTãµãŒãã¹ãžã®ãªã¯ãšã¹ããæ°è¡ã§äœæã§ããŸãã
Retrofitã䜿çšããã«ã¯ãã©ã€ãã©ãªããããžã§ã¯ãã«æ¥ç¶ããå¿
èŠããããŸãã gradleã䜿çšããŠãããã¯gradleãã¡ã€ã«ã«1è¡ã®äŸåé¢ä¿ãè¿œå ããããšã§å®è¡ãããŸãã
dependencies { compile 'com.squareup.retrofit:retrofit:1.7.1' }
次ã«ãGoogle Route Services APIã«ã€ããŠèª¬æããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãããã€ãã®ã¡ãœãããäœæããæ°ããJavaã€ã³ã¿ãŒãã§ã€ã¹ãäœæããRetrofitã¢ãããŒã·ã§ã³ã䜿çšããŠãããããµãŒããŒäžã®ããŸããŸãªã¡ãœããã«ãããããŸãã æ
å ±ã®ã¿ãåãåããããGETãªã¯ãšã¹ãã®ã¡ãœããã1ã€ã ãèšè¿°ããå¿
èŠããããŸãã
public interface RouteApi { @GET("/maps/api/directions/json") RouteResponse getRoute( @Query(value = "origin", encodeValue = false) String position, @Query(value = "destination", encodeValue = false) String destination, @Query("sensor") boolean sensor, @Query("language") String language); }
åŒæ°ãšããŠã®
GETã¢ãããŒã·ã§ã³ã¯ãã¯ãšãªãå®è¡ãããµãŒããŒäžã®ãã£ã¬ã¯ããªãååŸããã¡ãœããèªäœã§æ¢ã«åãã©ã¡ãŒã¿ãŒã«
Queryã¢ãããŒã·ã§ã³ãä»ããŸãã å泚éã®åŒæ°ãšããŠããªã¯ãšã¹ãã«å«ãããã©ã¡ãŒã¿ãŒã®ååã ãã®å Žåã
åºçºå°ãš
ç®çå°ã®ãã©ã¡ãŒã¿ãŒã«ã€ããŠã
encodeValueãã©ã°ã®å€ãèšå®ããŸããããã«ããã
Retrofitã«ããªã¯ãšã¹ãå
ã®ç·¯åºŠãšçµåºŠã®å€ãåºåãã³ã³ãããšã³ã³ãŒãããªãããã«æ瀺ããŸãã ãŸãããµãŒããŒããã®å¿çããã·ã¢èªã«ãªãããã«ããã1ã€ã®
èšèªãã©ã¡ãŒã¿ãŒãè¿œå ããŸãã RESTã¡ãœããã¯ãªããžã§ã¯ããè¿ãå¿
èŠããããŸãããããRouteResponseãšåŒã³ãŸãããã åŸã§èª¬æããŸããããšããããRouteResponseãšããå¥ã®ã¯ã©ã¹ãäœæããŠãã ããã
ãµãŒãã¹ã®APIã説æããåŸããªã¯ãšã¹ããåŠçã§ããŸãã ãããè¡ãã«ã¯ãRestAdapterãäœæãããªã¢ãŒããµãŒãã¹ãè¡šããµãŒãã¹ãäœæãããã®APIã¡ãœãããåŒã³åºãå¿
èŠããããŸãã
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://maps.googleapis.com") .build(); RouteApi routeService = restAdapter.create(RouteApi.class); RouteResponse routeResponse = routeService.getRoute(position, destination, true, "ru");
Googleã®ã«ãŒããµãŒãã¹ããã«ãŒããååŸããã®ã«å¿
èŠãªããšã¯ããã ãã§ãã RestAdapterã³ã³ã¹ãã©ã¯ã¿ãŒã«è¡ãè¿œå ãã
.setLogLevel(RestAdapter.LogLevel.FULL)
ããªã¯ãšã¹ããå®è¡ãããã°ã§ãµãŒããŒããã®ã¬ã¹ãã³ã¹ã確èªã§ããŸãã ããããç§ãã¡ã¯ããã§æ¢ãŸããŸããã
åä¿¡ããå¿çã®åŠç
ã¯ãšãªã®çµæãšããŠãRouteResponseãªããžã§ã¯ããååŸããŸãã å®éããµãŒããŒããJSONãèŠæ±ããããããµãŒããŒããã®å¿çã¯JSON圢åŒã«ãªããŸãã ãµãŒããŒããå¿çãåä¿¡ãã
Retrofit㯠ãGoogle
GSONã®ããŒãµãŒã䜿çšããŠJSONã®è§£æãåå¥ã«éå§ããJSONãRouteResponseãªããžã§ã¯ãã«è§£æããŸãã å¿
èŠã«å¿ããŠãå¥ã®ããŒãµãŒ-JacksonãŸãã¯
Instagramã®JSONããŒãµãŒãéžæã§ããŸãããGSONã䜿çšããããšã奜ã¿ãŸãã GSONã«ã¯Retrofitãä»å±ããŠããããããããžã§ã¯ãã§äœ¿çšããããã«è¿œå ã®äŸåé¢ä¿ãå«ããå¿
èŠã¯ãããŸããã
JSONã¬ã¹ãã³ã¹ããããŒã¿ãååŸããã«ã¯ããã®ããŒã¿ãèšè¿°ããã¯ã©ã¹ãäœæããå¿
èŠããããŸãã RouteResponseã¯ã©ã¹ã¯æ¢ã«äœæãããŠããŸãããããã€ãã®ã³ã³ãã³ãã§åããããšã¯æ®ã£ãŠããŸãã Google Route ServiceãµãŒããŒããã®å¿çã®äžè¬çãªæ§é ã¯æ¬¡ã®ãšããã§ãã
{ "routes" : [ { "bounds" : { "northeast" : { "lat" : 55.79283659999999, "lng" : 49.2216592 }, "southwest" : { "lat" : 55.73007759999999, "lng" : 49.1309371 } }, "copyrights" : " © 2014 Google", "legs" : [ ], "overview_polyline" : { "points" : "qffsIk{zjHEwKpKcAvGo@bFk@bGg@vFg@hEIxFQHcTL{a@FkCF_AFm@L_@Zs@Pa@f@cB|@gDb@aBbAuDrByIrAqIhB{LTaDFoA?uAK_B]gEe@oEKk@]]}@u@AGCIEEkEsCgAy@o@o@mBwBmCyCyAaBSQiAg@iBq@aAWmGaA_AKUFm@MiACU@i@Jj@sAVW^YbAs@T_@Nq@?_@Eu@g@iCuBcHq@yCIy@Aq@Fq@He@nCmGhC{FnGcNbA}BNa@TeAPqAZmDzBiWJ}@Da@cA_CiFmLc@aAkBkEqBiEcP__@oHmPaE}IgD}HaCiFcGyM}H{PcFeLyKqV_BuDyA}CaCqF{HgQsCuGyAiDsAoCk@cAe@u@iAmAq@k@m@]aA_@oA]m@IuCK_C@yMGwUO_M@{B?yUSuEAqG?aD@cM@qFDoFEs@?iPGiDEgA?yAEoFAoDCo@?mGEmGE_JEsGAq@BaCHsAJKqAHcBn@HEsDBADEJ]FIPEZ?LJTB" }, "summary" : ". ", "warnings" : [], "waypoint_order" : [] } ], "status" : "OK" }
ã芧ã®ãšãããçããšããŠã
ã«ãŒãã»ã°ã¡ã³ããæ§æããSteps
ã¹ããããšã»ã°ã¡ã³ãã«é¢ããæ
å ±ã§æ§æããã
Legsã»ã°ã¡ã³ãã®é
åãå«ã
Routesã«ãŒãã®é
åãååŸããŸãã åã®äŸã§ã¯ãã«ãŒãã¯ã»ã°ã¡ã³ãã®åã¹ãããã«é¢ããæ
å ±ã«åºã¥ããŠæ§ç¯ãããŸããããRouteãªããžã§ã¯ãã«ã¯ãã§ã«
Overview_polylineãªããžã§ã¯ããå«ãŸããŠããŸã-ããã¯ãçµæã®ã«ãŒãã®è¿äŒŒïŒæ»ãããªïŒãã¹ãè¡šããšã³ã³ãŒããã€ã³ãã®é
åãæã€ãªããžã§ã¯ãã§ãã ã»ãšãã©ã®å Žåããã®ã¹ã ãŒãºãªã«ãŒãã§ååã§ãã ãããã£ãŠãæç»ã«äœ¿çšããŸãã
ãã®æ
å ±ã«åºã¥ããŠãGSONã®ã¢ãã«ã¯ã©ã¹ãèšè¿°ããŸãã
public class RouteResponse { public List<Route> routes; public String getPoints() { return this.routes.get(0).overview_polyline.points; } class Route { OverviewPolyline overview_polyline; } class OverviewPolyline { String points; } }
ãªã¯ãšã¹ããåŠçããŠRouteResponseãªããžã§ã¯ããååŸãããšããããã
ãã€ã³ãã©ã€ã³ãååŸã§ããŸãã åæç¶æ
ã§ã¯ãã»ãšãã©äœãåŸãããŸããã ããããæ
å ±ãååŸããã«ã¯ã解èªããå¿
èŠããããŸãã ããã§ã¯ã
Google Maps Android APIãŠãŒãã£ãªãã£ã©ã€ãã©ãªã®PolyUtilã¯ã©ã¹ã圹ç«ã¡ãŸãã ããã䜿çšããã«ã¯ããããžã§ã¯ãã«æ¬¡ã®äŸåé¢ä¿ãå«ããå¿
èŠããããŸãã
dependencies { compile 'com.google.maps.android:android-maps-utils:0.3+' }
PolyUtilã«ã¯decodeïŒïŒã¡ãœãããå«ãŸããŠãããããã¯ãã€ã³ãã®ã¹ããªã³ã°ã
ååŸã ãã«ãŒãã®ããŒãã§ãã
LatLngãªããžã§ã¯ãã®ã»ãããè¿ããŸãã ããã§ãå°å³äžã«ã«ãŒããæç»ã§ããŸãã
å°å³ã«ã«ãŒããæã
å€ãäŸã§ã¯ãã«ãŒããæç»ããããã«ãªãŒããŒã¬ã€ã䜿çšãããŸããããããªã©ã€ã³ã¯ã©ã¹ã§ç®¡çããŸã-ãã®å ŽåããªãŒããŒã¬ã€ããç¶æ¿ãããè¿œå ã®ã¯ã©ã¹ãäœæããå¿
èŠã¯ãªããèšè¿°ããå¿
èŠãããã³ãŒãã®éã¯å€§å¹
ã«åæžãããŸãã ããªã©ã€ã³ã¯ããããäžã®ãã€ã³ããšããããçµã¶ç·ã®ãªã¹ãã§ãã ãã®åŸãããªã©ã€ã³ããããã«è¿œå ã§ããŸãã
PolylineOptions line = new PolylineOptions(); line.width(4f).color(R.color.indigo_900); LatLngBounds.Builder latLngBuilder = new LatLngBounds.Builder(); for (int i = 0; i < mPoints.size(); i++) { if (i == 0) { MarkerOptions startMarkerOptions = new MarkerOptions() .position(mPoints.get(i)) .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker_a)); mGoogleMap.addMarker(startMarkerOptions); } else if (i == mPoints.size() - 1) { MarkerOptions endMarkerOptions = new MarkerOptions() .position(mPoints.get(i)) .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker_b)); mGoogleMap.addMarker(endMarkerOptions); } line.add(mPoints.get(i)); latLngBuilder.include(mPoints.get(i)); } mGoogleMap.addPolyline(line); int size = getResources().getDisplayMetrics().widthPixels; LatLngBounds latLngBounds = latLngBuilder.build(); CameraUpdate track = CameraUpdateFactory.newLatLngBounds(latLngBounds, size, size, 25); mGoogleMap.moveCamera(track);
ãŸãã
PolylineOptionsã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããç·ã®å€ªããšè²ãèšå®ããŸãã 次ã«ã
LatLngBuilderã®ã€ã³ã¹ã¿ã³ã¹ãååŸããŠããããã®ã¹ã±ãŒãªã³ã°ã«äœ¿çšãããå¢çããã¯ã¹ãäœæããŸãã 次ã«ãGoogle
Routes APIããã®å¿çããã³ãŒãããçµæãšããŠååŸããã
LatLngãªããžã§ã¯ãã®ãªã¹ãã
調㹠ãåãã€ã³ããlineããã³
LatLngBuilderã«è¿œå ããŸãã ãªã¹ãã®æåãšæåŸã®ãªããžã§ã¯ãïŒããããéå§ç¹ãšçµäºç¹ã®åº§æšïŒã«å¯ŸããŠãããŒã«ãŒãäœæãããããã«è¿œå ããŸãã ãªã¹ãé
ç®ã®åæãå®äºããããaddPolylineïŒïŒã¡ãœãããåŒã³åºããŠãæ§ç¯ãããè¡ããããã«è¿œå ããŸãã
次ã«ãã«ãŒãå
šäœã衚瀺ããããã«ããããã¹ã±ãŒãªã³ã°ããå¿
èŠããããŸãã ãããå
ã移åããã«ã¯ãCameraã¯ã©ã¹ã®moveCameraïŒïŒã¡ãœããã䜿çšããŸãããã®ã¡ãœããã¯ãå
¥åãšããŠUpdateCameraãªããžã§ã¯ãã®ã«ã¡ã©èšå®ãåãåããŸãã UpdateCameraFactoryã¯ã©ã¹ã®newLatLngBoudnsã¡ãœãããåŒã³åºããŠãCameraUpdateãªããžã§ã¯ããäœæããŸãã ããã«ãäœæããLatLngBoundsãªããžã§ã¯ããæž¡ããŸããããã«ã¯ãã«ãŒãã®ãã¹ãŠã®ãã€ã³ããå«ãŸããç»é¢ã®å¹
ãæž¡ããããšããžããã€ã³ãã³ããè¿œå ãããŸãã ãã®åŸãã¡ãœãããåŒã³åºããŠã«ã¡ã©ã移åããŸãã ããã ãã§ããã«ãŒããæãããŸãã

çµè«ãšããŠãç§ã䜿çšããè³æãžã®ãã¹ãŠã®ãªã³ã¯ãå床瀺ããŸãã