ãŸããã mediba ã¡ãã£ã¢ã·ã¹ãã éçºéš ãã€ã³ãéçºGã®äœè€çŠç« ãšç³ããŸããã¹ããŒããã©ã³åãã®ãã€ãã£ãã¢ããªãæ§ç¯/éçšããŠããŸãã ä»åã®ãšã³ããªã§ã¯ Apache Cordova ã®äžã§ Vue.js ãå©çšã㊠Amazon AWS ã®æ©èœãåŒã³åºããŠã¿ãŸãã å©çšãããããã¯ãã®çŽ¹ä» Apache Cordova http://cordova.apache.org/ ããšããš Adobe ã®ãããã¯ãã§ã PhoneGap ãšèšãããŠããŸããã Apache ã«å¯èŽãããŠååãå€ãããŸããã ã¢ããªã®æ§ç¯ã HTML + CSS + JavaScript ã§å®çŸããŠããŸããããšããã¶ã£é£ãã çºæ³ã§ããã[ã¢ããªã®äžã«ãã©ãŠã¶ãå«ããŠããŸãããã®äžã§ HTML / JavaScript / CSS ãåãã]ãšããææ³ã§å®çŸããŠããŸãããªã®ã§ããã©ãŠã¶ã§åºæ¥ãããšã¯å€§æŠãåºæ¥ãŸãã ãŸãããã«ããã©ãããã©ãŒã 察å¿ãç¹åŸŽã§ã iOS / Android / WindowsPhone / Firefox OS / Blackberry ãªã©ãªã©ãæ§ã
ãªãã©ãããã©ãŒã åãã«ãã€ãã£ãã¢ããªãšããŠãã«ãã§ããŸãã ãã€ãã£ãã¢ããªç¹æã®æ©èœ(ã«ã¡ã©ãGPSãªã©)ã«ã€ããŠã¯ããã©ãããã©ãŒã ããšã«ãã©ã°ã€ã³ãšãã圢ã§å®è£
ããããšã§ããã®å·®ç°ãåžåããŠããŸãã ã¬ãã¬ãã®ã²ãŒã ã§ãã£ããã¹ããŒããã©ã³ã®çްããæ©èœãæäœããããããããªçšéã«ã¯åããŸããããã«ããŒã§ããç¯å²ã¯æ³å以äžã«åºãã§ãã Vue.js http://jp.vuejs.org/ JavaScript ã® MVVM ãã¬ãŒã ã¯ãŒã¯ã§ããã€ãå
æ¥ã 1.0 ããªãªãŒã¹ãããŸããã MVVM ãšã¯ Model - View - ViewModel ãšããèãæ¹ã§ã Model ã¯ããŒã¿ãã®ãã®ã View ã¯èŠãç®ã®å®çŸ©ã ViewModel ã®ãšãããã Model ãš View ã®åæ¹ãçµã³ã€ããŠç®¡çããŠããããã¿ãããªä»çµã¿ã§ãã Model ââ ViewModel ââ View View ã®åŽã§ç¶æ
ãå€ãã£ãŠãã¡ãããš Model ã«åæ ããŠããããã Model ã®åŽã§ç¶æ
ãå€ãã£ãŠã View ã®åŽã«ã¡ãããšåæ ããŠãããã®ã§ãåããèŠãŠãŠé¢çœãã§ãã ä»åãèŠãç®ã®å®çŸ©ãšéåæã§ã®ããŒã¿æŽæ°ã«å©çšããŸãã AWS SDK https://aws.amazon.com/jp/sdk-for-browser/ ã¿ããªå€§å¥œã Amazon AWS ã®ãµãŒãã¹ãããã°ã©ã èšèªããåŒãããã®ãããã§ãã ä»å㯠AWS SDK for JavaScript ã䜿çšãã Cognito ãš S3 ãå©çšããŸãã æ¬æ¥ãã©ãŠã¶ããåãããã®ã§ããã Cordova ã§ãã¡ãããšåãã®ãã©ããã æºå npm ãå®è¡ã§ããç°å¢ãçšæããŠäžããã Mac ã§ããã° brew install node ã§ npm ã®ç°å¢ããŸãšããŠå°å
¥ã§ããŸãã Cordovaã®ã€ã³ã¹ããŒã« äžèšã®ããã«ããŠã npm ãã cordova ãã€ã³ã¹ããŒã«ããŠäžããã $ npm install -g cordova ããã§ cordova ã³ãã³ãããŒã«ãå©çšå¯èœã«ãªããŸãã ãã®ã³ãã³ãããŒã«ãå©çšããŠãã¢ããªã±ãŒã·ã§ã³ã®éªšæ Œäœæãããã«ããŸã§è¡ããŸãã ã¢ããªã®ã¹ã±ã«ãã³äœæ ãŸããããŒã¹ãäœããŸããããã±ãŒãžåãªã©ããã®æã«æå®ããŸãã $ cordova create cordovatest jp.mediba.ysato.cordovatest CordovaTest cordova create [ãã£ã¬ã¯ããªå] [ããã±ãŒãžå] [ã¢ããªã±ãŒã·ã§ã³å] ãšããæå®ã®ä»æ¹ã§ãã æå®ãããã£ã¬ã¯ããªã®äžã«ããããªæãã§ãã¡ã€ã«ãçæãããŸãã ç¶ããŠããã©ãããã©ãŒã ã远å ããŸãã ããã§è¿œå ãããã©ãããã©ãŒã åãã¢ããªã±ãŒã·ã§ã³ããã«ããããããšã«ãªããŸãã $ cordova platform add ios $ cordova platform add android 远å ã§ãããã©ãããã©ãŒã ã«ã€ããŠã¯ãäžèšãåç
§äžããã Firefox OS ãšã Blackberry ãšãã察象ã«åºæ¥ãŸãã https://cordova.apache.org/docs/en/4.0.0/guide/support/index.html ã¢ããªãå®è¡ å®è¡ããæã¯ãã³ãã³ãã©ã€ã³ããäžèšã®ããã«ããŸãã $ cordova run cordova run ã ãã§åŒæ°ãæå®ããªããšãæå¹ã«ãªã£ãŠããå
šãŠã®ãã©ãããã©ãŒã ã«ãŠåããããšããŠãããŸããå
ã®äŸã§ããã°ã Android ãš iOS ã§ããã $ cordova run android ãªã©ãšæå®ããã°ããã®ãã©ãããã©ãŒã ã®åã ãããã«ã/å®è¡ããŠãããŸãã cordova create ããã ãã®ç¶æ
ã§ã¿ãŒã²ããã iOS ãšã㊠run ãããšããããªãµã³ãã«ãåããŸãã ããããã Cordova ã®äžçãžã JSå€éšã©ã€ãã©ãªãCordovaã§äœ¿ã ã§ã¯æ©éãã¢ããªãäœã£ãŠã¿ãŸãããã äœã AWS é¢é£ã«ã€ããŠã¯ã¡ãã£ãšçœ®ããŠãããŠãããã§ã¯[èªçæ¥ãæå®ãããã仿¥ãã30æ¥åŸãŸã§ã®ãã€ãªãªãºã ãã°ã©ãã§åºåãã]ãšããã¢ããªãäœã£ãŠã¿ãŸãã ã°ã©ãåºåã«ã¯ ccchart ã䜿çšããŸããããŒã¿ãJSONã§çŸ
åããã ãã§çŸéºãªã°ã©ããæããŠãããã䟿å©ãªã©ã€ãã©ãªã§ãã ã³ãŒã <script src="./js/vue.min.js"></script><ul id="biorythm"><li>èªçæ¥: <input type="date"></li> <li>身äœ: {{physical}}</li> <li>ææ
: {{sensitive}}</li> <li>ç¥æ§: {{intel}}</li> </ul><canvas id="biograph"></canvas><script src="./js/biorythm.js"></script> // èªçæ¥èšå®ãã©ãŒã éšåãšæŽæ°åŠç var biorythm = new Vue({ el: '#biorythm', lazy: true, data: { birthday: '1976-03-30', physical: 0, sensitive: 0, intel: 0, }, methods: { // 仿¥ã®ãã€ãªãªãºã ããŒã¿ã§æŽæ° // åŒæ° : èªçæ¥ update: function(){ birthday = biorythm.birthday; var bio_today = new Bio(birthday,new Date()); biorythm.physical = bio_today.physical; biorythm.sensitive = bio_today.sensitive; biorythm.intel = bio_today.intel; update_chart(birthday); } } }) // DOM倿Žãæ€ç¥ biorythm.$watch('birthday', function(value, mutation){ biorythm.update(); }); // ccchart ã®ã°ã©ãå®çŸ© // data: ã«æç»ããèŠçŽ ãé
åã§æå®ãã // ccchart.init(ãã£ã³ãã¹ID, å®çŸ©ããŒã¿) ã§å®éã«ã°ã©ããæç»ãã var chartdata6 = { "config": { "width": 320, "height": 240, "xScaleFont": "100 6px 'Arial'", "yScaleFont": "100 6px 'Arial'", "hanreiFont": "100 6px 'Arial'", "colorSet": ["#F00","#0F0","#00F"], }, "data": [[],[],[],[]] }; // ccchart ã°ã©ãããŒã¿(仿¥ãã30æ¥åŸãŸã§)ã®æŽæ° // åŒæ° : èªçæ¥ function update_chart(birthday){ chartdata6.data[0].length=0; chartdata6.data[0].push("æ¥"); chartdata6.data[1].length=0; chartdata6.data[1].push("身äœ"); chartdata6.data[2].length=0; chartdata6.data[2].push("ææ
"); chartdata6.data[3].length=0; chartdata6.data[3].push("ç¥æ§"); for(var i=0;i<30;i++){ var today = new Date(); var dateChart = new Date(today.getTime() + i * 1000*60*60*24) ; var dateChartBio = new Bio(birthday,dateChart.getTime()); chartdata6.data[0].push(dateChart.getDate()); chartdata6.data[1].push(dateChartBio.physical); chartdata6.data[2].push(dateChartBio.sensitive); chartdata6.data[3].push(dateChartBio.intel); } ccchart.init('biograph', chartdata6); } // ãã€ãªãªãºã èšç® // åŒæ° : èªçæ¥ , åºæºæ¥ function Bio(birthday,basedate){ dateDiff = (new Date(basedate) - new Date(birthday)) / 1000/60/60/24; dateDiff = Math.floor(dateDiff); var bioNumer = 2 * Math.PI * dateDiff; this.physical = Math.round( Math.sin( bioNumer / 23 ) * 10000) / 10000; this.sensitive = Math.round( Math.sin( bioNumer / 28 ) * 10000) / 10000; this.intel = Math.round( Math.sin( bioNumer / 33 ) * 10000) / 10000; } // æŽæ°åŠçãäžåèµ°ãããŠã°ã©ããæžããã biorythm.update(); çµæ DOM æäœãã€ãã³ããã³ããªã³ã°ãŸã§ãã Vue.js ãã Canvas æç»ãŽãªãŽãªãã ccchart ãã Cordova ã®äžã§åé¡ãªãåããŸãããæ¬åœã«äœã®åé¡ãèµ·ããªãã£ãã®ã§ãéã«é©ããŸããã å
šãåããã¡ã€ã«ã Google Chrome ãªã©ã§è¡šç€ºããŠãããã£ã±ãã¡ãããšå®è¡ã§ããŸããåããã®ã§ãããâŠ. Vue.js ã«ã€ã㊠ä»å Vue.js ã«ã¯ãäžèšã®åœ¹å²ãæ
ã£ãŠããããŸããã èªçæ¥ãæå®ãããã©ãŒã ã®å€ãç£èŠãã倿Žããããã³ã«ã€ãã³ããçºè¡ãã 第äžåŒæ°ã«ç£èŠããèŠçŽ ã第äºåŒæ°ãã³ãŒã«ããã¯ã«ãªãã®ã§ç¡å颿°ã§åŠçãæžããã¿ãããªäœ¿ãããã«ãªããŸãã vm.$watch('datakey', function(value, mutation){ // codes }); vm ãšãã Vue ãªããžã§ã¯ãã«ãã㊠vm.$watch ã§ datakey ãç£èŠãããŸãã 倿Žãçºçãããšã value ã«å€ãå
¥ãã mutation ã«ã¯å€æŽã«é¢ããæ
å ±(method, args, result, inserted, removed)ãå
¥ããŸãã ä»å㯠Vue.js ã®äžã«æžããã¡ãœãããåŒã³ãæŽæ°åŠçãèµ°ãããŠããŸãã èªçæ¥ã®å€æŽã«ãã£ãŠåèšç®ããã[身äœ][粟ç¥][ç¥æ§]ã®ãã€ãªãªãºã å€ãç»é¢ã«åæ ãã <div id="vm">{{parts}} <script type="text/javascript"> var vm = new Vue({ data: { parts: 0, } } </script> ãããªé¢šã«å®çŸ©ããŠããããšãVue.js ã HTML åŽã® {{parts}} ãš JavaScript åŽã® vm.parts ãçµã³ã€ããŠãããŸãã ãããããšã JavaScriptåŽã§ vm.parts = 1 ãªã©ãšããŠå€ã倿Žããæã«ã HTML åŽãèªåã§æžãæããŠãããããã§ãã ãã©ãŒã ã«é¢ããŠã¯ã¡ãã£ãšç¹æ®ã§ã <input> ãªã©ãš v-model ãšãããã£ã¬ã¯ãã£ãã䜿çšããå¿
èŠããããŸãã ccchart ã«ã€ã㊠解説ãããããªæã¯ãããŸããªãã®ã§ããã ccchart ã§ã°ã©ããæžãããã«ããããšã¯ããã£ãããšäžèšã«ãªããŸããç°¡åã HTML å
ã«ã°ã©ããæç»ãã canvas ãçšæãã ã°ã©ãã®å
容ãšããŒã¿ãå®çŸ©ãã JSON ãçšæãã æç»åŠçãåŒã³åºã http://ccchart.com/ ã«ã¯ã°ã©ãã®çš®é¡ãå®éã®æžãæ¹ãªã©ã«ã€ããŠããµã³ãã«ã³ãŒããšå®è¡äŸãè±å¯ã«äžŠãã§ããŸãã æ ªäŸ¡æ
å ±ã¿ãããªãã£ãŒããåºããããªã¢ã«ã¿ã€ã ã«æ
å ±ãœãŒã¹ãããŒãªã³ã°ããããšæ§ã
ãªããšãåºæ¥ãŸãã®ã§ããŸãã¯ãµã€ãã®æ¹ãèŠããŠã¿ãŠãã ããã AWS SDK for JavaScriptã䜿ã äºåã®æ³šæ iOSã«éã£ã話ãªã®ã§ããã ATS(Application Transport Security) ãšããæ©èœãiOS ã«å ããããã®å¯äœçšãšã㊠http ã¢ã¯ã»ã¹ãå
šéš https ã«å·®ãæ¿ããããããã AWS ã® API ã¢ã¯ã»ã¹ãå
šãŠ https ã«å·®ãæ¿ãã *.amazonaws.com ã®èšŒææžãSHA-1ãªã®ã§ãã»ãã¥ãªãã£ã¬ãã«äœããšã¢ã¯ã»ã¹ããããã¯ããã ãšããäºè±¡ãçºçããŸããçµæã iOS äžã® Cordova ãã AWS SDK for JavaScript ã䜿çšåºæ¥ãªãç¶æ
ã«ãªããŸãã https://mobile.awsblog.com/post/Tx2QM69ZE6BGTYX/Preparing-Your-Apps-for-iOS-9 http://dev.classmethod.jp/smartphone/iphone/ios-9-intro-ats/ åé¿æ¹æ³ã¯ã Cordova ãçæãã iOS åããã«ãçšã®ãœãŒã¹äžåŒã®äžã«ããã info.plist ãç·šéããåœè©²ãã¡ã€ã³ã®ATSãç¡å¹ã«ããããšã äœãã Apple ãçšæããã»ãã¥ãªãã£ã®ä»çµã¿ãè¿åãããã»ãã¥ãªãã£ã¬ãã«ãäžããããšã«ãªããããããçè§£ããäžã§äœ¿çšããŠäžããã NSAppTransportSecurity NSExceptionDomains amazonaws.com NSThirdPartyExceptionMinimumTLSVersion TLSv1.0 NSThirdPartyExceptionRequiresForwardSecrecy NSIncludesSubdomains åæºå Cordova ããå€éšã®ãªãœãŒã¹ã«ã¢ã¯ã»ã¹ããéã¯ã Content-Security-Policy ã«ãŠã¢ã¯ã»ã¹å
ã®æå®ãè¡ãå¿
èŠããããŸãããã¯ã€ããªã¹ã圢åŒã§ããã Cordova ãçæããŠããã HTML ã«ã¯åºæ¬çãªããªã·ãæ¢ã«èšèŒãããŠããŸãããå€éšãµãŒãã®ãªãœãŒã¹ãªã©ãå©çšãããå Žåã¯ãéæèš±å¯ãæžããŠãããå¿
èŠããããŸãã Amazon AWS ãžã®ã¢ã¯ã»ã¹ãèš±å¯ããå Žåã¯ãäžèšã®ããã«ãªããŸãã <meta content="connect-src https://*.amazonaws.com/"> JQuery ãªã©ãCDNããèªã¿èŸŒãããã«ãããå€éšã®ããŒã¿ããªãœãŒã¹ãšããŠäœ¿çšãããçã®å Žåã«ãã Content-Security-Policy ã¯éãããã«ããŠãããŠãããªããšãããŸããã Content-Security-Policy ã®è©³çްã«ã€ããŠã¯ãäžèšãµã€ããåç
§äžããã http://content-security-policy.com/ ã³ãŒã <div id="s3list_vue"> <ul><li> </ul></div> <script src="./js/awssample.js"></script> var loginCognito = function(){ AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:xxxx' }); } var getS3Buckets = function(){ var filelist = []; var s3bucketname = 'BUCKETNAME'; var s3 = new AWS.S3({region: 'ap-northeast-1', maxRetries: 15}); s3.listObjects({Bucket: s3bucketname}, function(error, data) { if (error) { console.log("S3 Error : " + error); } else { var targetNode = document.getElementById('s3list'); for(var i = 0 ; i < data.Contents.length ; i++){ var params = {Bucket: s3bucketname, Key: data.Contents[i].Key}; s3list_vue.s3list_vue_parts.push({ url: s3.getSignedUrl('getObject', params) , filename: data.Contents[i].Key , }); } } }); } var s3list_vue = new Vue({ el: '#s3list_vue', template: '{{filename}}', replace: true, data: { s3list_vue_parts: [], }, methods: { onClick: function (getter) { var ref = cordova.InAppBrowser.open(getter, '_blank', 'location=yes'); } } }) loginCognito(); getS3Buckets(); çµæ S3ã®æ¹ã«ããããªãµãã«ãã¡ã€ã«ãèšçœ®ããŠãããŸãã S3 ãã±ãããªã¹ã ç»åã InAppBrowser ã§è¡šç€º 解説 AWSåšã èŠãŠã®éãã§ããã loginCognito() ã§ AWS ã® Cognito ã«ãã°ã€ã³ããŠããŸããäœã®ããããšãããšãS3ãžã¢ã¯ã»ã¹ããããã® Credential ãååŸããããã§ãã Cognito èªäœã®è§£èª¬ã«ã€ããŠã¯æ¬å®¶ã® https://aws.amazon.com/jp/cognito/ ãªã©ããæç¹°ããŸããã Cognito èªèšŒã®çµæã«å¿ããŠæ§ã
ãªããŒã«ãå²ãä»ããããããã AWS ã®åçš®ã³ã³ããŒãã³ããžã®ã¢ã¯ã»ã¹èš±å¯ãåºããšãã«äŸ¿å©ã§ãã ã³ã¬ãç¡ãã£ãé 㯠AccessToken / SecretToken ã®å¯Ÿã§å¶åŸ¡ããŠãŸãããã ã§ãååŸãã Credential ã䜿çšããŠã getS3Buckets() ã§ S3 ãã±ããã®äžèº«ãååŸã衚瀺ããŠããŸãã listObjects() ã®ã³ãŒã«ããã¯ã§çµæãååŸããŠã Vue ã§å®çŸ©ããŠããã¢ãã«ã«äžã€äžã€ push ããã ãã è¡šç€ºã®æŽæ°ã¯ Vue ã«ä»»ããŠããŸããåæ¹åãã€ã³ãã£ã³ã°ã°ãããã InAppBrowser ãŸãããã¡ã€ã«åãã¿ããããæã«éããŠããã®ã¯ã InAppBrowser ãšããã Cordova ãçšæããã¢ããªå
ãã©ãŠã¶ã§ãã Cordova ã®äžã§ãéããã®ã§ãããå
ã«èª¬æãã Content-Security-Policy ã®å¶éãåããŸãã®ã§ãããããå¶éãç¡ããããå Žå㯠InAppBrowser ã䜿ãããšãå€ãããã§ãã Vue ã® v-on ãã£ã¬ã¯ãã£ãã§ã¿ããæã« onClick() ã¡ãœãããåŒã¶ããå®çŸ©ãããã®äžã§ cordova.InAppBrowser.open() ã«ãŠ InAppBrowser ãåŒã³åºããŠããŸãã open() ã®ç¬¬äºåŒæ°ã«ãã£ãŠãäžèšã®ããã«æåãå€ãããŸãã _self - URL ããã¯ã€ããªã¹ãã«ããå Žå㯠Cordova ã® WebView ã§ãããã§ãªããã° InAppBrowser ã§éã (ããã©ã«ã) _blank - åžžã« InAppBrowser ã§éã _system - åžžã«ã·ã¹ãã ã® Web ãã©ãŠã¶ã§éã ãŸãšã ã¹ããŒããã©ã³ã§ã®ã¯ãã¹ãã©ãããã©ãŒã éçºãæ€èšããéã«å¿
ãç®ã«ãã Cordova ã§ããããããŒã JavaScript ã§å¶åŸ¡ãããšãåãé¢åããã JQuery ãšã DOM ãšãåãã£ãŠãªããšãã¡ãªãã§ãããŒããšãé£ããå«ããããŠãããŸããã ã§ãå®éã«ãã£ãŠã¿ããšã Vue.js ãšãããã¬ãŒã ã¯ãŒã¯ã®åŒ·åããçžãŸã£ãŠããããç°¡åã«ããããäºãæžããããã«ãªã£ãŠããŠããããšãç¥ããŸãããé£ããå«ããããªãã ãã¡ãããã€ãã£ãã«æ¯ã¹ããåºæ¥ãããšã¯éãããŸãããããã§ã[äžåæžãããã©ã£ã¡ã§ãåã]äºãèãããšãæ¡ä»¶æ¬¡ç¬¬ã§ã¯æ¡çšããã¡ãªããã¯çžåœããããã ãããšæã£ãŠããŸãã ã¿ãªããããéžå®ã®éžæè¢ã«1ã€ã Cordova ãåŠäœã§ãããïŒ