Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android + JSON-RPC

operandoOS
September 16, 2016

Android + JSON-RPC

Android + JSON-RPC

shibuya.apk #10
http://shibuya-apk.connpass.com/event/39433/

operandoOS

September 16, 2016
Tweet

More Decks by operandoOS

Other Decks in Technology

Transcript

  1. Android + JSON-RPC
    shibuya.apk #10

    View Slide

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

    View Slide

  3. View Slide

  4. shinobu.apk #3
    ΍Γ·͢ʂʂ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. JSON-RPC??

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. JSON-RPC 2.0

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  19. Կʹ࢖͏ͷ??

    View Slide

  20. Կʹ࢖͏ͷ??

    View Slide

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

    View Slide

  22. GET /home??

    View Slide

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

    View Slide

  24. JSON-RPC Batch
    • API͸ݸʑͷॲཧΛϝιουͱͯ͠ఆٛ
    • ΫϥΠΞϯτଆͰݸʑͷॲཧΛ1ͭͷ

    ϦΫΤετʹ·ͱΊͯݺͼग़͢

    View Slide

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

    View Slide

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

    View Slide

  27. Αͦ͞͏!!

    View Slide

  28. ͡ΌAndroidͰ࣮૷͢Δ͔!!

    View Slide

  29. 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();

    View Slide

  30. 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

    View Slide

  31. ͜ΕΠέͯ·͔͢Ͷʁʁ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  35. ్ํʹ฻ΕΔ೔ʑ...

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    ͍͢·ͤΜ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  47. ͲΕ΋Πέͯͳ͍

    View Slide

  48. ͦ͏ͩ...Tupleͩʂʂ

    View Slide

  49. View Slide

  50. ے೑ 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);
    }
    }

    View Slide

  51. ے೑ 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);
    }
    }

    View Slide

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

    View Slide

  53. ෳ਺ͷϦΫΤετΛ࡞Δ
    // ಉ͡Α͏ʹผ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;
    }
    }

    View Slide

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

    View Slide

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

    View Slide

  56. ෳ਺ͷϨεϙϯε͕ฦͬͯ͘Δ + 

    ϋϯυϦϯάͯ͠ϨεϙϯεΛ௨஌͢Δ
    // ෳ਺ͷϨεϙϯε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
    }
    });

    View Slide

  57. Thanks!

    View Slide