Slide 1

Slide 1 text

Android + JSON-RPC shibuya.apk #10

Slide 2

Slide 2 text

About Me Shinobu Okano @operandoOS Mercari, Inc. Souzoh, Inc.

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

shinobu.apk #3 ΍Γ·͢ʂʂ

Slide 5

Slide 5 text

Androidʹ͍ͭͯޠΔ! shinobu.apk #1 Λ։࠵͠·ͨ͠ʂ http://tech.mercari.com/entry/2016/02/12/122918

Slide 6

Slide 6 text

shinobu.apk #2 ͷύωϧσΟεΧογϣϯ ࿥ԻσʔλͱShow NotesΛެ։͠·ͨ͠ʂ http://hack-it-iron.hatenablog.com/entry/ 2016/04/20/124823

Slide 7

Slide 7 text

http://shinobu-apk.connpass.com/event/40202/ Join!! shinobu.apk #3

Slide 8

Slide 8 text

JSON-RPC??

Slide 9

Slide 9 text

JSON-RPC “JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol.”

Slide 10

Slide 10 text

JSON-RPC spec http://www.jsonrpc.org/specification

Slide 11

Slide 11 text

RPC • gRPC • http://www.grpc.io/ • Go Conference 2016 SpringͰgRPCͷݱঢ়ʹ͍ͭͯ ൃද͖ͯ͠·ͨ͠ • http://tech.mercari.com/entry/ 2016/04/27/145227

Slide 12

Slide 12 text

JSON-RPC 2.0

Slide 13

Slide 13 text

JSON-RPC HTTP bodyͷJSONͰϦΫΤετΛهड़͢Δ

Slide 14

Slide 14 text

JSON-RPC Request { "jsonrpc": "2.0", "method": "subtract", "params": [ 42, 23 ], "id": 1 }

Slide 15

Slide 15 text

JSON-RPC Response { "jsonrpc": "2.0", "result": 19, "id": 1 }

Slide 16

Slide 16 text

JSON-RPC Batch 1ճͷ௨৴Ͱෳ਺ͷϦΫΤετΛૹΕΔ

Slide 17

Slide 17 text

JSON-RPC Request [ { "id": 1, "jsonrpc": "2.0", "method": "shibuya.apk", "params": { ... } }, { "id": 2, "jsonrpc": "2.0", "method": "shinobu.apk", "params": { ... } } ]

Slide 18

Slide 18 text

JSON-RPC Response [ { "id": 1, "jsonrpc": "2.0", "result": { ... } }, { "id": 2, "jsonrpc": "2.0", "result": { ... } } ]

Slide 19

Slide 19 text

Կʹ࢖͏ͷ??

Slide 20

Slide 20 text

Կʹ࢖͏ͷ??

Slide 21

Slide 21 text

Կʹ࢖͏ͷ?? • λΠϜϥΠϯͷ౤ߘΛऔಘ • ݱࡏ஍ͷ࠲ඪΛॅॴʹม׵͢Δ • όφʔΛऔಘ͢Δ ҎԼͷϦΫΤετ͕1ճͷϦΫΤετͰͰ͖Δ

Slide 22

Slide 22 text

GET /home??

Slide 23

Slide 23 text

ෳ਺ͷॲཧΛ·ͱΊͨAPI͸ ࢓༷͕յΕ΍͍͢

Slide 24

Slide 24 text

JSON-RPC Batch • API͸ݸʑͷॲཧΛϝιουͱͯ͠ఆٛ • ΫϥΠΞϯτଆͰݸʑͷॲཧΛ1ͭͷ
 ϦΫΤετʹ·ͱΊͯݺͼग़͢

Slide 25

Slide 25 text

JSON-RPC Request [ { "id": 1, "jsonrpc": "2.0", "method": "GetTimeline", "params": { ... } }, { "id": 2, "jsonrpc": "2.0", "method": "GetBanner", "params": { ... } } ]

Slide 26

Slide 26 text

JSON-RPC Response [ { "id": 1, "jsonrpc": "2.0", "result": { ... } }, { "id": 2, "jsonrpc": "2.0", "result": { ... } } ]

Slide 27

Slide 27 text

Αͦ͞͏!!

Slide 28

Slide 28 text

͡ΌAndroidͰ࣮૷͢Δ͔!!

Slide 29

Slide 29 text

OkHttp࢖ͬͯॻ͍ͯΈΔ Request OkHttpClient client; JSONObject json = new JSONObject(); JsonArray params = new JsonArray(); json.put("method","subtract"); params.put(42); params.put(23); json.put("params",params); RequestBody requestBody = RequestBody.create(MEDIA_TYPE, json.toString().getBytes()); Request request = new Request.Builder() .url("https://....") .post(requestBody) .build(); Response response = client.newCall(request).execute();

Slide 30

Slide 30 text

OkHttp࢖ͬͯॻ͍ͯΈΔ Response Response response = client.newCall(request).execute(); // ... isSuccessfulͷνΣοΫͱ͔... ResponseBody value = response.body(); JSONObject j = new JSONObject(value.string()); int result = j.getInt("result");// return 19

Slide 31

Slide 31 text

͜ΕΠέͯ·͔͢Ͷʁʁ

Slide 32

Slide 32 text

Πέͯͳ͍Ͱ͢ΑͶ...

Slide 33

Slide 33 text

͍͍ײ͡ͷLibrary͋ΔΜ͡ΌͶ… ݕࡧݕࡧ

Slide 34

Slide 34 text

͋·Γͳ͍?? • jsonrpc4j • https://github.com/briandilley/jsonrpc4j • BatchʹରԠͯ͠ͳ͍?? • retrofit-jsonrpc • https://github.com/segmentio/retrofit-jsonrpc • BatchʹରԠͯ͠ͳ͍??

Slide 35

Slide 35 text

్ํʹ฻ΕΔ೔ʑ...

Slide 36

Slide 36 text

͋ʔͳΜͰ͜ΜͳAPIʹ ͳͬͯΔΜͩ...

Slide 37

Slide 37 text

͏͎…๻͸ΘΔ͘ͳ͍... (ɻ-ω-)

Slide 38

Slide 38 text

ͦ͏΋ݴͬͯΒΕͳ͍...

Slide 39

Slide 39 text

ͦ͏ͩʂ ࣗ෼Ͱ࡞Ε͹͍͍Μͩʂ

Slide 40

Slide 40 text

࡞ͬͯΈͨ ※౰೔·Ͱʹίʔυ͕ެ։Ͱ͖·ͤΜͰͨ͠
 ͍͢·ͤΜ

Slide 41

Slide 41 text

࡞Δલʹߟ͑ͨ͜ͱ • ຖճಉ͡ॲཧ͸ॻ͖ͨ͘ͳ͍ • ϦΫΤετͷܕ͕ܾ·Ε͹Ϩεϙϯεͷܕ͕ܾ·Δ • ϦΫΤετͱϨεϙϯεΛܕͰఆٛ • Batch ϦΫΤετΛ͍͍ײ͡ʹड͚औΓ͍ͨ • Rxͱ͔࢖ͬͪΌ͏ʁʁ • ಛఆͷ௨৴ϥΠϒϥϦʹґଘ͠ͳ͍

Slide 42

Slide 42 text

JSON-RPCͷΫϥΠΞϯτ࣮૷Ͱେมͩͬͨ͜ͱ • Batch ϦΫΤετͷड͚औΓํ • ΤϥʔϋϯυϦϯά • RetrofitͷԸܙ͕ड͚ΒΕͳ͍…

Slide 43

Slide 43 text

Ϩεϙϯεͷύλʔϯ • OK 1ͭͷϨεϙϯε • OK ෳ਺ͷϨεϙϯε(2,3ͭ) • NG શϨεϙϯεΤϥʔ • NG Ұ෦ͷϨεϙϯεΤϥʔ

Slide 44

Slide 44 text

Batch ϦΫΤετͷड͚औΓํ • ෳ਺ͷϦΫΤετΛ࡞Δ • ࡞ͬͨϦΫΤετΛ·ͱΊͯAPIʹ౤͛Δ • ෳ਺ͷϨεϙϯε͕ฦͬͯ͘Δ • ϋϯυϦϯάͯ͠ϨεϙϯεΛ௨஌͢Δ

Slide 45

Slide 45 text

ෳ਺ͷϨεϙϯε...??

Slide 46

Slide 46 text

ෳ਺ͷϨεϙϯε...?? • List ?? • List> ?? • List ??

Slide 47

Slide 47 text

ͲΕ΋Πέͯͳ͍

Slide 48

Slide 48 text

ͦ͏ͩ...Tupleͩʂʂ

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

ے೑ 2ͭ @Getter public class Pair { private final F first; private final S second; private Pair(F first, S second) { this.first = first; this.second = second; } public static Pair create(F first, S second) { return new Pair<>(first, second); } }

Slide 51

Slide 51 text

ے೑ 3ͭ @Getter public class Triplet { private final F first; private final S second; private final T thread; private Triplet(F first, S second, T thread) { this.first = first; this.second = second; this.thread = thread; } public static Triplet create(F first, S second, T thread) { return new Triplet<>(first, second, thread); } }

Slide 52

Slide 52 text

ෳ਺ͷϦΫΤετΛ࡞Δ // ϦΫΤετͱϨεϙϯεΛΫϥεͱͯ͠ఆٛ // ϦΫΤετ : GetBanner Ϩεϙϯε : GetBanner class GetBannerResponse { String url; } // ϦΫΤετͷܕ͕ܾ·Ε͹Ϩεϙϯεͷܕ͕ܾ·Δ = RequestType<Ϩεϙϯεͷܕ> class GetBanner extends RequestType { @Override public String getMethod() { return "GetBanner"; } @Override protected Class getResponseType() { return GetBannerResponse.class; } }

Slide 53

Slide 53 text

ෳ਺ͷϦΫΤετΛ࡞Δ // ಉ͡Α͏ʹผAPIͷϦΫΤετͱϨεϙϯεΛΫϥεͱͯ͠ఆٛ // ϦΫΤετ : GetTimeline Ϩεϙϯε : GetTimelineResponse class GetTimelineResponse { List items; } class GetTimeline extends RequestType { private final long timelineId; GetTimeline(long timelineId) { this.timelineId = timelineId; } @Override public String getMethod() { return "GetTimeline"; } @Override protected Class getResponseType() { return GetTimelineResponse.class; } }

Slide 54

Slide 54 text

࡞ͬͨϦΫΤετΛ·ͱΊͯAPIʹ౤͛Δ GetTimeline getTimeline = new GetTimeline(1); GetBanner getBanner = new GetBanner(); RxApiClient rxApiClient = new RxApiClient(); // Observable> ͕ฦͬͯ͘Δ rxApiClient.responseFrom(getTimeline,getBanner) ....

Slide 55

Slide 55 text

ϦΫΤετͷΫϥε͸JSONʹͳͬͯ HTTP bodyʹઃఆ͞ΕΔ [ { "params": { "timelineId": 1 }, "method": "GetTimeline", "jsonrpc": "2.0", "id": "1" }, { "params": {}, "method": "GetBanner", "jsonrpc": "2.0", "id": "2" } ]

Slide 56

Slide 56 text

ෳ਺ͷϨεϙϯε͕ฦͬͯ͘Δ + 
 ϋϯυϦϯάͯ͠ϨεϙϯεΛ௨஌͢Δ // ෳ਺ͷϨεϙϯεTupleʹแΜͰRxʹྲྀ͢ // responseFrom಺ͰTupleʹแΉॲཧΛͯ͠Δ rxApiClient.responseFrom(getTimeline, getBanner) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1>() { @Override public void call(Pair pair) { // Tuple͔ΒϨεϙϯεΛऔΓग़͢ pair.getFirst(); // return GetTimelineResponse pair.getSecond(); // retrun GetBannerResponse } });

Slide 57

Slide 57 text

Thanks!