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

JavaScriptとSwift&JavaをつなげるCapacitorと、これからのWeb Frontend/Linking JavaScript with Swift&Java,
And the future of Web Frontend.

Masahiko Sakakibara
December 01, 2019
3k

JavaScriptとSwift&JavaをつなげるCapacitorと、これからのWeb Frontend/Linking JavaScript with Swift&Java,
And the future of Web Frontend.

Masahiko Sakakibara

December 01, 2019
Tweet

More Decks by Masahiko Sakakibara

Transcript

  1. -JOLJOH+BWB4DSJQUXJUI4XJGU+BWB
    "OEUIFGVUVSFPG8FC'SPOUFOE
    +BWB4DSJQUͱ4XJGU+BWBΛͭͳ͛Δ$BQBDJUPSͱɺ͜Ε͔Βͷ8FC'SPOUFOE

    View Slide

  2. *OUSPEVDF
    .BTBIJLP4BLBLJCBSB
    $&0
    PG3FMBUJPO%FTJHO-BC
    $50PG
    "SFB*OOPWBUJPO"MMJBODF
    *POJD+BQBO6TFS(SPVQ
    0SHBOJ[FS

    View Slide

  3. $POUSJCVUF
    ionic-team/ionic
    ionic-team/starters
    ionic-team/ionic-cli
    ionic-team/ionic-docs
    ionic-team/ionic-react
    -conference-app
    GoogleChrome/lighthouse

    View Slide

  4. !SEMBCPDBQBDJUPSGBDFCPPLMPHJO

    View Slide

  5. !SEMBCPDBQBDJUPSBENPC

    View Slide

  6. ఆֹॅΈ์୊ºՈकͷֶߍ
    ʮ݄ສͰશࠃॅΈ์୊ʯͰόζͬͨ"%%SFTTͷڌ఺ϚωʔδϟʔεΫʔ
    ϧΛߦ͍·͢ɻ"%%SFTTͷڌ఺ʹॅΈɺ஍ҬΛม͑ͯΈ·ͤΜ͔ʁʁ
    ڌ఺ʢॅډʣΛ࣋ͬͯ஍ҬͱؔΘΓͳ͕Βࣄۀ͕Ͱ͖ΔͷͰɺϦϞʔτ
    ϫʔΧʔͷ৽͍͠ಇ͖ํʹ͓͢͢ΊͰ͢ʂ
    Ոकͷֶߍ

    View Slide

  7. 8IBUJT$BQBDJUPS

    View Slide

  8. $BQBDJUPS

    View Slide

  9. )PXXPSLTPG8FC/BUJWF"QQ
    w 7JFXT-PDBMT8FC"QQVTJOHB
    8FC7JFXDBMMFE"QQ
    w "1*BWBJMBCMFUPBDDFTT/BUJWF
    'VODUJPOT
    888

    View Slide

  10. %J⒎FSFODFPG3FBDU/BUJWF/BUJWF4DSJQU

    View Slide

  11. /PUGBTUFTU#VUOPUTMPX
    https://vimeo.com/55486684

    View Slide

  12. 6TJOH$BQBDJUPS
    )PX

    View Slide

  13. 6TJOH$BQBDJUPS
    $ npm install @capacitor/core @capacitor/cli
    $ npx cap init
    {
    "appId": “jp.rdlabo.capacitor",
    "appName": "ng-capacitor",
    "bundledWebRuntime": false,
    "npmClient": "npm",
    "webDir": “dist/ng-capacitor",
    "cordova": {}
    }
    capacitor.config.json

    View Slide

  14. 6TJOH$BQBDJUPSJ04
    $ npx cap add ios
    SFG
    /FX4XJGU1SPKFDU

    View Slide

  15. 4XJGUUP)5.-+BWB4DSJQU

    View Slide

  16. 6TJOH$BQBDJUPSJ04 DPNQBSF/FX4XJGU1SPKFDU

    SFG
    /FX4XJGU1SPKFDU

    View Slide

  17. /FX4XJGU1SPKFDUˠ#MBOL

    View Slide

  18. $BQBDJUPSJ041SPKFDUˠ$"1#SJEHF7JFX$POUSPMMFS
    customModule="Capacitor" sceneMemberID="viewController"/>

    View Slide

  19. 8IBUJT$"1#SJEHF7JFX$POUSPMMFS ˠ1PEpMF
    platform :ios, '11.0'
    use_frameworks!
    # workaround to avoid Xcode 10
    caching of Pods that requires
    # Product -> Clean Build Folder
    after new Cordova plugins installed
    # Requires CocoaPods 1.6 or newer
    install!
    'cocoapods', :disable_input_output_p
    aths => true
    def capacitor_pods
    # Automatic Capacitor Pod
    dependencies, do not delete
    pod 'Capacitor', :path => '../../
    node_modules/@capacitor/ios'
    pod 'CapacitorCordova', :path =>
    '../../node_modules/@capacitor/ios'
    # Do not delete
    end
    Podfile

    View Slide

  20. $"1#SJEHF7JFX$POUSPMMFSWJFXTQVCMJD
    func loadWebView() {
    let fullStartPath = URL(fileURLWithPath:
    "public").appendingPathComponent(startDir).appen
    dingPathComponent("index")
    if Bundle.main.path(forResource:
    fullStartPath.relativePath, ofType: "html") == nil {
    fatalLoadError()
    }
    hostname =
    bridge!.config.getString("server.url") ?? "\
    (bridge!.getLocalUrl())"
    allowNavigationConfig =
    bridge!.config.getValue("server.allowNavigation")
    as? Array
    CAPLog.print("⚡ Loading app at \
    (hostname!)...")
    let request = URLRequest(url: URL(string:
    hostname!)!)
    _ = webView?.load(request)
    }
    CAPBridgeViewController.swift

    View Slide

  21. 8IBUJTAQVCMJDA
    $ npm install @capacitor/core @capacitor/cli
    $ npx cap init
    {
    "appId": “jp.rdlabo.capacitor",
    "appName": "ng-capacitor",
    "bundledWebRuntime": false,
    "npmClient": "npm",
    "webDir": “dist/ng-capacitor",
    "cordova": {}
    }
    capacitor.config.json
    5PQVCMJDEJSFDUPSZ

    View Slide

  22. /PU.VTUSFRVJSF41" 4BNF0SJHJO0OMZ

    JOEFYIUNM OFYUIUNM UIJSETIUNM
    #VU"QQNVTUMPBEBTTFUTpMFFWFSZUJNF

    View Slide

  23. )5.-+BWB4DSJQUUP4XJGU

    View Slide

  24. 6TJOH$BQBDJUPS1MVHJO
    $ npx @capacitor/cli plugin:generate

    View Slide

  25. 6TJOH$BQBDJUPS1MVHJO
    TIPVME4UBSU-PBE8JUI3FRVFTU

    View Slide

  26. TIPVME4UBSU-PBE8JUI3FRVFTU
    1MVHJOI1MVHJON
    w "EE$VTUPN63-4DIFNF
    w "EELFZUP8JOEPX0CKFDUJO8FC7JFX
    w FY
    XJOXFCLJUNFTTBHF)BOEMFSTCSJEHFQPTU.FTTBHF BSH

    *GBQQBDDFTT8JOEPX
    0CKFDU VTJOHBSH
    UIJTpMF
    XJMMCFFYFDVUFE
    Plugin.swift

    View Slide

  27. #SJEHF'VODUJPO
    if (win.webkit && win.webkit.messageHandlers && win.webkit.messageHandlers.bridge) {
    // ios platform
    postToNative = function iosBridge(data) {
    data.type = 'message';
    win.webkit.messageHandlers.bridge.postMessage(data);
    };
    capacitor.isNative = true;
    capacitor.isIOS = true;
    capacitor.platform = 'ios';
    }
    capacitor/core/native-bridge.js

    View Slide

  28. 4Pʜ
    JOEFYIUNM #VOEMFKT OBUJWFCSJEHFKT
    1MVHJON
    1MVHJO I
    1MVHJOTXJGU
    TIPVME4UBSU-PBE8JUI3FRVFTU
    $IFDLSVOFOWJSPONFOU
    $BMM'VODUJPO

    View Slide

  29. +BWBUP)5.-+BWB4DSJQU

    View Slide

  30. 6TJOH$BQBDJUPS"OESPJE
    $ npx cap add android
    SFG
    /FX+BWB1SPKFDU

    View Slide

  31. 6TJOH$BQBDJUPS"OESPJE
    SFG
    /FX+BWB1SPKFDU

    View Slide

  32. .BJO"DUJWJUZFYUFOET#SJEHF"DUJWJUZ
    public class MainActivity extends BridgeActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Initializes the Bridge
    this.init(savedInstanceState, new ArrayList>() {{
    // Additional plugins you've installed go here
    // Ex: add(TotallyAwesomePlugin.class);
    }});
    }
    }
    MainActivity.java

    View Slide

  33. #SJEHF"DUJWJUZMPBET#SJEHF$MBTT
    protected void load(Bundle savedInstanceState) {
    Log.d(LogUtils.getCoreTag(), "Starting BridgeActivity");
    webView = findViewById(R.id.webview);

    pluginManager = mockWebView.getPluginManager();
    cordovaInterface.onCordovaInit(pluginManager);
    bridge = new Bridge(this, webView, initialPlugins, cordovaInterface, pluginManager,
    preferences);
    Splash.showOnLaunch(this);
    if (savedInstanceState != null) {
    bridge.restoreInstanceState(savedInstanceState);
    }
    this.keepRunning = preferences.getBoolean("KeepRunning", true);
    this.onNewIntent(getIntent());
    }
    MainActivity.java

    View Slide

  34. #SJEHF$MBTTMPBETXFCWJFX
    Bridge.java
    public class Bridge {

    public static final String DEFAULT_WEB_ASSET_DIR = "public";
    public static final String CAPACITOR_HTTP_SCHEME = "http";
    public static final String CAPACITOR_HTTPS_SCHEME = "https";
    public static final String CAPACITOR_FILE_START = "/_capacitor_file_";
    public static final String CAPACITOR_CONTENT_START = "/_capacitor_content_";
    public Bridge(Activity context, WebView webView, List>
    initialPlugins, CordovaInterfaceImpl cordovaInterface, PluginManager pluginManager,
    CordovaPreferences preferences) {
    this.context = context;
    this.webView = webView;
    this.initialPlugins = initialPlugins;
    this.cordovaInterface = cordovaInterface;
    this.preferences = preferences;

    this.loadWebView();
    }

    View Slide

  35. #SJEHF$MBTTMPBETXFCWJFX
    Bridge.java
    private void loadWebView() {
    appUrlConfig =
    Config.getString("server.url");
    String[]
    appAllowNavigationConfig =
    Config.getArray("server.allowN
    avigation");

    localUrl = scheme + "://" +
    authority;
    localServer = new
    WebViewLocalServer(context,
    this, getJSInjector(), authorities,
    html5mode);
    localServer.hostAssets(DEFAU
    LT_WEB_ASSET_DIR);

    View Slide

  36. )5.-+BWB4DSJQUUP+BWB

    View Slide

  37. 6TJOH$BQBDJUPS1MVHJO
    $ npx @capacitor/cli plugin:generate

    View Slide

  38. #SJEHF$MBTTJTl+BWB4DSJQU*OUFSGBDFz
    Bridge.java
    public Bridge(Activity context, WebView webView, List> initialPlugins,
    CordovaInterfaceImpl cordovaInterface, PluginManager pluginManager, CordovaPreferences
    preferences) {
    this.context = context;
    this.webView = webView;
    this.initialPlugins = initialPlugins;
    this.cordovaInterface = cordovaInterface;
    this.preferences = preferences;
    // Start our plugin execution threads and handlers
    handlerThread.start();
    taskHandler = new Handler(handlerThread.getLooper());
    Config.load(getActivity());
    // Initialize web view and message handler for it
    this.initWebView();
    this.msgHandler = new MessageHandler(this, webView, pluginManager);

    View Slide

  39. #SJEHF$MBTTJTl+BWB4DSJQU*OUFSGBDFz
    MessageHandler.java
    public class MessageHandler {
    private Bridge bridge;
    private WebView webView;
    private PluginManager cordovaPluginManager;
    public MessageHandler(Bridge bridge, WebView webView, PluginManager
    cordovaPluginManager) {
    this.bridge = bridge;
    this.webView = webView;
    this.cordovaPluginManager = cordovaPluginManager;
    webView.addJavascriptInterface(this, "androidBridge");
    }

    View Slide

  40. #SJEHF'VODUJPO
    if (win.androidBridge) {
    // android platform
    postToNative = function androidBridge(data) {
    win.androidBridge.postMessage(JSON.stringify(data));
    };
    capacitor.isNative = true;
    capacitor.isAndroid = true;
    capacitor.platform = 'android';
    }
    capacitor/core/native-bridge.js

    View Slide

  41. 4Pʜ
    JOEFYIUNM #VOEMFKT OBUJWFCSJEHFKT
    1MVHJOKBWB
    +BWB4DSJQU*OUFSGBDF
    $IFDLSVOFOWJSPONFOU
    $BMM'VODUJPO

    View Slide

  42. %FTDSJQUJPO

    View Slide

  43. 4Pʜ
    QVCMJD
    JOEFYIUNM
    8FC
    #SPXTFS
    J04
    "OESPJE
    63-3FRVFTU
    +BWB4DSJQU
    XFC7JFX MPBE SFRVFTU

    TIPVME4UBSU-PBE8JUI3FRVFTU
    XFC7JFXMPBE6SM BQQ6SM

    +BWB4DSJQU*OUFSGBDF

    View Slide

  44. .PCJMF%FWJDF"1*
    %5PVDI
    "##::3FBM5JNF
    3FDPHOJUJPO
    "&4
    "DUJPO4IFFU
    "E.PC'SFF
    "E.PC1MVT
    "E.PC1SP
    "EKVTU
    "ENPC
    "MJQBZ
    "OBMZUJDT'JSFCBTF
    "OESPJE&YP1MBZFS
    "OESPJE'JOHFSQSJOU
    "VUI
    "OESPJE'VMM4DSFFO
    "OESPJE
    1FSNJTTJPOT
    "OTXFST
    "OZMJOF
    "QQ"WBJMBCJMJUZ
    "QQ$FOUFS
    "OBMZUJDT
    "QQ$FOUFS
    $SBTIFT
    "QQ$FOUFS1VTI
    "QQ-BVODIFS
    #BTF
    #BUUFSZ4UBUVT
    #JP$BUDI
    #JPNFUSJD8SBQQFS
    #MJOL*E
    #MJOL6Q
    #MVFUPPUI4FSJBM
    #MVFUPPUI-&
    #SBJOUSFF
    #SBODI*P
    #SJHIUOFTT
    #SPBEDBTUFS
    #SPXTFS5BC
    $BMFOEBS
    $BMM%JSFDUPSZ
    $BMM-PH
    $BMM/VNCFS
    $BNFSB1SFWJFX
    $BNFSB
    $BSE*0
    $IPPTFS
    $MBTT,JU
    $MFWFS5BQ
    $MJQCPBSE
    $MPVE4FUUJOHT
    $PEF1VTI
    $PMPSFE#SPXTFS
    &NN"QQ$POpH
    &TUJNPUF#FBDPOT
    &YUFOEFE%FWJDF
    *OGPSNBUJPO
    '$.
    '51
    'BDFCPPL
    'JMF$IPPTFS
    'JMF&ODSZQUJPO
    'JMF0QFOFS
    'JMF1BUI
    'JMF5SBOTGFS
    'JMF
    'JOHFSQSJOU"*0
    'JSFCBTF"OBMZUJDT
    'JSFCBTF
    "VUIFOUJDBUJPO
    'JSFCBTF$POpH
    'JSFCBTF
    $SBTIMZUJDT
    'JSFCBTF%ZOBNJD
    -JOLT
    'JSFCBTF.FTTBHJOH
    'JSFCBTF9
    'JSFCBTF
    'JSFCBTF$SBTI
    'MBTIMJHIU
    )ZQFS5SBDL
    *#FBDPO
    *NBHF1JDLFS
    *NBHF3FTJ[FS
    *O"QQ#SPXTFS
    *O"QQ1VSDIBTF
    *O"QQ1VSDIBTF
    *O"QQ3FWJFX
    *OEFY"QQ$POUFOU
    *OTPNOJB
    *OTUBHSBN
    *OUFM4FDVSJUZ
    *OUFSDPN
    *POJD8FCWJFX
    *T%FCVH
    +JOT.FNF
    ,FZCPBSE
    ,FZDIBJO5PVDI*E
    ,FZDIBJO
    -BTU$BN
    -BVODI/BWJHBUPS
    -BVODI3FWJFX
    -JOF-PHJO
    -PDBM/PUJpDBUJPOT
    -PDBUJPO"DDVSBDZ
    -PUUJF4QMBTI
    4DSFFO
    0QFO/BUJWF
    4FUUJOHT
    0QFO"-13
    1BZ1BM
    1FEPNFUFS
    1IPOFHBQ-PDBM
    /PUJpDBUJPO
    1IPUP-JCSBSZ
    1IPUP7JFXFS
    1JO$IFDL
    1JO%JBMPH
    1JOUFSFTU
    1PXFS.BOBHFNFOU
    1SFWJFX"OZ'JMF
    1SJOUFS
    1SP
    1VSDIBTFT
    1VTI
    224%,
    234DBOOFS
    2VJLLMZ1MVHJO
    3FHVMB%PDVNFOU
    3FBEFS
    3PMMCBS
    4.4
    42-JUF1PSUFS
    42-JUF
    4UBS13/5
    4UBUVT#BS
    4UFQDPVOUFS
    4USFBNJOH.FEJB
    4USJQF
    4VN6Q
    5BQUJD&OHJOF
    5FBMJVN
    5FBMJVN"E*EFOUJpFS
    5FBMJVN*OTUBMM3FGFSS
    FS
    5FYU5P4QFFDI
    5IFNF%FUFDUJPO
    5IFNFBCMF#SPXTFS
    5PBTU
    5PVDI*%
    5XJUUFS$POOFDU
    6JE
    6OJRVF%FWJDF*%
    6OWJSFE$PSEPWB
    4%,
    6QUJNF
    6SCBO"JS4IJQ
    6TFS"HFOU
    7JCSBUJPO
    7JEFP$BQUVSF1MVT
    7JEFP&EJUPS

    View Slide

  45. 8FCJT.BJO8FC7JFXPOMZ
    *GUIJTJTTMPX XFCJONPCJMFJTBMMTMPX
    8FDBOBDDFTT4XJGUBOE+BWB$PEFGSPN+BWB4DSJQU 8JOEPX0CKFDU

    8FDBODSFBUF/BUJWF7JFXBOEUPCFBCMFDPOUSPMGSPN/BUJWF$PEF

    View Slide

  46. *GZPVJOUFSFTUFEJO.PCJMF%FWJDF
    ZPVTIPVMEVTF$BQBDJUPS

    View Slide

  47. %PZPVXBOU.PCJMF"QQ6*
    'SBNFXPSL
    $PNQBUJCJMJUZ
    lOPOMJOFBS
    OBWJHBUJPO
    .PCJMF6*
    /BWJHBUJPO
    4UBDL

    View Slide

  48. /FFE.PCJMF"QQ6*.PCJMF6*
    .PCJMF6TFS*OUFSGBDF

    View Slide

  49. /FFE.PCJMF"QQ6*'SBNFXPSL$PNQBUJCJMJUZ
    'SBNFXPSL$PNQBUJCJMJUZ
    ʮίϯύνϏϦςΟͱ͸ɺϋʔυ΢ΣΞ΍ιϑτ΢ΣΞ͕ɺ࢓༷ͷҟͳΔ΋ͷʹஔ͖
    ׵͑ΒΕ্ͨͰ΋ɺݩ௨Γͷಈ࡞Λ͢Δͱ͍͏ঢ়ଶͷ͜ͱͰ͋Δʯ

    View Slide

  50. /FFE.PCJMF"QQ6*lOPOMJOFBSOBWJHBUJPO
    lOPOMJOFBSOBWJHBUJPO

    View Slide

  51. /FFE.PCJMF"QQ6*/BWJHBUJPO4UBDL
    /BWJHBUJPOTUBDL

    View Slide

  52. *POJD'SBNFXPSL

    View Slide

  53. /PUPOMZPOF8IJDIpSTU8FC18"PS.PCJMF
    IUUQTXXXBGQCCDPNBSUJDMFT

    View Slide

  54. $SFBUF.PCJMF"QQTVTJOH*POJD
    IUUQTBN[OUP1"S&M

    View Slide