Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

!SEMBCPDBQBDJUPSGBDFCPPLMPHJO

Slide 5

Slide 5 text

!SEMBCPDBQBDJUPSBENPC

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

8IBUJT$BQBDJUPS

Slide 8

Slide 8 text

$BQBDJUPS

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

%J⒎FSFODFPG3FBDU/BUJWF/BUJWF4DSJQU

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

6TJOH$BQBDJUPS )PX

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

4XJGUUP)5.-+BWB4DSJQU

Slide 16

Slide 16 text

6TJOH$BQBDJUPSJ04 DPNQBSF/FX4XJGU1SPKFDU SFG /FX4XJGU1SPKFDU

Slide 17

Slide 17 text

/FX4XJGU1SPKFDUˠ#MBOL

Slide 18

Slide 18 text

$BQBDJUPSJ041SPKFDUˠ$"1#SJEHF7JFX$POUSPMMFS

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

$"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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

/PU.VTUSFRVJSF41" 4BNF0SJHJO0OMZ JOEFYIUNM OFYUIUNM UIJSETIUNM #VU"QQNVTUMPBEBTTFUTpMFFWFSZUJNF

Slide 23

Slide 23 text

)5.-+BWB4DSJQUUP4XJGU

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

6TJOH$BQBDJUPS1MVHJO TIPVME4UBSU-PBE8JUI3FRVFTU

Slide 26

Slide 26 text

TIPVME4UBSU-PBE8JUI3FRVFTU 1MVHJOI1MVHJON w "EE$VTUPN63-4DIFNF w "EELFZUP8JOEPX0CKFDUJO8FC7JFX w FY XJOXFCLJUNFTTBHF)BOEMFSTCSJEHFQPTU.FTTBHF BSH *GBQQBDDFTT8JOEPX 0CKFDU VTJOHBSH UIJTpMF XJMMCFFYFDVUFE Plugin.swift

Slide 27

Slide 27 text

#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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

+BWBUP)5.-+BWB4DSJQU

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

6TJOH$BQBDJUPS"OESPJE SFG /FX+BWB1SPKFDU

Slide 32

Slide 32 text

.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

Slide 33

Slide 33 text

#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

Slide 34

Slide 34 text

#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(); }

Slide 35

Slide 35 text

#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);

Slide 36

Slide 36 text

)5.-+BWB4DSJQUUP+BWB

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

#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);

Slide 39

Slide 39 text

#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"); }

Slide 40

Slide 40 text

#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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

%FTDSJQUJPO

Slide 43

Slide 43 text

4Pʜ QVCMJD JOEFYIUNM 8FC #SPXTFS J04 "OESPJE 63-3FRVFTU +BWB4DSJQU XFC7JFX MPBE SFRVFTU TIPVME4UBSU-PBE8JUI3FRVFTU XFC7JFXMPBE6SM BQQ6SM +BWB4DSJQU*OUFSGBDF

Slide 44

Slide 44 text

.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

Slide 45

Slide 45 text

8FCJT.BJO8FC7JFXPOMZ *GUIJTJTTMPX XFCJONPCJMFJTBMMTMPX 8FDBOBDDFTT4XJGUBOE+BWB$PEFGSPN+BWB4DSJQU 8JOEPX0CKFDU 8FDBODSFBUF/BUJWF7JFXBOEUPCFBCMFDPOUSPMGSPN/BUJWF$PEF

Slide 46

Slide 46 text

*GZPVJOUFSFTUFEJO.PCJMF%FWJDF ZPVTIPVMEVTF$BQBDJUPS

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

/FFE.PCJMF"QQ6*lOPOMJOFBSOBWJHBUJPO lOPOMJOFBSOBWJHBUJPO

Slide 51

Slide 51 text

/FFE.PCJMF"QQ6*/BWJHBUJPO4UBDL /BWJHBUJPOTUBDL

Slide 52

Slide 52 text

*POJD'SBNFXPSL

Slide 53

Slide 53 text

/PUPOMZPOF8IJDIpSTU8FC18"PS.PCJMF IUUQTXXXBGQCCDPNBSUJDMFT

Slide 54

Slide 54 text

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