diff --git a/.gitignore b/.gitignore index a6fae280..00c5fc41 100755 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /node_modules /platforms /resources +/plugins /www # IDEs and editors @@ -41,4 +42,4 @@ testem.log #System Files .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db diff --git a/.sourcemaps/0.js.map b/.sourcemaps/0.js.map old mode 100644 new mode 100755 diff --git a/.sourcemaps/1.js.map b/.sourcemaps/1.js.map old mode 100644 new mode 100755 index 276e42dc..abc95a80 --- a/.sourcemaps/1.js.map +++ b/.sourcemaps/1.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../node_modules/@angular/http/esm5/http.js"],"names":["normalizeMethodName","method","toUpperCase","RequestMethod","Get","Post","Put","Delete","Options","Head","Patch","Error","standardEncoding","v","encodeURIComponent","replace","_getJsonpConnections","w","window","_jsonpConnections","JSONP_HOME","httpRequest","backend","request","createConnection","response","mergeOptions","defaultOpts","providedOpts","url","newOptions","merge","RequestOptions","search","params","headers","body","withCredentials","responseType","_createDefaultCookieXSRFStrategy","CookieXSRFStrategy","httpFactory","xhrBackend","requestOptions","Http","jsonpFactory","jsonpBackend","Jsonp","__WEBPACK_IMPORTED_MODULE_3__angular_platform_browser__","__webpack_require__","BrowserXhr","prototype","build","XMLHttpRequest","decorators","type","__WEBPACK_IMPORTED_MODULE_0__angular_core__","ctorParameters","ReadyState","Unsent","Open","HeadersReceived","Loading","Done","Cancelled","ResponseType","Basic","Cors","Default","Opaque","ContentType","NONE","JSON","FORM","FORM_DATA","TEXT","BLOB","ARRAY_BUFFER","ResponseContentType","Text","Json","ArrayBuffer","Blob","Headers","_this","this","_headers","Map","_normalizedNames","forEach","values","name","value","append","Object","keys","Array","isArray","delete","fromResponseHeaderString","headersString","split","line","index","indexOf","name_1","slice","trim","set","getAll","push","lcName","toLowerCase","fn","get","length","has","from","join","mayBeSetNormalizedName","toJSON","serialized","apply","entries","ResponseOptions","opts","status","statusText","options","BaseResponseOptions","_super","call","__WEBPACK_IMPORTED_MODULE_1_tslib__","ConnectionBackend","Connection","XSRFStrategy","isSuccess","QueryEncoder","encodeKey","k","encodeValue","URLSearchParams","rawParams","queryEncoder","paramsMap","map","param","eqIdx","_a","key","val","list","paramParser","clone","appendAll","storedParam","setAll","searchParams","i","replaceAll","toString","paramsList","Body","json","_body","parse","text","encodingHint","String","fromCharCode","Uint16Array","Uint8Array","stringify","arrayBuffer","input","view","strLen","charCodeAt","buffer","stringToArrayBuffer","blob","Response","responseOptions","ok","_nextRequestId","BrowserJsonp","node","document","createElement","src","nextRequestID","requestCallback","id","exposeConnection","connection","removeConnection","send","appendChild","cleanup","parentNode","removeChild","JSONP_ERR_NO_CALLBACK","JSONP_ERR_WRONG_METHOD","JSONPConnection","req","_dom","baseResponseOptions","_finished","TypeError","__WEBPACK_IMPORTED_MODULE_2_rxjs_Observable__","responseObserver","readyState","_id","callback","lastIndexOf","substring","script","_script","onLoad","event","responseOptions_1","error","_responseData","next","complete","onError","message","addEventListener","removeEventListener","finished","data","JSONPBackend","_browserJSONP","_baseResponseOptions","XSSI_PREFIX","XHRConnection","browserXHR","_xhr","open","responseText","getAllResponseHeaders","xhr","responseURL","test","getResponseHeader","getResponseURL","err","setDetectedContentType","setRequestHeader","getBody","abort","contentType","_cookieName","_headerName","configureRequest","xsrfToken","getCookie","XHRBackend","_browserXHR","_xsrfStrategy","_mergeSearchParams","defineProperty","enumerable","configurable","_parseParams","objParams","item","_appendParam","BaseRequestOptions","Request","paramsArg","element","urlEncodeParams","prefix","detectContentType","ArrayBuffer$1","detectContentTypeFromBody","FormData","Blob$1","noop","_backend","_defaultOptions","responseObservable","post","put","patch","head","defaultOptions","HttpModule","args","providers","provide","useFactory","deps","useClass","JsonpModule","VERSION"],"mappings":"mDAirBA,SAAAA,EAAAC,GACA,GAAA,iBAAAA,EACA,OAAAA,EACA,OAAAA,EAAAC,eACA,IAAA,MACA,OAAAC,EAAAC,IACA,IAAA,OACA,OAAAD,EAAAE,KACA,IAAA,MACA,OAAAF,EAAAG,IACA,IAAA,SACA,OAAAH,EAAAI,OACA,IAAA,UACA,OAAAJ,EAAAK,QACA,IAAA,OACA,OAAAL,EAAAM,KACA,IAAA,QACA,OAAAN,EAAAO,MAEA,MAAA,IAAAC,MAAA,uCAAAV,EAAA,uBAuFA,SAAAW,EAAAC,GACA,OAAAC,mBAAAD,GACAE,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KACAA,QAAA,QAAA,KAubA,SAAAC,IACA,IAAqBC,EAAA,iBAAAC,OAAAA,UAIrB,OAHA,OAAAC,IACAA,EAAAF,EAAAG,OAEAD,EAu9BA,SAAAE,EAAAC,EAAAC,GACA,OAAAD,EAAAE,iBAAAD,GAAAE,SASA,SAAAC,EAAAC,EAAAC,EAAA3B,EAAA4B,GACA,IAAqBC,EAAAH,EACrB,OAE4BG,EAAAC,MAAA,IAAAC,EAF5BJ,GAGA3B,OAAA2B,EAAA3B,QAAAA,EACA4B,IAAAD,EAAAC,KAAAA,EACAI,OAAAL,EAAAK,OACAC,OAAAN,EAAAM,OACAC,QAAAP,EAAAO,QACAC,KAAAR,EAAAQ,KACAC,gBAAAT,EAAAS,gBACAC,aAAAV,EAAAU,eAGkErC,OAAAA,EAAA4B,IAAAA,KA8VlE,SAAAU,IACA,OAAA,IAAAC,EAOA,SAAAC,EAAAC,EAAAC,GACA,OAAA,IAAAC,EAAAF,EAAAC,GAOA,SAAAE,EAAAC,EAAAH,GACA,OAAA,IAAAI,EAAAD,EAAAH,83CAhkFAK,UAAAC,EAAA,KA4BAC,EAAA,WACA,SAAAA,KAcA,OATAA,EAAAC,UAAAC,MAGA,WAAiB,OAAqB,IAAAC,gBACtCH,EAAAI,aACSC,KAAAC,EAAA,IAGTN,EAAAO,eAAA,WAA6C,UAC7CP,EAfA,GAuBA/C,GACAC,IAAA,EACAC,KAAA,EACAC,IAAA,EACAC,OAAA,EACAC,QAAA,EACAC,KAAA,EACAC,MAAA,GAEAP,EAAAA,EAAAC,KAAA,MACAD,EAAAA,EAAAE,MAAA,OACAF,EAAAA,EAAAG,KAAA,MACAH,EAAAA,EAAAI,QAAA,SACAJ,EAAAA,EAAAK,SAAA,UACAL,EAAAA,EAAAM,MAAA,OACAN,EAAAA,EAAAO,OAAA,QAEA,IAAAgD,GACAC,OAAA,EACAC,KAAA,EACAC,gBAAA,EACAC,QAAA,EACAC,KAAA,EACAC,UAAA,GAEAN,EAAAA,EAAAC,QAAA,SACAD,EAAAA,EAAAE,MAAA,OACAF,EAAAA,EAAAG,iBAAA,kBACAH,EAAAA,EAAAI,SAAA,UACAJ,EAAAA,EAAAK,MAAA,OACAL,EAAAA,EAAAM,WAAA,YAEA,IAAAC,GACAC,MAAA,EACAC,KAAA,EACAC,QAAA,EACAzD,MAAA,EACA0D,OAAA,GAEAJ,EAAAA,EAAAC,OAAA,QACAD,EAAAA,EAAAE,MAAA,OACAF,EAAAA,EAAAG,SAAA,UACAH,EAAAA,EAAAtD,OAAA,QACAsD,EAAAA,EAAAI,QAAA,SAEA,IAAAC,GACAC,KAAA,EACAC,KAAA,EACAC,KAAA,EACAC,UAAA,EACAC,KAAA,EACAC,KAAA,EACAC,aAAA,GAEAP,EAAAA,EAAAC,MAAA,OACAD,EAAAA,EAAAE,MAAA,OACAF,EAAAA,EAAAG,MAAA,OACAH,EAAAA,EAAAI,WAAA,YACAJ,EAAAA,EAAAK,MAAA,OACAL,EAAAA,EAAAM,MAAA,OACAN,EAAAA,EAAAO,cAAA,eAEA,IAAAC,GACAC,KAAA,EACAC,KAAA,EACAC,YAAA,EACAC,KAAA,GAEAJ,EAAAA,EAAAC,MAAA,OACAD,EAAAA,EAAAE,MAAA,OACAF,EAAAA,EAAAG,aAAA,cACAH,EAAAA,EAAAI,MAAA,OAkCA,IAAAC,EAAA,WAEA,SAAAA,EAAAhD,GACA,IAAAiD,EAAAC,KAIAA,KAAAC,SAAA,IAAAC,IAIAF,KAAAG,iBAAA,IAAAD,IACApD,IAGAA,aAAAgD,EACAhD,EAAAsD,QAAA,SAAAC,EAAAC,GACAD,EAAAD,QAAA,SAAAG,GAAiD,OAAAR,EAAAS,OAAAF,EAAAC,OAIjDE,OAAAC,KAAA5D,GAAAsD,QAAA,SAAAE,GACA,IAA6BD,EAAAM,MAAAC,QAAA9D,EAAAwD,IAAAxD,EAAAwD,IAAAxD,EAAAwD,IAC7BP,EAAAc,OAAAP,GACAD,EAAAD,QAAA,SAAAG,GAA6C,OAAAR,EAAAS,OAAAF,EAAAC,QAsO7C,OA3NAT,EAAAgB,yBAKA,SAAAC,GACA,IAAyBjE,EAAA,IAAAgD,EASzB,OARAiB,EAAAC,MAAA,MAAAZ,QAAA,SAAAa,GACA,IAA6BC,EAAAD,EAAAE,QAAA,KAC7B,GAAAD,EAAA,EAAA,CACA,IAAiCE,EAAAH,EAAAI,MAAA,EAAAH,GACAX,EAAAU,EAAAI,MAAAH,EAAA,GAAAI,OACjCxE,EAAAyE,IAAAH,EAAAb,MAGAzD,GAWAgD,EAAAhC,UAAA0C,OAMA,SAAAF,EAAAC,GACA,IAAyBF,EAAAL,KAAAwB,OAAAlB,GACzB,OAAAD,EACAL,KAAAuB,IAAAjB,EAAAC,GAGAF,EAAAoB,KAAAlB,IAWAT,EAAAhC,UAAA+C,OAKA,SAAAP,GACA,IAAyBoB,EAAApB,EAAAqB,cACzB3B,KAAAG,iBAAAU,OAAAa,GACA1B,KAAAC,SAAAY,OAAAa,IAMA5B,EAAAhC,UAAAsC,QAIA,SAAAwB,GACA,IAAA7B,EAAAC,KACAA,KAAAC,SAAAG,QAAA,SAAAC,EAAAqB,GAAyD,OAAAE,EAAAvB,EAAAN,EAAAI,iBAAA0B,IAAAH,GAAA3B,EAAAE,aAUzDH,EAAAhC,UAAA+D,IAKA,SAAAvB,GACA,IAAyBD,EAAAL,KAAAwB,OAAAlB,GACzB,OAAA,OAAAD,EACA,KAEAA,EAAAyB,OAAA,EAAAzB,EAAA,GAAA,MAUAP,EAAAhC,UAAAiE,IAKA,SAAAzB,GAAqB,OAAAN,KAAAC,SAAA8B,IAAAzB,EAAAqB,gBAQrB7B,EAAAhC,UAAA4C,KAIA,WAAiB,OAAAC,MAAAqB,KAAAhC,KAAAG,iBAAAE,WAUjBP,EAAAhC,UAAAyD,IAMA,SAAAjB,EAAAC,GACAI,MAAAC,QAAAL,GACAA,EAAAuB,QACA9B,KAAAC,SAAAsB,IAAAjB,EAAAqB,eAAApB,EAAA0B,KAAA,OAIAjC,KAAAC,SAAAsB,IAAAjB,EAAAqB,eAAApB,IAEAP,KAAAkC,uBAAA5B,IASAR,EAAAhC,UAAAuC,OAIA,WAAiB,OAAAM,MAAAqB,KAAAhC,KAAAC,SAAAI,WASjBP,EAAAhC,UAAAqE,OAIA,WACA,IAAApC,EAAAC,KACyBoC,KAMzB,OALApC,KAAAC,SAAAG,QAAA,SAAAC,EAAAC,GACA,IAA6BU,KAC7BX,EAAAD,QAAA,SAAA5E,GAAyC,OAAAwF,EAAAS,KAAAY,MAAArB,EAAAxF,EAAAwF,MAAA,QACzCoB,EAAoCrC,EAAAI,iBAAA0B,IAAAvB,IAAAU,IAEpCoB,GAUAtC,EAAAhC,UAAA0D,OAKA,SAAAlB,GACA,OAAAN,KAAA+B,IAAAzB,GAAAN,KAAAC,SAAA4B,IAAAvB,EAAAqB,gBAAA,KAAA,MASA7B,EAAAhC,UAAAwE,QAIA,WAAiB,MAAA,IAAAhH,MAAA,yDAKjBwE,EAAAhC,UAAAoE,uBAIA,SAAA5B,GACA,IAAyBoB,EAAApB,EAAAqB,cACzB3B,KAAAG,iBAAA4B,IAAAL,IACA1B,KAAAG,iBAAAoB,IAAAG,EAAApB,IAGAR,EA9PA,GAwSAyC,EAAA,WACA,SAAAA,EAAAC,QACA,IAAAA,IAA8BA,MAC9B,IAAAzF,EAAAyF,EAAAzF,KAAA0F,EAAAD,EAAAC,OAAA3F,EAAA0F,EAAA1F,QAAA4F,EAAAF,EAAAE,WAAAxE,EAAAsE,EAAAtE,KAAA1B,EAAAgG,EAAAhG,IACAwD,KAAAjD,KAAA,MAAAA,EAAAA,EAAA,KACAiD,KAAAyC,OAAA,MAAAA,EAAAA,EAAA,KACAzC,KAAAlD,QAAA,MAAAA,EAAAA,EAAA,KACAkD,KAAA0C,WAAA,MAAAA,EAAAA,EAAA,KACA1C,KAAA9B,KAAA,MAAAA,EAAAA,EAAA,KACA8B,KAAAxD,IAAA,MAAAA,EAAAA,EAAA,KA2FA,OArCA+F,EAAAzE,UAAApB,MA2BA,SAAAiG,GACA,OAAA,IAAAJ,GACAxF,KAAA4F,GAAA,MAAAA,EAAA5F,KAAA4F,EAAA5F,KAAAiD,KAAAjD,KACA0F,OAAAE,GAAA,MAAAA,EAAAF,OAAAE,EAAAF,OAAAzC,KAAAyC,OACA3F,QAAA6F,GAAA,MAAAA,EAAA7F,QAAA6F,EAAA7F,QAAAkD,KAAAlD,QACA4F,WAAAC,GAAA,MAAAA,EAAAD,WAAAC,EAAAD,WAAA1C,KAAA0C,WACAxE,KAAAyE,GAAA,MAAAA,EAAAzE,KAAAyE,EAAAzE,KAAA8B,KAAA9B,KACA1B,IAAAmG,GAAA,MAAAA,EAAAnG,IAAAmG,EAAAnG,IAAAwD,KAAAxD,OAGA+F,EApGA,GAoJAK,EAAA,SAAAC,GAEA,SAAAD,IACA,OAAAC,EAAAC,KAAA9C,MAAkCyC,OAAA,IAAAC,WAAA,KAAAxE,KAAAU,EAAAG,QAAAjC,QAAA,IAAAgD,KAAoFE,KAOtH,OATAS,OAAAsC,EAAA,EAAAtC,CAAAmC,EAAAC,GAIAD,EAAA3E,aACSC,KAAAC,EAAA,IAGTyE,EAAAxE,eAAA,WAAsD,UACtDwE,EAVA,CAWCL,GAeDS,EAAA,WAGA,OAFA,aADA,GAWAC,EAAA,WAGA,OAFA,aADA,GAWAC,EAAA,WAGA,OAFA,aADA,GA8DAC,EAAA,SAAAV,GAAmC,OAAAA,GAAA,KAAAA,EAAA,KA0DnCW,EAAA,WACA,SAAAA,KAoBA,OAdAA,EAAAtF,UAAAuF,UAIA,SAAAC,GAAkB,OAAA/H,EAAA+H,IAKlBF,EAAAtF,UAAAyF,YAIA,SAAA/H,GAAkB,OAAAD,EAAAC,IAClB4H,EArBA,GA0EAI,EAAA,WACA,SAAAA,EAAAC,EAAAC,QACA,IAAAD,IAAmCA,EAAA,SACnC,IAAAC,IAAsCA,EAAA,IAAAN,GACtCpD,KAAAyD,UAAAA,EACAzD,KAAA0D,aAAAA,EACA1D,KAAA2D,UAnGA,SAAAF,QACA,IAAAA,IAA+BA,EAAA,IAC/B,IAAqBG,EAAA,IAAA1D,IACrBuD,EAAA3B,OAAA,GACyB2B,EAAAzC,MAAA,KACzBZ,QAAA,SAAAyD,GACA,IAA6BC,EAAAD,EAAA1C,QAAA,KAC7B4C,GAAA,GAAAD,GAAAD,EAAA,KAAAA,EAAAxC,MAAA,EAAAyC,GAAAD,EAAAxC,MAAAyC,EAAA,IAAAE,EAAAD,EAAA,GAAAE,EAAAF,EAAA,GAC6BG,EAAAN,EAAA/B,IAAAmC,OAC7BE,EAAAzC,KAAAwC,GACAL,EAAArC,IAAAyC,EAAAE,KAGA,OAAAN,EAsFAO,CAAAV,GAmLA,OA9KAD,EAAA1F,UAAAsG,MAGA,WACA,IAAyBA,EAAA,IAAAZ,EAAA,GAAAxD,KAAA0D,cAEzB,OADAU,EAAAC,UAAArE,MACAoE,GAMAZ,EAAA1F,UAAAiE,IAIA,SAAA8B,GAAsB,OAAA7D,KAAA2D,UAAA5B,IAAA8B,IAKtBL,EAAA1F,UAAA+D,IAIA,SAAAgC,GACA,IAAyBS,EAAAtE,KAAA2D,UAAA9B,IAAAgC,GACzB,OAAAlD,MAAAC,QAAA0D,GAAAA,EAAA,GAAA,MAMAd,EAAA1F,UAAA0D,OAIA,SAAAqC,GAAsB,OAAA7D,KAAA2D,UAAA9B,IAAAgC,QAMtBL,EAAA1F,UAAAyD,IAKA,SAAAsC,EAAAI,GACA,QAAA,IAAAA,GAAA,OAAAA,EAAA,CAIA,IAAyBC,EAAAlE,KAAA2D,UAAA9B,IAAAgC,OACzBK,EAAApC,OAAA,EACAoC,EAAAzC,KAAAwC,GACAjE,KAAA2D,UAAApC,IAAAsC,EAAAK,QANAlE,KAAAa,OAAAgD,IAkBAL,EAAA1F,UAAAyG,OAIA,SAAAC,GACA,IAAAzE,EAAAC,KACAwE,EAAAb,UAAAvD,QAAA,SAAAG,EAAAsD,GACA,IAA6BK,EAAAnE,EAAA4D,UAAA9B,IAAAgC,OAC7BK,EAAApC,OAAA,EACAoC,EAAAzC,KAAAlB,EAAA,IACAR,EAAA4D,UAAApC,IAAAsC,EAAAK,MAQAV,EAAA1F,UAAA0C,OAKA,SAAAqD,EAAAI,GACA,QAAA,IAAAA,GAAA,OAAAA,EAAA,CAEA,IAAyBC,EAAAlE,KAAA2D,UAAA9B,IAAAgC,OACzBK,EAAAzC,KAAAwC,GACAjE,KAAA2D,UAAApC,IAAAsC,EAAAK,KAaAV,EAAA1F,UAAAuG,UAIA,SAAAG,GACA,IAAAzE,EAAAC,KACAwE,EAAAb,UAAAvD,QAAA,SAAAG,EAAAsD,GAEA,IAAA,IAD6BK,EAAAnE,EAAA4D,UAAA9B,IAAAgC,OACKY,EAAA,EAAUA,EAAAlE,EAAAuB,SAAkB2C,EAC9DP,EAAAzC,KAAAlB,EAAAkE,IAEA1E,EAAA4D,UAAApC,IAAAsC,EAAAK,MAcAV,EAAA1F,UAAA4G,WAIA,SAAAF,GACA,IAAAzE,EAAAC,KACAwE,EAAAb,UAAAvD,QAAA,SAAAG,EAAAsD,GACA,IAA6BK,EAAAnE,EAAA4D,UAAA9B,IAAAgC,OAC7BK,EAAApC,OAAA,EACA,IAAA,IAAkC2C,EAAA,EAAUA,EAAAlE,EAAAuB,SAAkB2C,EAC9DP,EAAAzC,KAAAlB,EAAAkE,IAEA1E,EAAA4D,UAAApC,IAAAsC,EAAAK,MAMAV,EAAA1F,UAAA6G,SAGA,WACA,IAAA5E,EAAAC,KACyB4E,KAMzB,OALA5E,KAAA2D,UAAAvD,QAAA,SAAAC,EAAAiD,GACAjD,EAAAD,QAAA,SAAA5E,GACA,OAAAoJ,EAAAnD,KAAA1B,EAAA2D,aAAAL,UAAAC,GAAA,IAAAvD,EAAA2D,aAAAH,YAAA/H,QAGAoJ,EAAA3C,KAAA,MAMAuB,EAAA1F,UAAA+C,OAIA,SAAAgD,GAAsB7D,KAAA2D,UAAA9C,OAAAgD,IACtBL,EAzLA,GA4MAqB,EAAA,WACA,SAAAA,KAgIA,OAvHAA,EAAA/G,UAAAgH,KAIA,WACA,MAAA,iBAAA9E,KAAA+E,MACA5F,KAAA6F,MAA2ChF,KAAA,OAE3CA,KAAA+E,iBAAAnF,YACAT,KAAA6F,MAAAhF,KAAAiF,QAEAjF,KAAA+E,OAgCAF,EAAA/G,UAAAmH,KAgBA,SAAAC,GAEA,QADA,IAAAA,IAAsCA,EAAA,UACtClF,KAAA+E,iBAAAvB,EACA,OAAAxD,KAAA+E,MAAAJ,WAEA,GAAA3E,KAAA+E,iBAAAnF,YACA,OAAAsF,GACA,IAAA,SACA,OAAAC,OAAAC,aAAA/C,MAAA,KAAA,IAAAgD,YAAwFrF,KAAA,QACxF,IAAA,WACA,OAAAmF,OAAAC,aAAA/C,MAAA,KAAA,IAAAiD,WAAuFtF,KAAA,QACvF,QACA,MAAA,IAAA1E,MAAA,mCAAA4J,GAGA,OAAA,MAAAlF,KAAA+E,MACA,GAEA,iBAAA/E,KAAA+E,MACA5F,KAAAoG,UAAAvF,KAAA+E,MAAA,KAAA,GAEA/E,KAAA+E,MAAAJ,YASAE,EAAA/G,UAAA0H,YAIA,WACA,OAAAxF,KAAA+E,iBAAAnF,YACgCI,KAAA,MAlahC,SAAAyF,GAEA,IAAA,IADqBC,EAAA,IAAAL,YAAAI,EAAA3D,QACK2C,EAAA,EAAwBkB,EAAAF,EAAA3D,OAA0B2C,EAAAkB,EAAYlB,IACxFiB,EAAAjB,GAAAgB,EAAAG,WAAAnB,GAEA,OAAAiB,EAAAG,OA+ZAC,CAAA9F,KAAAiF,SASAJ,EAAA/G,UAAAiI,KAIA,WACA,GAAA/F,KAAA+E,iBAAAlF,KACA,OAAgCG,KAAA,MAEhC,GAAAA,KAAA+E,iBAAAnF,YACA,OAAA,IAAAC,MAAAG,KAAA+E,QAEA,MAAA,IAAAzJ,MAAA,4DAEAuJ,EAjIA,GA4JAmB,EAAA,SAAAnD,GAEA,SAAAmD,EAAAC,GACA,IAAAlG,EAAA8C,EAAAC,KAAA9C,OAAAA,KAQA,OAPAD,EAAAgF,MAAAkB,EAAAlJ,KACAgD,EAAA0C,OAAoCwD,EAAA,OACpClG,EAAAmG,GAAAnG,EAAA0C,QAAA,KAAA1C,EAAA0C,QAAA,IACA1C,EAAA2C,WAAAuD,EAAAvD,WACA3C,EAAAjD,QAAAmJ,EAAAnJ,QACAiD,EAAA7B,KAAkC+H,EAAA,KAClClG,EAAAvD,IAAiCyJ,EAAA,IACjClG,EAWA,OArBAU,OAAAsC,EAAA,EAAAtC,CAAAuF,EAAAnD,GAeAmD,EAAAlI,UAAA6G,SAGA,WACA,MAAA,yBAAA3E,KAAAyC,OAAA,IAAAzC,KAAA0C,WAAA,aAAA1C,KAAAxD,KAEAwJ,EAtBA,CAuBCnB,GAaDsB,EAAA,EACApK,EAAA,eACAD,EAAA,KAWAsK,EAAA,WACA,SAAAA,KAuFA,OAhFAA,EAAAtI,UAAAC,MAIA,SAAAvB,GACA,IAAyB6J,EAAAC,SAAAC,cAAA,UAEzB,OADAF,EAAAG,IAAAhK,EACA6J,GAKAD,EAAAtI,UAAA2I,cAGA,WAAiB,MAAA,QAAAN,KAKjBC,EAAAtI,UAAA4I,gBAIA,SAAAC,GAAmB,OAAA5K,EAAA,IAAA4K,EAAA,aAMnBP,EAAAtI,UAAA8I,iBAKA,SAAAD,EAAAE,GACyBlL,IACzBgL,GAAAE,GAMAT,EAAAtI,UAAAgJ,iBAIA,SAAAH,GACyBhL,IACzBgL,GAAA,MAOAP,EAAAtI,UAAAiJ,KAIA,SAAAV,GAAqBC,SAAAvJ,KAAAiK,YAAwC,IAM7DZ,EAAAtI,UAAAmJ,QAIA,SAAAZ,GACAA,EAAAa,YACAb,EAAAa,WAAAC,YAAqD,IAGrDf,EAAAnI,aACSC,KAAAC,EAAA,IAGTiI,EAAAhI,eAAA,WAA+C,UAC/CgI,EAxFA,GAsGAgB,EAAA,iDACAC,EAAA,8CAMAC,EAAA,WAEA,SAAAA,EAAAC,EAAAC,EAAAC,GACA,IAAA1H,EAAAC,KAIA,GAHAA,KAAAwH,KAAAA,EACAxH,KAAAyH,oBAAAA,EACAzH,KAAA0H,WAAA,EACAH,EAAA3M,SAAAE,EAAAC,IACA,MAAA,IAAA4M,UAAAN,GAEArH,KAAA9D,QAAAqL,EACAvH,KAAA5D,SAAA,IAAAwL,EAAA,WAAA,SAAAC,GACA9H,EAAA+H,WAAAzJ,EAAAI,QACA,IAA6BkI,EAAA5G,EAAAgI,IAAAP,EAAAf,gBAC7Be,EAAAZ,iBAAAD,EAAA5G,GAGA,IAA6BiI,EAAAR,EAAAd,gBAAA3G,EAAAgI,KACAvL,EAAA+K,EAAA/K,IAC7BA,EAAA2E,QAAA,qBAAA,EACA3E,EAAAA,EAAAd,QAAA,mBAAA,IAAAsM,EAAA,KAEAxL,EAAAyL,YAAA,qBAAAzL,EAAAsF,OAAA,kBAAAA,SACAtF,EAAAA,EAAA0L,UAAA,EAAA1L,EAAAsF,OAAA,kBAAAA,QAAA,IAAAkG,GAEA,IAA6BG,EAAApI,EAAAqI,QAAAZ,EAAAzJ,MAAAvB,GACA6L,EAAA,SAAAC,GAC7B,GAAAvI,EAAA+H,aAAAzJ,EAAAM,UAAA,CAIA,GAFAoB,EAAA+H,WAAAzJ,EAAAK,KACA8I,EAAAP,QAAAkB,IACApI,EAAA2H,UAAA,CACA,IAAqCa,EAAA,IAAAhG,GAA6CxF,KAAAqK,EAAAlJ,KAAAU,EAAAtD,MAAAkB,IAAAA,IAKlF,OAJAiL,IACAc,EAAAd,EAAA/K,MAAA6L,SAEAV,EAAAW,MAAA,IAAAxC,EAAAuC,IAGA,IAAiCtC,EAAA,IAAA1D,GAA2CxF,KAAAgD,EAAA0I,cAAAjM,IAAAA,IAC5EuD,EAAA0H,sBACAxB,EAAAlG,EAAA0H,oBAAA/K,MAAAuJ,IAEA4B,EAAAa,KAAA,IAAA1C,EAAAC,IACA4B,EAAAc,aAE6BC,EAAA,SAAAJ,GAC7B,GAAAzI,EAAA+H,aAAAzJ,EAAAM,UAAA,CAEAoB,EAAA+H,WAAAzJ,EAAAK,KACA8I,EAAAP,QAAAkB,GACA,IAAiClC,EAAA,IAAA1D,GAA2CxF,KAAAyL,EAAAK,QAAA3K,KAAAU,EAAAtD,QAC5EmM,IACAxB,EAAAwB,EAAA/K,MAAAuJ,IAEA4B,EAAAW,MAAA,IAAAxC,EAAAC,MAKA,OAHAkC,EAAAW,iBAAA,OAAAT,GACAF,EAAAW,iBAAA,QAAAF,GACApB,EAAAT,KAAAoB,GACA,WACApI,EAAA+H,WAAAzJ,EAAAM,UACAwJ,EAAAY,oBAAA,OAAAV,GACAF,EAAAY,oBAAA,QAAAH,GACA7I,EAAAyH,KAAAP,QAAAkB,MA4BA,OAdAb,EAAAxJ,UAAAkL,SAMA,SAAAC,GAEAjJ,KAAA0H,WAAA,EACA1H,KAAAwH,KAAAV,iBAAA9G,KAAA+H,KACA/H,KAAA8H,aAAAzJ,EAAAM,YAEAqB,KAAAyI,cAAAQ,IAEA3B,EA5FA,GAmGA4B,EAAA,SAAArG,GAGA,SAAAqG,EAAAC,EAAAC,GACA,IAAArJ,EAAA8C,EAAAC,KAAA9C,OAAAA,KAGA,OAFAD,EAAAoJ,cAAAA,EACApJ,EAAAqJ,qBAAAA,EACArJ,EAqBA,OA3BAU,OAAAsC,EAAA,EAAAtC,CAAAyI,EAAArG,GAYAqG,EAAApL,UAAA3B,iBAIA,SAAAD,GACA,OAAA,IAAAoL,EAAApL,EAAA8D,KAAAmJ,cAAAnJ,KAAAoJ,uBAEAF,EAAAjL,aACSC,KAAAC,EAAA,IAGT+K,EAAA9K,eAAA,WAA+C,QACtCF,KAAAkI,IACAlI,KAAAqE,KAET2G,EA5BA,CA6BClG,GAaDqG,EAAA,eAWAC,EAAA,WACA,SAAAA,EAAA/B,EAAAgC,EAAA9B,GACA,IAAA1H,EAAAC,KACAA,KAAA9D,QAAAqL,EACAvH,KAAA5D,SAAA,IAAAwL,EAAA,WAAA,SAAAC,GACA,IAA6B2B,EAAAD,EAAAxL,QAC7ByL,EAAAC,KAAA3O,EAAAyM,EAAA3M,QAAAC,cAAA0M,EAAA/K,KACA,MAAA+K,EAAAvK,kBACAwM,EAAAxM,gBAAAuK,EAAAvK,iBAGA,IAA6BqL,EAAA,WAE7B,IAAiC5F,EAAA,OAAA+G,EAAA/G,OAAA,IAAA+G,EAAA/G,OACA1F,EAAA,KAEjC,MAAA0F,GAMA,iBAFA1F,OAAA,IAAAyM,EAAApN,SAAAoN,EAAAE,aAAAF,EAAApN,YAGAW,EAAAA,EAAArB,QAAA2N,EAAA,KAMA,IAAA5G,IACAA,EAAA1F,EAAA,IAAA,GAEA,IAAiCD,EAAAgD,EAAAgB,yBAAA0I,EAAAG,yBAEAnN,EA/zBjC,SAAAoN,GACA,MAAA,gBAAAA,EACAA,EAAAC,YAEA,mBAAAC,KAAAF,EAAAD,yBACAC,EAAAG,kBAAA,iBAEA,KAwzBiCC,CAAAR,IAAAjC,EAAA/K,IAEAyJ,EAAA,IAAA1D,GAA2CxF,KAAAA,EAAA0F,OAAAA,EAAA3F,QAAAA,EAAA4F,WAD3C8G,EAAA9G,YAAA,KAC2ClG,IAAAA,IAC5E,MAAAiL,IACAxB,EAAAwB,EAAA/K,MAAAuJ,IAEA,IAAiC7J,EAAA,IAAA4J,EAAAC,GAEjC,GADA7J,EAAA8J,GAAA/C,EAAAV,GACArG,EAAA8J,GAIA,OAHA2B,EAAAa,KAAAtM,QAEAyL,EAAAc,WAGAd,EAAAW,MAAApM,IAG6BwM,EAAA,SAAAqB,GAC7B,IAAiChE,EAAA,IAAA1D,GACjCxF,KAAAkN,EACA/L,KAAAU,EAAAtD,MACAmH,OAAA+G,EAAA/G,OACAC,WAAA8G,EAAA9G,aAEA,MAAA+E,IACAxB,EAAAwB,EAAA/K,MAAAuJ,IAEA4B,EAAAW,MAAA,IAAAxC,EAAAC,KAWA,GATAlG,EAAAmK,uBAAA3C,EAAAiC,GACA,MAAAjC,EAAAzK,UACAyK,EAAAzK,QAAA,IAAAgD,GAEAyH,EAAAzK,QAAAiF,IAAA,WACAwF,EAAAzK,QAAA0D,OAAA,SAAA,qCAEA+G,EAAAzK,QAAAsD,QAAA,SAAAC,EAAAC,GAAyD,OAAAkJ,EAAAW,iBAA2C,EAAA9J,EAAA4B,KAAA,QAEpG,MAAAsF,EAAAtK,cAAA,MAAAuM,EAAAvM,aACA,OAAAsK,EAAAtK,cACA,KAAAwC,EAAAG,YACA4J,EAAAvM,aAAA,cACA,MACA,KAAAwC,EAAAE,KACA6J,EAAAvM,aAAA,OACA,MACA,KAAAwC,EAAAC,KACA8J,EAAAvM,aAAA,OACA,MACA,KAAAwC,EAAAI,KACA2J,EAAAvM,aAAA,OACA,MACA,QACA,MAAA,IAAA3B,MAAA,8CAMA,OAHAkO,EAAAV,iBAAA,OAAAT,GACAmB,EAAAV,iBAAA,QAAAF,GACAY,EAAAzC,KAAAhH,EAAA7D,QAAAkO,WACA,WACAZ,EAAAT,oBAAA,OAAAV,GACAmB,EAAAT,oBAAA,QAAAH,GACAY,EAAAa,WAwCA,OA/BAf,EAAAxL,UAAAoM,uBAKA,SAAA3C,EAAAiC,GAEA,GAAA,MAAAjC,EAAAzK,SAAA,MAAAyK,EAAAzK,QAAA+E,IAAA,gBAIA,OAAA0F,EAAA+C,aACA,KAAArL,EAAAC,KACA,MACA,KAAAD,EAAAE,KACAqK,EAAAW,iBAAA,eAAA,oBACA,MACA,KAAAlL,EAAAG,KACAoK,EAAAW,iBAAA,eAAA,mDACA,MACA,KAAAlL,EAAAK,KACAkK,EAAAW,iBAAA,eAAA,cACA,MACA,KAAAlL,EAAAM,KACA,IAAiCwG,EAAAwB,EAAAxB,OACjCA,EAAA7H,MACAsL,EAAAW,iBAAA,eAAApE,EAAA7H,QAKAoL,EAxIA,GAqJAnM,EAAA,WACA,SAAAA,EAAAoN,EAAAC,QACA,IAAAD,IAAqCA,EAAA,mBACrC,IAAAC,IAAqCA,EAAA,gBACrCxK,KAAAuK,YAAAA,EACAvK,KAAAwK,YAAAA,EAgBA,OAVArN,EAAAW,UAAA2M,iBAIA,SAAAlD,GACA,IAAyBmD,EAAAjK,OAAA9C,EAAA,EAAA8C,GAAAkK,UAAA3K,KAAAuK,aACzBG,GACAnD,EAAAzK,QAAAyE,IAAAvB,KAAAwK,YAAAE,IAGAvN,EArBA,GAiDAyN,EAAA,WACA,SAAAA,EAAAC,EAAAzB,EAAA0B,GACA9K,KAAA6K,YAAAA,EACA7K,KAAAoJ,qBAAAA,EACApJ,KAAA8K,cAAAA,EAuBA,OAjBAF,EAAA9M,UAAA3B,iBAIA,SAAAD,GAEA,OADA8D,KAAA8K,cAAAL,iBAAAvO,GACA,IAAAoN,EAAApN,EAAA8D,KAAA6K,YAAA7K,KAAAoJ,uBAEAwB,EAAA3M,aACSC,KAAAC,EAAA,IAGTyM,EAAAxM,eAAA,WAA6C,QACpCF,KAAAL,IACAK,KAAAqE,IACArE,KAAAgF,KAET0H,EA3BA,GAiEAjO,EAAA,WAEA,SAAAA,EAAA6F,QACA,IAAAA,IAA8BA,MAC9B,IAAA5H,EAAA4H,EAAA5H,OAAAkC,EAAA0F,EAAA1F,QAAAC,EAAAyF,EAAAzF,KAAAP,EAAAgG,EAAAhG,IAAAI,EAAA4F,EAAA5F,OAAAC,EAAA2F,EAAA3F,OAAAG,EAAAwF,EAAAxF,gBAAAC,EAAAuF,EAAAvF,aACA+C,KAAApF,OAAA,MAAAA,EAAAD,EAAAC,GAAA,KACAoF,KAAAlD,QAAA,MAAAA,EAAAA,EAAA,KACAkD,KAAAjD,KAAA,MAAAA,EAAAA,EAAA,KACAiD,KAAAxD,IAAA,MAAAA,EAAAA,EAAA,KACAwD,KAAAnD,OAAAmD,KAAA+K,mBAAAlO,GAAAD,GACAoD,KAAAhD,gBAAA,MAAAA,EAAAA,EAAA,KACAgD,KAAA/C,aAAA,MAAAA,EAAAA,EAAA,KAyKA,OAvKAwD,OAAAuK,eAAArO,EAAAmB,UAAA,UAIA+D,IAIA,WAAqB,OAAA7B,KAAAnD,QAIrB0E,IAKA,SAAA1E,GAA2BmD,KAAAnD,OAAAA,GAC3BoO,YAAA,EACAC,cAAA,IAkDAvO,EAAAmB,UAAApB,MAyBA,SAAAiG,GACA,OAAA,IAAAhG,GACA/B,OAAA+H,GAAA,MAAAA,EAAA/H,OAAA+H,EAAA/H,OAAAoF,KAAApF,OACAkC,QAAA6F,GAAA,MAAAA,EAAA7F,QAAA6F,EAAA7F,QAAA,IAAAgD,EAAAE,KAAAlD,SACAC,KAAA4F,GAAA,MAAAA,EAAA5F,KAAA4F,EAAA5F,KAAAiD,KAAAjD,KACAP,IAAAmG,GAAA,MAAAA,EAAAnG,IAAAmG,EAAAnG,IAAAwD,KAAAxD,IACAK,OAAA8F,GAAA3C,KAAA+K,mBAAApI,EAAA9F,QAAA8F,EAAA/F,QACAI,gBAAA2F,GAAA,MAAAA,EAAA3F,gBAAA2F,EAAA3F,gBACAgD,KAAAhD,gBACAC,aAAA0F,GAAA,MAAAA,EAAA1F,aAAA0F,EAAA1F,aACA+C,KAAA/C,gBAOAN,EAAAmB,UAAAiN,mBAIA,SAAAlO,GACA,OAAAA,EAEAA,aAAA2G,EACA3G,EAAAuH,QAEA,iBAAAvH,EACA,IAAA2G,EAAA3G,GAEAmD,KAAAmL,aAAAtO,GAPAmD,KAAAnD,QAaAF,EAAAmB,UAAAqN,aAIA,SAAAC,GACA,IAAArL,EAAAC,UACA,IAAAoL,IAAmCA,MACnC,IAAyBvO,EAAA,IAAA2G,EAUzB,OATA/C,OAAAC,KAAA0K,GAAAhL,QAAA,SAAA4D,GACA,IAA6BzD,EAAA6K,EAAApH,GAC7BrD,MAAAC,QAAAL,GACAA,EAAAH,QAAA,SAAAiL,GAA+C,OAAAtL,EAAAuL,aAAAtH,EAAAqH,EAAAxO,KAG/CkD,EAAAuL,aAAAtH,EAAAzD,EAAA1D,KAGAA,GAQAF,EAAAmB,UAAAwN,aAMA,SAAAtH,EAAAzD,EAAA1D,GACA,iBAAA0D,IACAA,EAAApB,KAAAoG,UAAAhF,IAEA1D,EAAA2D,OAAAwD,EAAAzD,IAEA5D,EApLA,GA6NA4O,EAAA,SAAA1I,GAEA,SAAA0I,IACA,OAAA1I,EAAAC,KAAA9C,MAAkCpF,OAAAE,EAAAC,IAAA+B,QAAA,IAAAgD,KAAoDE,KAOtF,OATAS,OAAAsC,EAAA,EAAAtC,CAAA8K,EAAA1I,GAIA0I,EAAAtN,aACSC,KAAAC,EAAA,IAGToN,EAAAnN,eAAA,WAAqD,UACrDmN,EAVA,CAWC5O,GAoDD6O,EAAA,SAAA3I,GAEA,SAAA2I,EAAAlO,GACA,IAAAyC,EAAA8C,EAAAC,KAAA9C,OAAAA,KAEyBxD,EAAAc,EAAAd,IACzBuD,EAAAvD,IAAiCc,EAAA,IACjC,IAAyBmO,EAAAnO,EAAAT,QAAAS,EAAAV,OACzB,GAAA6O,EAAA,CACA,IAA6B5O,OAAA,EAO7B,IAFAA,EAJA,iBAAA4O,GAAAA,aAAAjI,EAIAiI,EAAA9G,WA4HA,SAAA9H,GACA,IAAqB2H,EAAA,IAAAhB,EAUrB,OATA/C,OAAAC,KAAA7D,GAAAuD,QAAA,SAAA4D,GACA,IAAyBzD,EAAA1D,EAAAmH,GACzBzD,GAAAI,MAAAC,QAAAL,GACAA,EAAAH,QAAA,SAAAsL,GAA8C,OAAAlH,EAAAhE,OAAAwD,EAAA0H,EAAA/G,cAG9CH,EAAAhE,OAAAwD,EAAAzD,EAAAoE,cAGAH,EA1IAmH,CAAAF,GAAA9G,YAKA7C,OAAA,EAAA,CACA,IAAiC8J,EAAA,KACjC,GAAA7L,EAAAvD,IAAA2E,QAAA,OACAyK,EAAA,KAAA7L,EAAAvD,IAAAuD,EAAAvD,IAAAsF,OAAA,GAAA,GAAA,KAIA/B,EAAAvD,IAAAA,EAAAoP,EAAA/O,GAaA,OAVAkD,EAAAgF,MAAAzH,EAAAP,KACAgD,EAAAnF,OAAAD,EAAwD2C,EAAA,QAKxDyC,EAAAjD,QAAA,IAAAgD,EAAAxC,EAAAR,SACAiD,EAAAuK,YAAAvK,EAAA8L,oBACA9L,EAAA/C,gBAA6CM,EAAA,gBAC7CyC,EAAA9C,aAA0CK,EAAA,aAC1CyC,EAgGA,OAnIAU,OAAAsC,EAAA,EAAAtC,CAAA+K,EAAA3I,GA4CA2I,EAAA1N,UAAA+N,kBAIA,WACA,OAAA7L,KAAAlD,QAAA+E,IAAA,iBACA,IAAA,mBACA,OAAA5C,EAAAE,KACA,IAAA,oCACA,OAAAF,EAAAG,KACA,IAAA,sBACA,OAAAH,EAAAI,UACA,IAAA,aACA,IAAA,YACA,OAAAJ,EAAAK,KACA,IAAA,2BACA,OAAAU,KAAA+E,iBAAA+G,EAAA7M,EAAAO,aAAAP,EAAAM,KACA,QACA,OAAAS,KAAA+L,8BAUAP,EAAA1N,UAAAiO,0BAIA,WACA,OAAA,MAAA/L,KAAA+E,MACA9F,EAAAC,KAEAc,KAAA+E,iBAAAvB,EACAvE,EAAAG,KAEAY,KAAA+E,iBAAAiH,EACA/M,EAAAI,UAEAW,KAAA+E,iBAAAkH,EACAhN,EAAAM,KAEAS,KAAA+E,iBAAA+G,EACA7M,EAAAO,aAEAQ,KAAA+E,OAAA,iBAAA/E,KAAA+E,MACA9F,EAAAE,KAGAF,EAAAK,MAYAkM,EAAA1N,UAAAsM,QAKA,WACA,OAAApK,KAAAsK,aACA,KAAArL,EAAAE,KAEA,KAAAF,EAAAG,KACA,OAAAY,KAAAiF,OACA,KAAAhG,EAAAI,UACA,OAAAW,KAAA+E,MACA,KAAA9F,EAAAK,KACA,OAAAU,KAAAiF,OACA,KAAAhG,EAAAM,KACA,OAAAS,KAAA+F,OACA,KAAA9G,EAAAO,aACA,OAAAQ,KAAAwF,cACA,QACA,OAAA,OAGAgG,EApIA,CAqIC3G,GAkBDqH,EAAA,aACAtQ,EAAA,iBAAAC,OAAAA,OAAAqQ,EACAF,EAAA,EAA6B,UAAAE,EAC7BD,EAAA,EAA2B,MAAAC,EAC3BJ,EAAA,EAAkC,aAAAI,EAyGlC3O,EAAA,WACA,SAAAA,EAAA4O,EAAAC,GACApM,KAAAmM,SAAAA,EACAnM,KAAAoM,gBAAAA,EAmLA,OAlKA7O,EAAAO,UAAA5B,QASA,SAAAM,EAAAmG,GACA,IAAyB0J,EACzB,GAAA,iBAAA7P,EACA6P,EAAArQ,EAAAgE,KAAAmM,SAAA,IAAAX,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAC,IAAoJ,SAEpJ,CAAA,KAAAyB,aAAAgP,GAIA,MAAA,IAAAlQ,MAAA,4DAHA+Q,EAAArQ,EAAAgE,KAAAmM,SAAA3P,GAKA,OAAA6P,GAWA9O,EAAAO,UAAA+D,IAMA,SAAArF,EAAAmG,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAC,IAAAyB,MAYAe,EAAAO,UAAAwO,KAOA,SAAA9P,EAAAO,EAAA4F,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAA1P,MAAA,IAAAC,GAAoGI,KAAAA,KAAa4F,EAAA7H,EAAAE,KAAAwB,MAYjHe,EAAAO,UAAAyO,IAOA,SAAA/P,EAAAO,EAAA4F,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAA1P,MAAA,IAAAC,GAAoGI,KAAAA,KAAa4F,EAAA7H,EAAAG,IAAAuB,MAWjHe,EAAAO,UAAA+C,OAMA,SAAArE,EAAAmG,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAI,OAAAsB,MAYAe,EAAAO,UAAA0O,MAOA,SAAAhQ,EAAAO,EAAA4F,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAA1P,MAAA,IAAAC,GAAoGI,KAAAA,KAAa4F,EAAA7H,EAAAO,MAAAmB,MAWjHe,EAAAO,UAAA2O,KAMA,SAAAjQ,EAAAmG,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAM,KAAAoB,MAWAe,EAAAO,UAAA6E,QAMA,SAAAnG,EAAAmG,GACA,OAAA3C,KAAA9D,QAAA,IAAAsP,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAK,QAAAqB,MAEAe,EAAAU,aACSC,KAAAC,EAAA,IAGTZ,EAAAa,eAAA,WAAuC,QAC9BF,KAAA8E,IACA9E,KAAAvB,KAETY,EAtLA,GA2LAG,EAAA,SAAAmF,GAEA,SAAAnF,EAAAzB,EAAAyQ,GACA,OAAA7J,EAAAC,KAAA9C,KAAA/D,EAAAyQ,IAAA1M,KA2EA,OA7EAS,OAAAsC,EAAA,EAAAtC,CAAA/C,EAAAmF,GAmCAnF,EAAAI,UAAA5B,QAiBA,SAAAM,EAAAmG,GAMA,GAJA,iBAAAnG,IACAA,EACA,IAAAgP,EAAAnP,EAAA2D,KAAAoM,gBAAAzJ,EAAA7H,EAAAC,IAAwG,OAExGyB,aAAAgP,GAOA,MAAA,IAAAlQ,MAAA,4DANA,GAAAkB,EAAA5B,SAAAE,EAAAC,IACA,MAAA,IAAAO,MAAA,+CAOA,OALAU,EAAAgE,KAAAmM,SAAA3P,IAOAkB,EAAAO,aACSC,KAAAC,EAAA,IAGTT,EAAAU,eAAA,WAAwC,QAC/BF,KAAA8E,IACA9E,KAAAvB,KAETe,EA9EA,CA+ECH,GA8CDoP,GAAA,WACA,SAAAA,KAkBA,OAhBAA,EAAA1O,aACSC,KAAAC,EAAA,EAAAyO,OACTC,YAGyBC,QAAAvP,EAAAwP,WAAA3P,EAAA4P,MAAApC,EAAAjO,IACzBkB,GACyBiP,QAAAnQ,EAAAsQ,SAAA1B,IACAuB,QAAAvK,EAAA0K,SAAArK,GACzBgI,GACyBkC,QAAA5J,EAAA6J,WAAA7P,QAKzByP,EAAAvO,eAAA,WAA6C,UAC7CuO,EAnBA,GA0BAO,GAAA,WACA,SAAAA,KAiBA,OAfAA,EAAAjP,aACSC,KAAAC,EAAA,EAAAyO,OACTC,YAGyBC,QAAApP,EAAAqP,WAAAvP,EAAAwP,MAAA9D,EAAAvM,IACzByJ,GACyB0G,QAAAnQ,EAAAsQ,SAAA1B,IACAuB,QAAAvK,EAAA0K,SAAArK,GACzBsG,OAKAgE,EAAA9O,eAAA,WAA8C,UAC9C8O,EAlBA,GAwCAC,GAAA,IAAAhP,EAAA,EAAA","sourcesContent":["/**\n * @license Angular v5.0.3\n * (c) 2010-2017 Google, Inc. https://angular.io/\n * License: MIT\n */\nimport { Injectable, NgModule, Version } from '@angular/core';\nimport { __extends } from 'tslib';\nimport { Observable } from 'rxjs/Observable';\nimport { ɵgetDOM } from '@angular/platform-browser';\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * A backend for http that uses the `XMLHttpRequest` browser API.\n *\n * Take care not to evaluate this in non-browser contexts.\n *\n * @deprecated use \\@angular/common/http instead\n */\nvar BrowserXhr = (function () {\n function BrowserXhr() {\n }\n /**\n * @return {?}\n */\n BrowserXhr.prototype.build = /**\n * @return {?}\n */\n function () { return /** @type {?} */ ((new XMLHttpRequest())); };\n BrowserXhr.decorators = [\n { type: Injectable },\n ];\n /** @nocollapse */\n BrowserXhr.ctorParameters = function () { return []; };\n return BrowserXhr;\n}());\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/** @enum {number} */\nvar RequestMethod = {\n Get: 0,\n Post: 1,\n Put: 2,\n Delete: 3,\n Options: 4,\n Head: 5,\n Patch: 6,\n};\nRequestMethod[RequestMethod.Get] = \"Get\";\nRequestMethod[RequestMethod.Post] = \"Post\";\nRequestMethod[RequestMethod.Put] = \"Put\";\nRequestMethod[RequestMethod.Delete] = \"Delete\";\nRequestMethod[RequestMethod.Options] = \"Options\";\nRequestMethod[RequestMethod.Head] = \"Head\";\nRequestMethod[RequestMethod.Patch] = \"Patch\";\n/** @enum {number} */\nvar ReadyState = {\n Unsent: 0,\n Open: 1,\n HeadersReceived: 2,\n Loading: 3,\n Done: 4,\n Cancelled: 5,\n};\nReadyState[ReadyState.Unsent] = \"Unsent\";\nReadyState[ReadyState.Open] = \"Open\";\nReadyState[ReadyState.HeadersReceived] = \"HeadersReceived\";\nReadyState[ReadyState.Loading] = \"Loading\";\nReadyState[ReadyState.Done] = \"Done\";\nReadyState[ReadyState.Cancelled] = \"Cancelled\";\n/** @enum {number} */\nvar ResponseType = {\n Basic: 0,\n Cors: 1,\n Default: 2,\n Error: 3,\n Opaque: 4,\n};\nResponseType[ResponseType.Basic] = \"Basic\";\nResponseType[ResponseType.Cors] = \"Cors\";\nResponseType[ResponseType.Default] = \"Default\";\nResponseType[ResponseType.Error] = \"Error\";\nResponseType[ResponseType.Opaque] = \"Opaque\";\n/** @enum {number} */\nvar ContentType = {\n NONE: 0,\n JSON: 1,\n FORM: 2,\n FORM_DATA: 3,\n TEXT: 4,\n BLOB: 5,\n ARRAY_BUFFER: 6,\n};\nContentType[ContentType.NONE] = \"NONE\";\nContentType[ContentType.JSON] = \"JSON\";\nContentType[ContentType.FORM] = \"FORM\";\nContentType[ContentType.FORM_DATA] = \"FORM_DATA\";\nContentType[ContentType.TEXT] = \"TEXT\";\nContentType[ContentType.BLOB] = \"BLOB\";\nContentType[ContentType.ARRAY_BUFFER] = \"ARRAY_BUFFER\";\n/** @enum {number} */\nvar ResponseContentType = {\n Text: 0,\n Json: 1,\n ArrayBuffer: 2,\n Blob: 3,\n};\nResponseContentType[ResponseContentType.Text] = \"Text\";\nResponseContentType[ResponseContentType.Json] = \"Json\";\nResponseContentType[ResponseContentType.ArrayBuffer] = \"ArrayBuffer\";\nResponseContentType[ResponseContentType.Blob] = \"Blob\";\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * Polyfill for [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers/Headers), as\n * specified in the [Fetch Spec](https://fetch.spec.whatwg.org/#headers-class).\n *\n * The only known difference between this `Headers` implementation and the spec is the\n * lack of an `entries` method.\n *\n * ### Example\n *\n * ```\n * import {Headers} from '\\@angular/http';\n *\n * var firstHeaders = new Headers();\n * firstHeaders.append('Content-Type', 'image/jpeg');\n * console.log(firstHeaders.get('Content-Type')) //'image/jpeg'\n *\n * // Create headers from Plain Old JavaScript Object\n * var secondHeaders = new Headers({\n * 'X-My-Custom-Header': 'Angular'\n * });\n * console.log(secondHeaders.get('X-My-Custom-Header')); //'Angular'\n *\n * var thirdHeaders = new Headers(secondHeaders);\n * console.log(thirdHeaders.get('X-My-Custom-Header')); //'Angular'\n * ```\n *\n * @deprecated use \\@angular/common/http instead\n */\nvar Headers = (function () {\n // TODO(vicb): any -> string|string[]\n function Headers(headers) {\n var _this = this;\n /**\n * \\@internal header names are lower case\n */\n this._headers = new Map();\n /**\n * \\@internal map lower case names to actual names\n */\n this._normalizedNames = new Map();\n if (!headers) {\n return;\n }\n if (headers instanceof Headers) {\n headers.forEach(function (values, name) {\n values.forEach(function (value) { return _this.append(name, value); });\n });\n return;\n }\n Object.keys(headers).forEach(function (name) {\n var /** @type {?} */ values = Array.isArray(headers[name]) ? headers[name] : [headers[name]];\n _this.delete(name);\n values.forEach(function (value) { return _this.append(name, value); });\n });\n }\n /**\n * Returns a new Headers instance from the given DOMString of Response Headers\n */\n /**\n * Returns a new Headers instance from the given DOMString of Response Headers\n * @param {?} headersString\n * @return {?}\n */\n Headers.fromResponseHeaderString = /**\n * Returns a new Headers instance from the given DOMString of Response Headers\n * @param {?} headersString\n * @return {?}\n */\n function (headersString) {\n var /** @type {?} */ headers = new Headers();\n headersString.split('\\n').forEach(function (line) {\n var /** @type {?} */ index = line.indexOf(':');\n if (index > 0) {\n var /** @type {?} */ name_1 = line.slice(0, index);\n var /** @type {?} */ value = line.slice(index + 1).trim();\n headers.set(name_1, value);\n }\n });\n return headers;\n };\n /**\n * Appends a header to existing list of header values for a given header name.\n */\n /**\n * Appends a header to existing list of header values for a given header name.\n * @param {?} name\n * @param {?} value\n * @return {?}\n */\n Headers.prototype.append = /**\n * Appends a header to existing list of header values for a given header name.\n * @param {?} name\n * @param {?} value\n * @return {?}\n */\n function (name, value) {\n var /** @type {?} */ values = this.getAll(name);\n if (values === null) {\n this.set(name, value);\n }\n else {\n values.push(value);\n }\n };\n /**\n * Deletes all header values for the given name.\n */\n /**\n * Deletes all header values for the given name.\n * @param {?} name\n * @return {?}\n */\n Headers.prototype.delete = /**\n * Deletes all header values for the given name.\n * @param {?} name\n * @return {?}\n */\n function (name) {\n var /** @type {?} */ lcName = name.toLowerCase();\n this._normalizedNames.delete(lcName);\n this._headers.delete(lcName);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n Headers.prototype.forEach = /**\n * @param {?} fn\n * @return {?}\n */\n function (fn) {\n var _this = this;\n this._headers.forEach(function (values, lcName) { return fn(values, _this._normalizedNames.get(lcName), _this._headers); });\n };\n /**\n * Returns first header that matches given name.\n */\n /**\n * Returns first header that matches given name.\n * @param {?} name\n * @return {?}\n */\n Headers.prototype.get = /**\n * Returns first header that matches given name.\n * @param {?} name\n * @return {?}\n */\n function (name) {\n var /** @type {?} */ values = this.getAll(name);\n if (values === null) {\n return null;\n }\n return values.length > 0 ? values[0] : null;\n };\n /**\n * Checks for existence of header by given name.\n */\n /**\n * Checks for existence of header by given name.\n * @param {?} name\n * @return {?}\n */\n Headers.prototype.has = /**\n * Checks for existence of header by given name.\n * @param {?} name\n * @return {?}\n */\n function (name) { return this._headers.has(name.toLowerCase()); };\n /**\n * Returns the names of the headers\n */\n /**\n * Returns the names of the headers\n * @return {?}\n */\n Headers.prototype.keys = /**\n * Returns the names of the headers\n * @return {?}\n */\n function () { return Array.from(this._normalizedNames.values()); };\n /**\n * Sets or overrides header value for given name.\n */\n /**\n * Sets or overrides header value for given name.\n * @param {?} name\n * @param {?} value\n * @return {?}\n */\n Headers.prototype.set = /**\n * Sets or overrides header value for given name.\n * @param {?} name\n * @param {?} value\n * @return {?}\n */\n function (name, value) {\n if (Array.isArray(value)) {\n if (value.length) {\n this._headers.set(name.toLowerCase(), [value.join(',')]);\n }\n }\n else {\n this._headers.set(name.toLowerCase(), [value]);\n }\n this.mayBeSetNormalizedName(name);\n };\n /**\n * Returns values of all headers.\n */\n /**\n * Returns values of all headers.\n * @return {?}\n */\n Headers.prototype.values = /**\n * Returns values of all headers.\n * @return {?}\n */\n function () { return Array.from(this._headers.values()); };\n /**\n * Returns string of all headers.\n */\n // TODO(vicb): returns {[name: string]: string[]}\n /**\n * Returns string of all headers.\n * @return {?}\n */\n Headers.prototype.toJSON = /**\n * Returns string of all headers.\n * @return {?}\n */\n function () {\n var _this = this;\n var /** @type {?} */ serialized = {};\n this._headers.forEach(function (values, name) {\n var /** @type {?} */ split = [];\n values.forEach(function (v) { return split.push.apply(split, v.split(',')); });\n serialized[/** @type {?} */ ((_this._normalizedNames.get(name)))] = split;\n });\n return serialized;\n };\n /**\n * Returns list of header values for a given name.\n */\n /**\n * Returns list of header values for a given name.\n * @param {?} name\n * @return {?}\n */\n Headers.prototype.getAll = /**\n * Returns list of header values for a given name.\n * @param {?} name\n * @return {?}\n */\n function (name) {\n return this.has(name) ? this._headers.get(name.toLowerCase()) || null : null;\n };\n /**\n * This method is not implemented.\n */\n /**\n * This method is not implemented.\n * @return {?}\n */\n Headers.prototype.entries = /**\n * This method is not implemented.\n * @return {?}\n */\n function () { throw new Error('\"entries\" method is not implemented on Headers class'); };\n /**\n * @param {?} name\n * @return {?}\n */\n Headers.prototype.mayBeSetNormalizedName = /**\n * @param {?} name\n * @return {?}\n */\n function (name) {\n var /** @type {?} */ lcName = name.toLowerCase();\n if (!this._normalizedNames.has(lcName)) {\n this._normalizedNames.set(lcName, name);\n }\n };\n return Headers;\n}());\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * Creates a response options object to be optionally provided when instantiating a\n * {\\@link Response}.\n *\n * This class is based on the `ResponseInit` description in the [Fetch\n * Spec](https://fetch.spec.whatwg.org/#responseinit).\n *\n * All values are null by default. Typical defaults can be found in the\n * {\\@link BaseResponseOptions} class, which sub-classes `ResponseOptions`.\n *\n * This class may be used in tests to build {\\@link Response Responses} for\n * mock responses (see {\\@link MockBackend}).\n *\n * ### Example ([live demo](http://plnkr.co/edit/P9Jkk8e8cz6NVzbcxEsD?p=preview))\n *\n * ```typescript\n * import {ResponseOptions, Response} from '\\@angular/http';\n *\n * var options = new ResponseOptions({\n * body: '{\"name\":\"Jeff\"}'\n * });\n * var res = new Response(options);\n *\n * console.log('res.json():', res.json()); // Object {name: \"Jeff\"}\n * ```\n *\n * @deprecated use \\@angular/common/http instead\n */\nvar ResponseOptions = (function () {\n function ResponseOptions(opts) {\n if (opts === void 0) { opts = {}; }\n var body = opts.body, status = opts.status, headers = opts.headers, statusText = opts.statusText, type = opts.type, url = opts.url;\n this.body = body != null ? body : null;\n this.status = status != null ? status : null;\n this.headers = headers != null ? headers : null;\n this.statusText = statusText != null ? statusText : null;\n this.type = type != null ? type : null;\n this.url = url != null ? url : null;\n }\n /**\n * Creates a copy of the `ResponseOptions` instance, using the optional input as values to\n * override\n * existing values. This method will not change the values of the instance on which it is being\n * called.\n *\n * This may be useful when sharing a base `ResponseOptions` object inside tests,\n * where certain properties may change from test to test.\n *\n * ### Example ([live demo](http://plnkr.co/edit/1lXquqFfgduTFBWjNoRE?p=preview))\n *\n * ```typescript\n * import {ResponseOptions, Response} from '@angular/http';\n *\n * var options = new ResponseOptions({\n * body: {name: 'Jeff'}\n * });\n * var res = new Response(options.merge({\n * url: 'https://google.com'\n * }));\n * console.log('options.url:', options.url); // null\n * console.log('res.json():', res.json()); // Object {name: \"Jeff\"}\n * console.log('res.url:', res.url); // https://google.com\n * ```\n */\n /**\n * Creates a copy of the `ResponseOptions` instance, using the optional input as values to\n * override\n * existing values. This method will not change the values of the instance on which it is being\n * called.\n *\n * This may be useful when sharing a base `ResponseOptions` object inside tests,\n * where certain properties may change from test to test.\n *\n * ### Example ([live demo](http://plnkr.co/edit/1lXquqFfgduTFBWjNoRE?p=preview))\n *\n * ```typescript\n * import {ResponseOptions, Response} from '\\@angular/http';\n *\n * var options = new ResponseOptions({\n * body: {name: 'Jeff'}\n * });\n * var res = new Response(options.merge({\n * url: 'https://google.com'\n * }));\n * console.log('options.url:', options.url); // null\n * console.log('res.json():', res.json()); // Object {name: \"Jeff\"}\n * console.log('res.url:', res.url); // https://google.com\n * ```\n * @param {?=} options\n * @return {?}\n */\n ResponseOptions.prototype.merge = /**\n * Creates a copy of the `ResponseOptions` instance, using the optional input as values to\n * override\n * existing values. This method will not change the values of the instance on which it is being\n * called.\n *\n * This may be useful when sharing a base `ResponseOptions` object inside tests,\n * where certain properties may change from test to test.\n *\n * ### Example ([live demo](http://plnkr.co/edit/1lXquqFfgduTFBWjNoRE?p=preview))\n *\n * ```typescript\n * import {ResponseOptions, Response} from '\\@angular/http';\n *\n * var options = new ResponseOptions({\n * body: {name: 'Jeff'}\n * });\n * var res = new Response(options.merge({\n * url: 'https://google.com'\n * }));\n * console.log('options.url:', options.url); // null\n * console.log('res.json():', res.json()); // Object {name: \"Jeff\"}\n * console.log('res.url:', res.url); // https://google.com\n * ```\n * @param {?=} options\n * @return {?}\n */\n function (options) {\n return new ResponseOptions({\n body: options && options.body != null ? options.body : this.body,\n status: options && options.status != null ? options.status : this.status,\n headers: options && options.headers != null ? options.headers : this.headers,\n statusText: options && options.statusText != null ? options.statusText : this.statusText,\n type: options && options.type != null ? options.type : this.type,\n url: options && options.url != null ? options.url : this.url,\n });\n };\n return ResponseOptions;\n}());\n/**\n * Subclass of {\\@link ResponseOptions}, with default values.\n *\n * Default values:\n * * status: 200\n * * headers: empty {\\@link Headers} object\n *\n * This class could be extended and bound to the {\\@link ResponseOptions} class\n * when configuring an {\\@link Injector}, in order to override the default options\n * used by {\\@link Http} to create {\\@link Response Responses}.\n *\n * ### Example ([live demo](http://plnkr.co/edit/qv8DLT?p=preview))\n *\n * ```typescript\n * import {provide} from '\\@angular/core';\n * import {bootstrap} from '\\@angular/platform-browser/browser';\n * import {HTTP_PROVIDERS, Headers, Http, BaseResponseOptions, ResponseOptions} from\n * '\\@angular/http';\n * import {App} from './myapp';\n *\n * class MyOptions extends BaseResponseOptions {\n * headers:Headers = new Headers({network: 'github'});\n * }\n *\n * bootstrap(App, [HTTP_PROVIDERS, {provide: ResponseOptions, useClass: MyOptions}]);\n * ```\n *\n * The options could also be extended when manually creating a {\\@link Response}\n * object.\n *\n * ### Example ([live demo](http://plnkr.co/edit/VngosOWiaExEtbstDoix?p=preview))\n *\n * ```\n * import {BaseResponseOptions, Response} from '\\@angular/http';\n *\n * var options = new BaseResponseOptions();\n * var res = new Response(options.merge({\n * body: 'Angular',\n * headers: new Headers({framework: 'angular'})\n * }));\n * console.log('res.headers.get(\"framework\"):', res.headers.get('framework')); // angular\n * console.log('res.text():', res.text()); // Angular;\n * ```\n *\n * @deprecated use \\@angular/common/http instead\n */\nvar BaseResponseOptions = (function (_super) {\n __extends(BaseResponseOptions, _super);\n function BaseResponseOptions() {\n return _super.call(this, { status: 200, statusText: 'Ok', type: ResponseType.Default, headers: new Headers() }) || this;\n }\n BaseResponseOptions.decorators = [\n { type: Injectable },\n ];\n /** @nocollapse */\n BaseResponseOptions.ctorParameters = function () { return []; };\n return BaseResponseOptions;\n}(ResponseOptions));\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * Abstract class from which real backends are derived.\n *\n * The primary purpose of a `ConnectionBackend` is to create new connections to fulfill a given\n * {\\@link Request}.\n *\n * @deprecated use \\@angular/common/http instead\n * @abstract\n */\nvar ConnectionBackend = (function () {\n function ConnectionBackend() {\n }\n return ConnectionBackend;\n}());\n/**\n * Abstract class from which real connections are derived.\n *\n * @deprecated use \\@angular/common/http instead\n * @abstract\n */\nvar Connection = (function () {\n function Connection() {\n }\n return Connection;\n}());\n/**\n * An XSRFStrategy configures XSRF protection (e.g. via headers) on an HTTP request.\n *\n * @deprecated use \\@angular/common/http instead\n * @abstract\n */\nvar XSRFStrategy = (function () {\n function XSRFStrategy() {\n }\n return XSRFStrategy;\n}());\n/**\n * Interface for options to construct a RequestOptions, based on\n * [RequestInit](https://fetch.spec.whatwg.org/#requestinit) from the Fetch spec.\n *\n * @deprecated use \\@angular/common/http instead\n * @record\n */\n\n/**\n * Required structure when constructing new Request();\n * @record\n */\n\n/**\n * Interface for options to construct a Response, based on\n * [ResponseInit](https://fetch.spec.whatwg.org/#responseinit) from the Fetch spec.\n *\n * @deprecated use \\@angular/common/http instead\n * @record\n */\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @param {?} method\n * @return {?}\n */\nfunction normalizeMethodName(method) {\n if (typeof method !== 'string')\n return method;\n switch (method.toUpperCase()) {\n case 'GET':\n return RequestMethod.Get;\n case 'POST':\n return RequestMethod.Post;\n case 'PUT':\n return RequestMethod.Put;\n case 'DELETE':\n return RequestMethod.Delete;\n case 'OPTIONS':\n return RequestMethod.Options;\n case 'HEAD':\n return RequestMethod.Head;\n case 'PATCH':\n return RequestMethod.Patch;\n }\n throw new Error(\"Invalid request method. The method \\\"\" + method + \"\\\" is not supported.\");\n}\nvar isSuccess = function (status) { return (status >= 200 && status < 300); };\n/**\n * @param {?} xhr\n * @return {?}\n */\nfunction getResponseURL(xhr) {\n if ('responseURL' in xhr) {\n return xhr.responseURL;\n }\n if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {\n return xhr.getResponseHeader('X-Request-URL');\n }\n return null;\n}\n/**\n * @param {?} input\n * @return {?}\n */\n\n/**\n * @param {?} input\n * @return {?}\n */\nfunction stringToArrayBuffer(input) {\n var /** @type {?} */ view = new Uint16Array(input.length);\n for (var /** @type {?} */ i = 0, /** @type {?} */ strLen = input.length; i < strLen; i++) {\n view[i] = input.charCodeAt(i);\n }\n return view.buffer;\n}\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @param {?=} rawParams\n * @return {?}\n */\nfunction paramParser(rawParams) {\n if (rawParams === void 0) { rawParams = ''; }\n var /** @type {?} */ map = new Map();\n if (rawParams.length > 0) {\n var /** @type {?} */ params = rawParams.split('&');\n params.forEach(function (param) {\n var /** @type {?} */ eqIdx = param.indexOf('=');\n var _a = eqIdx == -1 ? [param, ''] : [param.slice(0, eqIdx), param.slice(eqIdx + 1)], key = _a[0], val = _a[1];\n var /** @type {?} */ list = map.get(key) || [];\n list.push(val);\n map.set(key, list);\n });\n }\n return map;\n}\n/**\n * @deprecated use \\@angular/common/http instead\n *\n */\nvar QueryEncoder = (function () {\n function QueryEncoder() {\n }\n /**\n * @param {?} k\n * @return {?}\n */\n QueryEncoder.prototype.encodeKey = /**\n * @param {?} k\n * @return {?}\n */\n function (k) { return standardEncoding(k); };\n /**\n * @param {?} v\n * @return {?}\n */\n QueryEncoder.prototype.encodeValue = /**\n * @param {?} v\n * @return {?}\n */\n function (v) { return standardEncoding(v); };\n return QueryEncoder;\n}());\n/**\n * @param {?} v\n * @return {?}\n */\nfunction standardEncoding(v) {\n return encodeURIComponent(v)\n .replace(/%40/gi, '@')\n .replace(/%3A/gi, ':')\n .replace(/%24/gi, '$')\n .replace(/%2C/gi, ',')\n .replace(/%3B/gi, ';')\n .replace(/%2B/gi, '+')\n .replace(/%3D/gi, '=')\n .replace(/%3F/gi, '?')\n .replace(/%2F/gi, '/');\n}\n/**\n * Map-like representation of url search parameters, based on\n * [URLSearchParams](https://url.spec.whatwg.org/#urlsearchparams) in the url living standard,\n * with several extensions for merging URLSearchParams objects:\n * - setAll()\n * - appendAll()\n * - replaceAll()\n *\n * This class accepts an optional second parameter of ${\\@link QueryEncoder},\n * which is used to serialize parameters before making a request. By default,\n * `QueryEncoder` encodes keys and values of parameters using `encodeURIComponent`,\n * and then un-encodes certain characters that are allowed to be part of the query\n * according to IETF RFC 3986: https://tools.ietf.org/html/rfc3986.\n *\n * These are the characters that are not encoded: `! $ \\' ( ) * + , ; A 9 - . _ ~ ? /`\n *\n * If the set of allowed query characters is not acceptable for a particular backend,\n * `QueryEncoder` can be subclassed and provided as the 2nd argument to URLSearchParams.\n *\n * ```\n * import {URLSearchParams, QueryEncoder} from '\\@angular/http';\n * class MyQueryEncoder extends QueryEncoder {\n * encodeKey(k: string): string {\n * return myEncodingFunction(k);\n * }\n *\n * encodeValue(v: string): string {\n * return myEncodingFunction(v);\n * }\n * }\n *\n * let params = new URLSearchParams('', new MyQueryEncoder());\n * ```\n * @deprecated use \\@angular/common/http instead\n */\nvar URLSearchParams = (function () {\n function URLSearchParams(rawParams, queryEncoder) {\n if (rawParams === void 0) { rawParams = ''; }\n if (queryEncoder === void 0) { queryEncoder = new QueryEncoder(); }\n this.rawParams = rawParams;\n this.queryEncoder = queryEncoder;\n this.paramsMap = paramParser(rawParams);\n }\n /**\n * @return {?}\n */\n URLSearchParams.prototype.clone = /**\n * @return {?}\n */\n function () {\n var /** @type {?} */ clone = new URLSearchParams('', this.queryEncoder);\n clone.appendAll(this);\n return clone;\n };\n /**\n * @param {?} param\n * @return {?}\n */\n URLSearchParams.prototype.has = /**\n * @param {?} param\n * @return {?}\n */\n function (param) { return this.paramsMap.has(param); };\n /**\n * @param {?} param\n * @return {?}\n */\n URLSearchParams.prototype.get = /**\n * @param {?} param\n * @return {?}\n */\n function (param) {\n var /** @type {?} */ storedParam = this.paramsMap.get(param);\n return Array.isArray(storedParam) ? storedParam[0] : null;\n };\n /**\n * @param {?} param\n * @return {?}\n */\n URLSearchParams.prototype.getAll = /**\n * @param {?} param\n * @return {?}\n */\n function (param) { return this.paramsMap.get(param) || []; };\n /**\n * @param {?} param\n * @param {?} val\n * @return {?}\n */\n URLSearchParams.prototype.set = /**\n * @param {?} param\n * @param {?} val\n * @return {?}\n */\n function (param, val) {\n if (val === void 0 || val === null) {\n this.delete(param);\n return;\n }\n var /** @type {?} */ list = this.paramsMap.get(param) || [];\n list.length = 0;\n list.push(val);\n this.paramsMap.set(param, list);\n };\n // A merge operation\n // For each name-values pair in `searchParams`, perform `set(name, values[0])`\n //\n // E.g: \"a=[1,2,3], c=[8]\" + \"a=[4,5,6], b=[7]\" = \"a=[4], c=[8], b=[7]\"\n //\n // TODO(@caitp): document this better\n /**\n * @param {?} searchParams\n * @return {?}\n */\n URLSearchParams.prototype.setAll = /**\n * @param {?} searchParams\n * @return {?}\n */\n function (searchParams) {\n var _this = this;\n searchParams.paramsMap.forEach(function (value, param) {\n var /** @type {?} */ list = _this.paramsMap.get(param) || [];\n list.length = 0;\n list.push(value[0]);\n _this.paramsMap.set(param, list);\n });\n };\n /**\n * @param {?} param\n * @param {?} val\n * @return {?}\n */\n URLSearchParams.prototype.append = /**\n * @param {?} param\n * @param {?} val\n * @return {?}\n */\n function (param, val) {\n if (val === void 0 || val === null)\n return;\n var /** @type {?} */ list = this.paramsMap.get(param) || [];\n list.push(val);\n this.paramsMap.set(param, list);\n };\n // A merge operation\n // For each name-values pair in `searchParams`, perform `append(name, value)`\n // for each value in `values`.\n //\n // E.g: \"a=[1,2], c=[8]\" + \"a=[3,4], b=[7]\" = \"a=[1,2,3,4], c=[8], b=[7]\"\n //\n // TODO(@caitp): document this better\n /**\n * @param {?} searchParams\n * @return {?}\n */\n URLSearchParams.prototype.appendAll = /**\n * @param {?} searchParams\n * @return {?}\n */\n function (searchParams) {\n var _this = this;\n searchParams.paramsMap.forEach(function (value, param) {\n var /** @type {?} */ list = _this.paramsMap.get(param) || [];\n for (var /** @type {?} */ i = 0; i < value.length; ++i) {\n list.push(value[i]);\n }\n _this.paramsMap.set(param, list);\n });\n };\n // A merge operation\n // For each name-values pair in `searchParams`, perform `delete(name)`,\n // followed by `set(name, values)`\n //\n // E.g: \"a=[1,2,3], c=[8]\" + \"a=[4,5,6], b=[7]\" = \"a=[4,5,6], c=[8], b=[7]\"\n //\n // TODO(@caitp): document this better\n /**\n * @param {?} searchParams\n * @return {?}\n */\n URLSearchParams.prototype.replaceAll = /**\n * @param {?} searchParams\n * @return {?}\n */\n function (searchParams) {\n var _this = this;\n searchParams.paramsMap.forEach(function (value, param) {\n var /** @type {?} */ list = _this.paramsMap.get(param) || [];\n list.length = 0;\n for (var /** @type {?} */ i = 0; i < value.length; ++i) {\n list.push(value[i]);\n }\n _this.paramsMap.set(param, list);\n });\n };\n /**\n * @return {?}\n */\n URLSearchParams.prototype.toString = /**\n * @return {?}\n */\n function () {\n var _this = this;\n var /** @type {?} */ paramsList = [];\n this.paramsMap.forEach(function (values, k) {\n values.forEach(function (v) {\n return paramsList.push(_this.queryEncoder.encodeKey(k) + '=' + _this.queryEncoder.encodeValue(v));\n });\n });\n return paramsList.join('&');\n };\n /**\n * @param {?} param\n * @return {?}\n */\n URLSearchParams.prototype.delete = /**\n * @param {?} param\n * @return {?}\n */\n function (param) { this.paramsMap.delete(param); };\n return URLSearchParams;\n}());\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * HTTP request body used by both {\\@link Request} and {\\@link Response}\n * https://fetch.spec.whatwg.org/#body\n * @abstract\n */\nvar Body = (function () {\n function Body() {\n }\n /**\n * Attempts to return body as parsed `JSON` object, or raises an exception.\n */\n /**\n * Attempts to return body as parsed `JSON` object, or raises an exception.\n * @return {?}\n */\n Body.prototype.json = /**\n * Attempts to return body as parsed `JSON` object, or raises an exception.\n * @return {?}\n */\n function () {\n if (typeof this._body === 'string') {\n return JSON.parse(/** @type {?} */ (this._body));\n }\n if (this._body instanceof ArrayBuffer) {\n return JSON.parse(this.text());\n }\n return this._body;\n };\n /**\n * Returns the body as a string, presuming `toString()` can be called on the response body.\n *\n * When decoding an `ArrayBuffer`, the optional `encodingHint` parameter determines how the\n * bytes in the buffer will be interpreted. Valid values are:\n *\n * - `legacy` - incorrectly interpret the bytes as UTF-16 (technically, UCS-2). Only characters\n * in the Basic Multilingual Plane are supported, surrogate pairs are not handled correctly.\n * In addition, the endianness of the 16-bit octet pairs in the `ArrayBuffer` is not taken\n * into consideration. This is the default behavior to avoid breaking apps, but should be\n * considered deprecated.\n *\n * - `iso-8859` - interpret the bytes as ISO-8859 (which can be used for ASCII encoded text).\n */\n /**\n * Returns the body as a string, presuming `toString()` can be called on the response body.\n *\n * When decoding an `ArrayBuffer`, the optional `encodingHint` parameter determines how the\n * bytes in the buffer will be interpreted. Valid values are:\n *\n * - `legacy` - incorrectly interpret the bytes as UTF-16 (technically, UCS-2). Only characters\n * in the Basic Multilingual Plane are supported, surrogate pairs are not handled correctly.\n * In addition, the endianness of the 16-bit octet pairs in the `ArrayBuffer` is not taken\n * into consideration. This is the default behavior to avoid breaking apps, but should be\n * considered deprecated.\n *\n * - `iso-8859` - interpret the bytes as ISO-8859 (which can be used for ASCII encoded text).\n * @param {?=} encodingHint\n * @return {?}\n */\n Body.prototype.text = /**\n * Returns the body as a string, presuming `toString()` can be called on the response body.\n *\n * When decoding an `ArrayBuffer`, the optional `encodingHint` parameter determines how the\n * bytes in the buffer will be interpreted. Valid values are:\n *\n * - `legacy` - incorrectly interpret the bytes as UTF-16 (technically, UCS-2). Only characters\n * in the Basic Multilingual Plane are supported, surrogate pairs are not handled correctly.\n * In addition, the endianness of the 16-bit octet pairs in the `ArrayBuffer` is not taken\n * into consideration. This is the default behavior to avoid breaking apps, but should be\n * considered deprecated.\n *\n * - `iso-8859` - interpret the bytes as ISO-8859 (which can be used for ASCII encoded text).\n * @param {?=} encodingHint\n * @return {?}\n */\n function (encodingHint) {\n if (encodingHint === void 0) { encodingHint = 'legacy'; }\n if (this._body instanceof URLSearchParams) {\n return this._body.toString();\n }\n if (this._body instanceof ArrayBuffer) {\n switch (encodingHint) {\n case 'legacy':\n return String.fromCharCode.apply(null, new Uint16Array(/** @type {?} */ (this._body)));\n case 'iso-8859':\n return String.fromCharCode.apply(null, new Uint8Array(/** @type {?} */ (this._body)));\n default:\n throw new Error(\"Invalid value for encodingHint: \" + encodingHint);\n }\n }\n if (this._body == null) {\n return '';\n }\n if (typeof this._body === 'object') {\n return JSON.stringify(this._body, null, 2);\n }\n return this._body.toString();\n };\n /**\n * Return the body as an ArrayBuffer\n */\n /**\n * Return the body as an ArrayBuffer\n * @return {?}\n */\n Body.prototype.arrayBuffer = /**\n * Return the body as an ArrayBuffer\n * @return {?}\n */\n function () {\n if (this._body instanceof ArrayBuffer) {\n return /** @type {?} */ (this._body);\n }\n return stringToArrayBuffer(this.text());\n };\n /**\n * Returns the request's body as a Blob, assuming that body exists.\n */\n /**\n * Returns the request's body as a Blob, assuming that body exists.\n * @return {?}\n */\n Body.prototype.blob = /**\n * Returns the request's body as a Blob, assuming that body exists.\n * @return {?}\n */\n function () {\n if (this._body instanceof Blob) {\n return /** @type {?} */ (this._body);\n }\n if (this._body instanceof ArrayBuffer) {\n return new Blob([this._body]);\n }\n throw new Error('The request body isn\\'t either a blob or an array buffer');\n };\n return Body;\n}());\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * Creates `Response` instances from provided values.\n *\n * Though this object isn't\n * usually instantiated by end-users, it is the primary object interacted with when it comes time to\n * add data to a view.\n *\n * ### Example\n *\n * ```\n * http.request('my-friends.txt').subscribe(response => this.friends = response.text());\n * ```\n *\n * The Response's interface is inspired by the Response constructor defined in the [Fetch\n * Spec](https://fetch.spec.whatwg.org/#response-class), but is considered a static value whose body\n * can be accessed many times. There are other differences in the implementation, but this is the\n * most significant.\n *\n * @deprecated use \\@angular/common/http instead\n */\nvar Response = (function (_super) {\n __extends(Response, _super);\n function Response(responseOptions) {\n var _this = _super.call(this) || this;\n _this._body = responseOptions.body;\n _this.status = /** @type {?} */ ((responseOptions.status));\n _this.ok = (_this.status >= 200 && _this.status <= 299);\n _this.statusText = responseOptions.statusText;\n _this.headers = responseOptions.headers;\n _this.type = /** @type {?} */ ((responseOptions.type));\n _this.url = /** @type {?} */ ((responseOptions.url));\n return _this;\n }\n /**\n * @return {?}\n */\n Response.prototype.toString = /**\n * @return {?}\n */\n function () {\n return \"Response with status: \" + this.status + \" \" + this.statusText + \" for URL: \" + this.url;\n };\n return Response;\n}(Body));\n\n/**\n * @fileoverview added by tsickle\n * @suppress {checkTypes} checked by tsc\n */\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar _nextRequestId = 0;\nvar JSONP_HOME = '__ng_jsonp__';\nvar _jsonpConnections = null;\n/**\n * @return {?}\n */\nfunction _getJsonpConnections() {\n var /** @type {?} */ w = typeof window == 'object' ? window : {};\n if (_jsonpConnections === null) {\n _jsonpConnections = w[JSONP_HOME] = {};\n }\n return _jsonpConnections;\n}\nvar BrowserJsonp = (function () {\n function BrowserJsonp() {\n }\n // Construct a - - Ionic App - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platforms/android/app/src/main/assets/www/manifest.json b/platforms/android/app/src/main/assets/www/manifest.json deleted file mode 100755 index f6456bbb..00000000 --- a/platforms/android/app/src/main/assets/www/manifest.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "Ionic", - "short_name": "Ionic", - "start_url": "index.html", - "display": "standalone", - "icons": [{ - "src": "assets/imgs/logo.png", - "sizes": "512x512", - "type": "image/png" - }], - "background_color": "#4e8ef7", - "theme_color": "#4e8ef7" -} \ No newline at end of file diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-actionsheet/www/ActionSheet.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-actionsheet/www/ActionSheet.js deleted file mode 100644 index 2b703acc..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-actionsheet/www/ActionSheet.js +++ /dev/null @@ -1,32 +0,0 @@ -cordova.define("cordova-plugin-actionsheet.ActionSheet", function(require, exports, module) { -function ActionSheet() { -} - -ActionSheet.prototype.show = function (options, successCallback, errorCallback) { - cordova.exec(successCallback, errorCallback, "ActionSheet", "show", [options]); -}; - -ActionSheet.prototype.hide = function (options, successCallback, errorCallback) { - cordova.exec(successCallback, errorCallback, "ActionSheet", "hide", [options]); -}; - -ActionSheet.prototype.ANDROID_THEMES = { - THEME_TRADITIONAL : 1, // default - THEME_HOLO_DARK : 2, - THEME_HOLO_LIGHT : 3, - THEME_DEVICE_DEFAULT_DARK : 4, - THEME_DEVICE_DEFAULT_LIGHT : 5 -}; - -ActionSheet.install = function () { - if (!window.plugins) { - window.plugins = {}; - } - - window.plugins.actionsheet = new ActionSheet(); - - return window.plugins.actionsheet; -}; - -cordova.addConstructor(ActionSheet.install); -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-android-permissions/www/permissions.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-android-permissions/www/permissions.js deleted file mode 100644 index 30651e95..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-android-permissions/www/permissions.js +++ /dev/null @@ -1,197 +0,0 @@ -cordova.define("cordova-plugin-android-permissions.Permissions", function(require, exports, module) { -var permissionsName = 'Permissions'; - -function Permissions() { - - this.ACCESS_CHECKIN_PROPERTIES = 'android.permission.ACCESS_CHECKIN_PROPERTIES'; - this.ACCESS_COARSE_LOCATION = 'android.permission.ACCESS_COARSE_LOCATION'; - this.ACCESS_FINE_LOCATION = 'android.permission.ACCESS_FINE_LOCATION'; - this.ACCESS_LOCATION_EXTRA_COMMANDS = 'android.permission.ACCESS_LOCATION_EXTRA_COMMANDS'; - this.ACCESS_MOCK_LOCATION = 'android.permission.ACCESS_MOCK_LOCATION'; - this.ACCESS_NETWORK_STATE = 'android.permission.ACCESS_NETWORK_STATE'; - this.ACCESS_SURFACE_FLINGER = 'android.permission.ACCESS_SURFACE_FLINGER'; - this.ACCESS_WIFI_STATE = 'android.permission.ACCESS_WIFI_STATE'; - this.ACCOUNT_MANAGER = 'android.permission.ACCOUNT_MANAGER'; - this.ADD_VOICEMAIL = 'com.android.voicemail.permission.ADD_VOICEMAIL'; - this.AUTHENTICATE_ACCOUNTS = 'android.permission.AUTHENTICATE_ACCOUNTS'; - this.BATTERY_STATS = 'android.permission.BATTERY_STATS'; - this.BIND_ACCESSIBILITY_SERVICE = 'android.permission.BIND_ACCESSIBILITY_SERVICE'; - this.BIND_APPWIDGET = 'android.permission.BIND_APPWIDGET'; - this.BIND_CARRIER_MESSAGING_SERVICE = 'android.permission.BIND_CARRIER_MESSAGING_SERVICE'; - this.BIND_DEVICE_ADMIN = 'android.permission.BIND_DEVICE_ADMIN'; - this.BIND_DREAM_SERVICE = 'android.permission.BIND_DREAM_SERVICE'; - this.BIND_INPUT_METHOD = 'android.permission.BIND_INPUT_METHOD'; - this.BIND_NFC_SERVICE = 'android.permission.BIND_NFC_SERVICE'; - this.BIND_NOTIFICATION_LISTENER_SERVICE = 'android.permission.BIND_NOTIFICATION_LISTENER_SERVICE'; - this.BIND_PRINT_SERVICE = 'android.permission.BIND_PRINT_SERVICE'; - this.BIND_REMOTEVIEWS = 'android.permission.BIND_REMOTEVIEWS'; - this.BIND_TEXT_SERVICE = 'android.permission.BIND_TEXT_SERVICE'; - this.BIND_TV_INPUT = 'android.permission.BIND_TV_INPUT'; - this.BIND_VOICE_INTERACTION = 'android.permission.BIND_VOICE_INTERACTION'; - this.BIND_VPN_SERVICE = 'android.permission.BIND_VPN_SERVICE'; - this.BIND_WALLPAPER = 'android.permission.BIND_WALLPAPER'; - this.BLUETOOTH = 'android.permission.BLUETOOTH'; - this.BLUETOOTH_ADMIN = 'android.permission.BLUETOOTH_ADMIN'; - this.BLUETOOTH_PRIVILEGED = 'android.permission.BLUETOOTH_PRIVILEGED'; - this.BODY_SENSORS = 'android.permission.BODY_SENSORS'; - this.BRICK = 'android.permission.BRICK'; - this.BROADCAST_PACKAGE_REMOVED = 'android.permission.BROADCAST_PACKAGE_REMOVED'; - this.BROADCAST_SMS = 'android.permission.BROADCAST_SMS'; - this.BROADCAST_STICKY = 'android.permission.BROADCAST_STICKY'; - this.BROADCAST_WAP_PUSH = 'android.permission.BROADCAST_WAP_PUSH'; - this.CALL_PHONE = 'android.permission.CALL_PHONE'; - this.CALL_PRIVILEGED = 'android.permission.CALL_PRIVILEGED'; - this.CAMERA = 'android.permission.CAMERA'; - this.CAPTURE_AUDIO_OUTPUT = 'android.permission.CAPTURE_AUDIO_OUTPUT'; - this.CAPTURE_SECURE_VIDEO_OUTPUT = 'android.permission.CAPTURE_SECURE_VIDEO_OUTPUT'; - this.CAPTURE_VIDEO_OUTPUT = 'android.permission.CAPTURE_VIDEO_OUTPUT'; - this.CHANGE_COMPONENT_ENABLED_STATE = 'android.permission.CHANGE_COMPONENT_ENABLED_STATE'; - this.CHANGE_CONFIGURATION = 'android.permission.CHANGE_CONFIGURATION'; - this.CHANGE_NETWORK_STATE = 'android.permission.CHANGE_NETWORK_STATE'; - this.CHANGE_WIFI_MULTICAST_STATE = 'android.permission.CHANGE_WIFI_MULTICAST_STATE'; - this.CHANGE_WIFI_STATE = 'android.permission.CHANGE_WIFI_STATE'; - this.CLEAR_APP_CACHE = 'android.permission.CLEAR_APP_CACHE'; - this.CLEAR_APP_USER_DATA = 'android.permission.CLEAR_APP_USER_DATA'; - this.CONTROL_LOCATION_UPDATES = 'android.permission.CONTROL_LOCATION_UPDATES'; - this.DELETE_CACHE_FILES = 'android.permission.DELETE_CACHE_FILES'; - this.DELETE_PACKAGES = 'android.permission.DELETE_PACKAGES'; - this.DEVICE_POWER = 'android.permission.DEVICE_POWER'; - this.DIAGNOSTIC = 'android.permission.DIAGNOSTIC'; - this.DISABLE_KEYGUARD = 'android.permission.DISABLE_KEYGUARD'; - this.DUMP = 'android.permission.DUMP'; - this.EXPAND_STATUS_BAR = 'android.permission.EXPAND_STATUS_BAR'; - this.FACTORY_TEST = 'android.permission.FACTORY_TEST'; - this.FLASHLIGHT = 'android.permission.FLASHLIGHT'; - this.FORCE_BACK = 'android.permission.FORCE_BACK'; - this.GET_ACCOUNTS = 'android.permission.GET_ACCOUNTS'; - this.GET_PACKAGE_SIZE = 'android.permission.GET_PACKAGE_SIZE'; - this.GET_TASKS = 'android.permission.GET_TASKS'; - this.GET_TOP_ACTIVITY_INFO = 'android.permission.GET_TOP_ACTIVITY_INFO'; - this.GLOBAL_SEARCH = 'android.permission.GLOBAL_SEARCH'; - this.HARDWARE_TEST = 'android.permission.HARDWARE_TEST'; - this.INJECT_EVENTS = 'android.permission.INJECT_EVENTS'; - this.INSTALL_LOCATION_PROVIDER = 'android.permission.INSTALL_LOCATION_PROVIDER'; - this.INSTALL_PACKAGES = 'android.permission.INSTALL_PACKAGES'; - this.INSTALL_SHORTCUT = 'com.android.launcher.permission.INSTALL_SHORTCUT'; - this.INTERNAL_SYSTEM_WINDOW = 'android.permission.INTERNAL_SYSTEM_WINDOW'; - this.INTERNET = 'android.permission.INTERNET'; - this.KILL_BACKGROUND_PROCESSES = 'android.permission.KILL_BACKGROUND_PROCESSES'; - this.LOCATION_HARDWARE = 'android.permission.LOCATION_HARDWARE'; - this.MANAGE_ACCOUNTS = 'android.permission.MANAGE_ACCOUNTS'; - this.MANAGE_APP_TOKENS = 'android.permission.MANAGE_APP_TOKENS'; - this.MANAGE_DOCUMENTS = 'android.permission.MANAGE_DOCUMENTS'; - this.MASTER_CLEAR = 'android.permission.MASTER_CLEAR'; - this.MEDIA_CONTENT_CONTROL = 'android.permission.MEDIA_CONTENT_CONTROL'; - this.MODIFY_AUDIO_SETTINGS = 'android.permission.MODIFY_AUDIO_SETTINGS'; - this.MODIFY_PHONE_STATE = 'android.permission.MODIFY_PHONE_STATE'; - this.MOUNT_FORMAT_FILESYSTEMS = 'android.permission.MOUNT_FORMAT_FILESYSTEMS'; - this.MOUNT_UNMOUNT_FILESYSTEMS = 'android.permission.MOUNT_UNMOUNT_FILESYSTEMS'; - this.NFC = 'android.permission.NFC'; - this.PERSISTENT_ACTIVITY = 'android.permission.PERSISTENT_ACTIVITY'; - this.PROCESS_OUTGOING_CALLS = 'android.permission.PROCESS_OUTGOING_CALLS'; - this.READ_CALENDAR = 'android.permission.READ_CALENDAR'; - this.READ_CALL_LOG = 'android.permission.READ_CALL_LOG'; - this.READ_CONTACTS = 'android.permission.READ_CONTACTS'; - this.READ_EXTERNAL_STORAGE = 'android.permission.READ_EXTERNAL_STORAGE'; - this.READ_FRAME_BUFFER = 'android.permission.READ_FRAME_BUFFER'; - this.READ_HISTORY_BOOKMARKS = 'com.android.browser.permission.READ_HISTORY_BOOKMARKS'; - this.READ_INPUT_STATE = 'android.permission.READ_INPUT_STATE'; - this.READ_LOGS = 'android.permission.READ_LOGS'; - this.READ_PHONE_STATE = 'android.permission.READ_PHONE_STATE'; - this.READ_PROFILE = 'android.permission.READ_PROFILE'; - this.READ_SMS = 'android.permission.READ_SMS'; - this.READ_SOCIAL_STREAM = 'android.permission.READ_SOCIAL_STREAM'; - this.READ_SYNC_SETTINGS = 'android.permission.READ_SYNC_SETTINGS'; - this.READ_SYNC_STATS = 'android.permission.READ_SYNC_STATS'; - this.READ_USER_DICTIONARY = 'android.permission.READ_USER_DICTIONARY'; - this.READ_VOICEMAIL = 'com.android.voicemail.permission.READ_VOICEMAIL'; - this.REBOOT = 'android.permission.REBOOT'; - this.RECEIVE_BOOT_COMPLETED = 'android.permission.RECEIVE_BOOT_COMPLETED'; - this.RECEIVE_MMS = 'android.permission.RECEIVE_MMS'; - this.RECEIVE_SMS = 'android.permission.RECEIVE_SMS'; - this.RECEIVE_WAP_PUSH = 'android.permission.RECEIVE_WAP_PUSH'; - this.RECORD_AUDIO = 'android.permission.RECORD_AUDIO'; - this.REORDER_TASKS = 'android.permission.REORDER_TASKS'; - this.RESTART_PACKAGES = 'android.permission.RESTART_PACKAGES'; - this.SEND_RESPOND_VIA_MESSAGE = 'android.permission.SEND_RESPOND_VIA_MESSAGE'; - this.SEND_SMS = 'android.permission.SEND_SMS'; - this.SET_ACTIVITY_WATCHER = 'android.permission.SET_ACTIVITY_WATCHER'; - this.SET_ALARM = 'com.android.alarm.permission.SET_ALARM'; - this.SET_ALWAYS_FINISH = 'android.permission.SET_ALWAYS_FINISH'; - this.SET_ANIMATION_SCALE = 'android.permission.SET_ANIMATION_SCALE'; - this.SET_DEBUG_APP = 'android.permission.SET_DEBUG_APP'; - this.SET_ORIENTATION = 'android.permission.SET_ORIENTATION'; - this.SET_POINTER_SPEED = 'android.permission.SET_POINTER_SPEED'; - this.SET_PREFERRED_APPLICATIONS = 'android.permission.SET_PREFERRED_APPLICATIONS'; - this.SET_PROCESS_LIMIT = 'android.permission.SET_PROCESS_LIMIT'; - this.SET_TIME = 'android.permission.SET_TIME'; - this.SET_TIME_ZONE = 'android.permission.SET_TIME_ZONE'; - this.SET_WALLPAPER = 'android.permission.SET_WALLPAPER'; - this.SET_WALLPAPER_HINTS = 'android.permission.SET_WALLPAPER_HINTS'; - this.SIGNAL_PERSISTENT_PROCESSES = 'android.permission.SIGNAL_PERSISTENT_PROCESSES'; - this.STATUS_BAR = 'android.permission.STATUS_BAR'; - this.SUBSCRIBED_FEEDS_READ = 'android.permission.SUBSCRIBED_FEEDS_READ'; - this.SUBSCRIBED_FEEDS_WRITE = 'android.permission.SUBSCRIBED_FEEDS_WRITE'; - this.SYSTEM_ALERT_WINDOW = 'android.permission.SYSTEM_ALERT_WINDOW'; - this.TRANSMIT_IR = 'android.permission.TRANSMIT_IR'; - this.UNINSTALL_SHORTCUT = 'com.android.launcher.permission.UNINSTALL_SHORTCUT'; - this.UPDATE_DEVICE_STATS = 'android.permission.UPDATE_DEVICE_STATS'; - this.USE_CREDENTIALS = 'android.permission.USE_CREDENTIALS'; - this.USE_SIP = 'android.permission.USE_SIP'; - this.VIBRATE = 'android.permission.VIBRATE'; - this.WAKE_LOCK = 'android.permission.WAKE_LOCK'; - this.WRITE_APN_SETTINGS = 'android.permission.WRITE_APN_SETTINGS'; - this.WRITE_CALENDAR = 'android.permission.WRITE_CALENDAR'; - this.WRITE_CALL_LOG = 'android.permission.WRITE_CALL_LOG'; - this.WRITE_CONTACTS = 'android.permission.WRITE_CONTACTS'; - this.WRITE_EXTERNAL_STORAGE = 'android.permission.WRITE_EXTERNAL_STORAGE'; - this.WRITE_GSERVICES = 'android.permission.WRITE_GSERVICES'; - this.WRITE_HISTORY_BOOKMARKS = 'com.android.browser.permission.WRITE_HISTORY_BOOKMARKS'; - this.WRITE_PROFILE = 'android.permission.WRITE_PROFILE'; - this.WRITE_SECURE_SETTINGS = 'android.permission.WRITE_SECURE_SETTINGS'; - this.WRITE_SETTINGS = 'android.permission.WRITE_SETTINGS'; - this.WRITE_SMS = 'android.permission.WRITE_SMS'; - this.WRITE_SOCIAL_STREAM = 'android.permission.WRITE_SOCIAL_STREAM'; - this.WRITE_SYNC_SETTINGS = 'android.permission.WRITE_SYNC_SETTINGS'; - this.WRITE_USER_DICTIONARY = 'android.permission.WRITE_USER_DICTIONARY'; - this.WRITE_VOICEMAIL = 'com.android.voicemail.permission.WRITE_VOICEMAIL'; -} - -function deprecated(name) { - console.warn("Calling cordova.plugins.permissions." + name + " with the successCallback as first argument is deprecated"); - console.warn("The new signature is '" + name + "(permission, successCallback, errorCallback)'"); -} - -Permissions.prototype = { - checkPermission: function(permission, successCallback, errorCallback) { - cordova.exec(successCallback, errorCallback, permissionsName, 'checkPermission', [permission]); - }, - requestPermission: function(permission, successCallback, errorCallback) { - if (typeof permission === "function") { - deprecated("requestPermission"); - successCallback = arguments[0]; - errorCallback = arguments[1]; - permission = arguments[2]; - } - cordova.exec(successCallback, errorCallback, permissionsName, 'requestPermission', [permission]); - }, - requestPermissions: function(permissions, successCallback, errorCallback) { - cordova.exec(successCallback, errorCallback, permissionsName, 'requestPermissions', permissions); - } -}; - -Permissions.prototype.hasPermission = function (permission, successCallback, errorCallback) { - console.warn("hasPermission() function deprecated. Considers using checkPermission()"); - - if (typeof permission === "function") { - deprecated("hasPermission"); - successCallback = arguments[0]; - errorCallback = arguments[1]; - permission = arguments[2]; - } - this.checkPermission.call(this, permission, successCallback, errorCallback); -}; - -module.exports = new Permissions(); - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js deleted file mode 100644 index 3f614ec8..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js +++ /dev/null @@ -1,188 +0,0 @@ -cordova.define("cordova-plugin-camera.camera", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var argscheck = require('cordova/argscheck'); -var exec = require('cordova/exec'); -var Camera = require('./Camera'); -// XXX: commented out -// CameraPopoverHandle = require('./CameraPopoverHandle'); - -/** - * @namespace navigator - */ - -/** - * @exports camera - */ -var cameraExport = {}; - -// Tack on the Camera Constants to the base camera plugin. -for (var key in Camera) { - cameraExport[key] = Camera[key]; -} - -/** - * Callback function that provides an error message. - * @callback module:camera.onError - * @param {string} message - The message is provided by the device's native code. - */ - -/** - * Callback function that provides the image data. - * @callback module:camera.onSuccess - * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect. - * @example - * // Show image - * // - * function cameraCallback(imageData) { - * var image = document.getElementById('myImage'); - * image.src = "data:image/jpeg;base64," + imageData; - * } - */ - -/** - * Optional parameters to customize the camera settings. - * * [Quirks](#CameraOptions-quirks) - * @typedef module:camera.CameraOptions - * @type {Object} - * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.) - * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value. - * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture. - * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection. - * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the returned image file's encoding. - * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant. - * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant. - * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from. Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`. - * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture. - * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture. - * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad. - * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing). - */ - -/** - * @description Takes a photo using the camera, or retrieves a photo from the device's - * image gallery. The image is passed to the success callback as a - * Base64-encoded `String`, or as the URI for the image file. - * - * The `camera.getPicture` function opens the device's default camera - * application that allows users to snap pictures by default - this behavior occurs, - * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}. - * Once the user snaps the photo, the camera application closes and the application is restored. - * - * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or - * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays - * that allows users to select an existing image. - * - * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in - * one of the following formats, depending on the specified - * `cameraOptions`: - * - * - A `String` containing the Base64-encoded photo image. - * - A `String` representing the image file location on local storage (default). - * - * You can do whatever you want with the encoded image or URI, for - * example: - * - * - Render the image in an `` tag, as in the example below - * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.) - * - Post the data to a remote server - * - * __NOTE__: Photo resolution on newer devices is quite good. Photos - * selected from the device's gallery are not downscaled to a lower - * quality, even if a `quality` parameter is specified. To avoid common - * memory problems, set `Camera.destinationType` to `FILE_URI` rather - * than `DATA_URL`. - * - * __Supported Platforms__ - * - * - Android - * - BlackBerry - * - Browser - * - Firefox - * - FireOS - * - iOS - * - Windows - * - WP8 - * - Ubuntu - * - * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks). - * - * @example - * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions); - * @param {module:camera.onSuccess} successCallback - * @param {module:camera.onError} errorCallback - * @param {module:camera.CameraOptions} options CameraOptions - */ -cameraExport.getPicture = function (successCallback, errorCallback, options) { - argscheck.checkArgs('fFO', 'Camera.getPicture', arguments); - options = options || {}; - var getValue = argscheck.getValue; - - var quality = getValue(options.quality, 50); - var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI); - var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA); - var targetWidth = getValue(options.targetWidth, -1); - var targetHeight = getValue(options.targetHeight, -1); - var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG); - var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE); - var allowEdit = !!options.allowEdit; - var correctOrientation = !!options.correctOrientation; - var saveToPhotoAlbum = !!options.saveToPhotoAlbum; - var popoverOptions = getValue(options.popoverOptions, null); - var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK); - - var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType, - mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection]; - - exec(successCallback, errorCallback, 'Camera', 'takePicture', args); - // XXX: commented out - // return new CameraPopoverHandle(); -}; - -/** - * Removes intermediate image files that are kept in temporary storage - * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of - * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the - * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`. - * - * __Supported Platforms__ - * - * - iOS - * - * @example - * navigator.camera.cleanup(onSuccess, onFail); - * - * function onSuccess() { - * console.log("Camera cleanup success.") - * } - * - * function onFail(message) { - * alert('Failed because: ' + message); - * } - */ -cameraExport.cleanup = function (successCallback, errorCallback) { - exec(successCallback, errorCallback, 'Camera', 'cleanup', []); -}; - -module.exports = cameraExport; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js deleted file mode 100644 index 4f4b046f..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js +++ /dev/null @@ -1,104 +0,0 @@ -cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -/** - * @module Camera - */ -module.exports = { - /** - * @description - * Defines the output format of `Camera.getPicture` call. - * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with - * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will - * disable any image modifications (resize, quality change, cropping, etc.) due - * to implementation specific. - * - * @enum {number} - */ - DestinationType: { - /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */ - DATA_URL: 0, - /** Return file uri (content://media/external/images/media/2 for Android) */ - FILE_URI: 1, - /** Return native uri (eg. asset-library://... for iOS) */ - NATIVE_URI: 2 - }, - /** - * @enum {number} - */ - EncodingType: { - /** Return JPEG encoded image */ - JPEG: 0, - /** Return PNG encoded image */ - PNG: 1 - }, - /** - * @enum {number} - */ - MediaType: { - /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */ - PICTURE: 0, - /** Allow selection of video only, ONLY RETURNS URL */ - VIDEO: 1, - /** Allow selection from all media types */ - ALLMEDIA: 2 - }, - /** - * @description - * Defines the output format of `Camera.getPicture` call. - * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` - * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality - * change, cropping, etc.) due to implementation specific. - * - * @enum {number} - */ - PictureSourceType: { - /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */ - PHOTOLIBRARY: 0, - /** Take picture from camera */ - CAMERA: 1, - /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */ - SAVEDPHOTOALBUM: 2 - }, - /** - * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover. - * @enum {number} - */ - PopoverArrowDirection: { - ARROW_UP: 1, - ARROW_DOWN: 2, - ARROW_LEFT: 4, - ARROW_RIGHT: 8, - ARROW_ANY: 15 - }, - /** - * @enum {number} - */ - Direction: { - /** Use the back-facing camera */ - BACK: 0, - /** Use the front-facing camera */ - FRONT: 1 - } -}; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js deleted file mode 100644 index c970f55a..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js +++ /dev/null @@ -1,35 +0,0 @@ -cordova.define("cordova-plugin-camera.CameraPopoverHandle", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -/** - * @ignore in favour of iOS' one - * A handle to an image picker popover. - */ -var CameraPopoverHandle = function () { - this.setPosition = function (popoverOptions) { - console.log('CameraPopoverHandle.setPosition is only supported on iOS.'); - }; -}; - -module.exports = CameraPopoverHandle; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js deleted file mode 100644 index 81d7d20e..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js +++ /dev/null @@ -1,55 +0,0 @@ -cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var Camera = require('./Camera'); - -/** - * @namespace navigator - */ - -/** - * iOS-only parameters that specify the anchor element location and arrow - * direction of the popover when selecting images from an iPad's library - * or album. - * Note that the size of the popover may change to adjust to the - * direction of the arrow and orientation of the screen. Make sure to - * account for orientation changes when specifying the anchor element - * location. - * @module CameraPopoverOptions - * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover. - * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover. - * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover. - * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover. - * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point. - */ -var CameraPopoverOptions = function (x, y, width, height, arrowDir) { - // information of rectangle that popover should be anchored to - this.x = x || 0; - this.y = y || 32; - this.width = width || 320; - this.height = height || 480; - this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY; -}; - -module.exports = CameraPopoverOptions; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-datepicker/www/android/DatePicker.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-datepicker/www/android/DatePicker.js deleted file mode 100644 index c05ee3da..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-datepicker/www/android/DatePicker.js +++ /dev/null @@ -1,99 +0,0 @@ -cordova.define("cordova-plugin-datepicker.DatePicker", function(require, exports, module) { -/** - * Phonegap DatePicker Plugin Copyright (c) Greg Allen 2011 MIT Licensed - * Reused and ported to Android plugin by Daniel van 't Oever - */ - -/** - * Constructor - */ -function DatePicker() { - //this._callback; -} - -/** - * Android themes - */ -DatePicker.prototype.ANDROID_THEMES = { - THEME_TRADITIONAL : 1, // default - THEME_HOLO_DARK : 2, - THEME_HOLO_LIGHT : 3, - THEME_DEVICE_DEFAULT_DARK : 4, - THEME_DEVICE_DEFAULT_LIGHT : 5 -}; - -/** - * show - true to show the ad, false to hide the ad - */ -DatePicker.prototype.show = function(options, cb, errCb) { - - if (options.date && options.date instanceof Date) { - options.date = (options.date.getMonth() + 1) + "/" + - (options.date.getDate()) + "/" + - (options.date.getFullYear()) + "/" + - (options.date.getHours()) + "/" + - (options.date.getMinutes()); - } - - var defaults = { - mode : 'date', - date : '', - minDate: 0, - maxDate: 0, - titleText: '', - cancelText: '', - okText: '', - todayText: '', - nowText: '', - is24Hour: false, - androidTheme : window.datePicker.ANDROID_THEMES.THEME_TRADITIONAL, // Default theme - }; - - for (var key in defaults) { - if (typeof options[key] !== "undefined") { - defaults[key] = options[key]; - } - } - - //this._callback = cb; - - var callback = function(message) { - if(message != 'error'){ - var timestamp = Date.parse(message); - if(isNaN(timestamp) == false) { - cb(new Date(message)); - } - else { - cb(); - } - } else { - // TODO error popup? - } - } - - var errCallback = function(message) { - if (typeof errCb === 'function') { - errCb(message); - } - } - - cordova.exec(callback, - errCallback, - "DatePickerPlugin", - defaults.mode, - [defaults] - ); -}; - -var datePicker = new DatePicker(); -module.exports = datePicker; - -// Make plugin work under window.plugins -if (!window.plugins) { - window.plugins = {}; -} -if (!window.plugins.datePicker) { - window.plugins.datePicker = datePicker; -} - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js deleted file mode 100644 index ae48e354..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js +++ /dev/null @@ -1,86 +0,0 @@ -cordova.define("cordova-plugin-device.device", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var argscheck = require('cordova/argscheck'); -var channel = require('cordova/channel'); -var utils = require('cordova/utils'); -var exec = require('cordova/exec'); -var cordova = require('cordova'); - -channel.createSticky('onCordovaInfoReady'); -// Tell cordova channel to wait on the CordovaInfoReady event -channel.waitForInitialization('onCordovaInfoReady'); - -/** - * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the - * phone, etc. - * @constructor - */ -function Device () { - this.available = false; - this.platform = null; - this.version = null; - this.uuid = null; - this.cordova = null; - this.model = null; - this.manufacturer = null; - this.isVirtual = null; - this.serial = null; - - var me = this; - - channel.onCordovaReady.subscribe(function () { - me.getInfo(function (info) { - // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js - // TODO: CB-5105 native implementations should not return info.cordova - var buildLabel = cordova.version; - me.available = true; - me.platform = info.platform; - me.version = info.version; - me.uuid = info.uuid; - me.cordova = buildLabel; - me.model = info.model; - me.isVirtual = info.isVirtual; - me.manufacturer = info.manufacturer || 'unknown'; - me.serial = info.serial || 'unknown'; - channel.onCordovaInfoReady.fire(); - }, function (e) { - me.available = false; - utils.alert('[ERROR] Error initializing Cordova: ' + e); - }); - }); -} - -/** - * Get device info - * - * @param {Function} successCallback The function to call when the heading data is available - * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) - */ -Device.prototype.getInfo = function (successCallback, errorCallback) { - argscheck.checkArgs('fF', 'Device.getInfo', arguments); - exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []); -}; - -module.exports = new Device(); - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/android/notification.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/android/notification.js deleted file mode 100644 index 03333918..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/android/notification.js +++ /dev/null @@ -1,77 +0,0 @@ -cordova.define("cordova-plugin-dialogs.notification_android", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var exec = require('cordova/exec'); - -/** - * Provides Android enhanced notification API. - */ -module.exports = { - activityStart: function (title, message) { - // If title and message not specified then mimic Android behavior of - // using default strings. - if (typeof title === 'undefined' && typeof message === 'undefined') { - title = 'Busy'; - message = 'Please wait...'; - } - - exec(null, null, 'Notification', 'activityStart', [ title, message ]); - }, - - /** - * Close an activity dialog - */ - activityStop: function () { - exec(null, null, 'Notification', 'activityStop', []); - }, - - /** - * Display a progress dialog with progress bar that goes from 0 to 100. - * - * @param {String} - * title Title of the progress dialog. - * @param {String} - * message Message to display in the dialog. - */ - progressStart: function (title, message) { - exec(null, null, 'Notification', 'progressStart', [ title, message ]); - }, - - /** - * Close the progress dialog. - */ - progressStop: function () { - exec(null, null, 'Notification', 'progressStop', []); - }, - - /** - * Set the progress dialog value. - * - * @param {Number} - * value 0-100 - */ - progressValue: function (value) { - exec(null, null, 'Notification', 'progressValue', [ value ]); - } -}; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/notification.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/notification.js deleted file mode 100644 index e34e710e..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-dialogs/www/notification.js +++ /dev/null @@ -1,133 +0,0 @@ -cordova.define("cordova-plugin-dialogs.notification", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var exec = require('cordova/exec'); -var platform = require('cordova/platform'); - -/** - * Provides access to notifications on the device. - */ - -module.exports = { - - /** - * Open a native alert dialog, with a customizable title and button text. - * - * @param {String} message Message to print in the body of the alert - * @param {Function} completeCallback The callback that is called when user clicks on a button. - * @param {String} title Title of the alert dialog (default: Alert) - * @param {String} buttonLabel Label of the close button (default: OK) - */ - alert: function (message, completeCallback, title, buttonLabel) { - var _message = (typeof message === 'string' ? message : JSON.stringify(message)); - var _title = (typeof title === 'string' ? title : 'Alert'); - var _buttonLabel = (buttonLabel && typeof buttonLabel === 'string' ? buttonLabel : 'OK'); - exec(completeCallback, null, 'Notification', 'alert', [_message, _title, _buttonLabel]); - }, - - /** - * Open a native confirm dialog, with a customizable title and button text. - * The result that the user selects is returned to the result callback. - * - * @param {String} message Message to print in the body of the alert - * @param {Function} resultCallback The callback that is called when user clicks on a button. - * @param {String} title Title of the alert dialog (default: Confirm) - * @param {Array} buttonLabels Array of the labels of the buttons (default: ['OK', 'Cancel']) - */ - confirm: function (message, resultCallback, title, buttonLabels) { - var _message = (typeof message === 'string' ? message : JSON.stringify(message)); - var _title = (typeof title === 'string' ? title : 'Confirm'); - var _buttonLabels = (buttonLabels || ['OK', 'Cancel']); - - // Strings are deprecated! - if (typeof _buttonLabels === 'string') { - console.log('Notification.confirm(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array).'); - } - - _buttonLabels = convertButtonLabels(_buttonLabels); - - exec(resultCallback, null, 'Notification', 'confirm', [_message, _title, _buttonLabels]); - }, - - /** - * Open a native prompt dialog, with a customizable title and button text. - * The following results are returned to the result callback: - * buttonIndex Index number of the button selected. - * input1 The text entered in the prompt dialog box. - * - * @param {String} message Dialog message to display (default: "Prompt message") - * @param {Function} resultCallback The callback that is called when user clicks on a button. - * @param {String} title Title of the dialog (default: "Prompt") - * @param {Array} buttonLabels Array of strings for the button labels (default: ["OK","Cancel"]) - * @param {String} defaultText Textbox input value (default: empty string) - */ - prompt: function (message, resultCallback, title, buttonLabels, defaultText) { - var _message = (typeof message === 'string' ? message : JSON.stringify(message)); - var _title = (typeof title === 'string' ? title : 'Prompt'); - var _buttonLabels = (buttonLabels || ['OK', 'Cancel']); - - // Strings are deprecated! - if (typeof _buttonLabels === 'string') { - console.log('Notification.prompt(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array).'); - } - - _buttonLabels = convertButtonLabels(_buttonLabels); - - var _defaultText = (defaultText || ''); - exec(resultCallback, null, 'Notification', 'prompt', [_message, _title, _buttonLabels, _defaultText]); - }, - - /** - * Causes the device to beep. - * On Android, the default notification ringtone is played "count" times. - * - * @param {Integer} count The number of beeps. - */ - beep: function (count) { - var defaultedCount = count || 1; - exec(null, null, 'Notification', 'beep', [ defaultedCount ]); - } -}; - -function convertButtonLabels (buttonLabels) { - - // Some platforms take an array of button label names. - // Other platforms take a comma separated list. - // For compatibility, we convert to the desired type based on the platform. - if (platform.id === 'amazon-fireos' || platform.id === 'android' || platform.id === 'ios' || - platform.id === 'windowsphone' || platform.id === 'firefoxos' || platform.id === 'ubuntu' || - platform.id === 'windows8' || platform.id === 'windows') { - - if (typeof buttonLabels === 'string') { - buttonLabels = buttonLabels.split(','); // not crazy about changing the var type here - } - } else { - if (Array.isArray(buttonLabels)) { - var buttonLabelArray = buttonLabels; - buttonLabels = buttonLabelArray.toString(); - } - } - - return buttonLabels; -} - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js deleted file mode 100644 index 39821393..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js +++ /dev/null @@ -1,29 +0,0 @@ -cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) { -/*global cordova */ - -function Fingerprint() { -} - -Fingerprint.prototype.show = function (params, successCallback, errorCallback) { - cordova.exec( - successCallback, - errorCallback, - "Fingerprint", - "authenticate", - [params] - ); -}; - -Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) { - cordova.exec( - successCallback, - errorCallback, - "Fingerprint", - "isAvailable", - [{}] - ); -}; - -module.exports = new Fingerprint(); - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/PositionError.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/PositionError.js deleted file mode 100644 index c26dd754..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/PositionError.js +++ /dev/null @@ -1,41 +0,0 @@ -cordova.define("cordova-plugin-geolocation.PositionError", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -/** - * Position error object - * - * @constructor - * @param code - * @param message - */ -var PositionError = function(code, message) { - this.code = code || null; - this.message = message || ''; -}; - -PositionError.prototype.PERMISSION_DENIED = PositionError.PERMISSION_DENIED = 1; -PositionError.prototype.POSITION_UNAVAILABLE = PositionError.POSITION_UNAVAILABLE = 2; -PositionError.prototype.TIMEOUT = PositionError.TIMEOUT = 3; - -module.exports = PositionError; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/android/geolocation.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/android/geolocation.js deleted file mode 100644 index 814aafbc..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-geolocation/www/android/geolocation.js +++ /dev/null @@ -1,74 +0,0 @@ -cordova.define("cordova-plugin-geolocation.geolocation", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var exec = cordova.require('cordova/exec'); -var utils = require('cordova/utils'); -var PositionError = require('./PositionError'); - -// Native watchPosition method is called async after permissions prompt. -// So we use additional map and own ids to return watch id synchronously. -var pluginToNativeWatchMap = {}; - -module.exports = { - getCurrentPosition: function(success, error, args) { - var win = function() { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - geo.getCurrentPosition(success, error, args); - }; - var fail = function() { - if (error) { - error(new PositionError (PositionError.PERMISSION_DENIED, 'Illegal Access')); - } - }; - exec(win, fail, "Geolocation", "getPermission", []); - }, - - watchPosition: function(success, error, args) { - var pluginWatchId = utils.createUUID(); - - var win = function() { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - pluginToNativeWatchMap[pluginWatchId] = geo.watchPosition(success, error, args); - }; - - var fail = function() { - if (error) { - error(new PositionError(PositionError.PERMISSION_DENIED, 'Illegal Access')); - } - }; - exec(win, fail, "Geolocation", "getPermission", []); - - return pluginWatchId; - }, - - clearWatch: function(pluginWatchId) { - var win = function() { - var nativeWatchId = pluginToNativeWatchMap[pluginWatchId]; - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - geo.clearWatch(nativeWatchId); - }; - - exec(win, null, "Geolocation", "getPermission", []); - } -}; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js deleted file mode 100644 index 34f71c57..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js +++ /dev/null @@ -1,84 +0,0 @@ -cordova.define("cordova-plugin-ionic-keyboard.keyboard", function(require, exports, module) { -var argscheck = require('cordova/argscheck'), - utils = require('cordova/utils'), - exec = require('cordova/exec'), - channel = require('cordova/channel'); - - -var Keyboard = function () {}; - -Keyboard.fireOnShow = function (height) { - Keyboard.isVisible = true; - cordova.fireWindowEvent('keyboardDidShow', { - 'keyboardHeight': height - }); - - // To support the keyboardAttach directive listening events - // inside Ionic's main bundle - cordova.fireWindowEvent('native.keyboardshow', { - 'keyboardHeight': height - }); -}; - -Keyboard.fireOnHide = function () { - Keyboard.isVisible = false; - cordova.fireWindowEvent('keyboardDidHide'); - - // To support the keyboardAttach directive listening events - // inside Ionic's main bundle - cordova.fireWindowEvent('native.keyboardhide'); -}; - -Keyboard.fireOnHiding = function () { - cordova.fireWindowEvent('keyboardWillHide'); -}; - -Keyboard.fireOnShowing = function (height) { - cordova.fireWindowEvent('keyboardWillShow', { - 'keyboardHeight': height - }); -}; - -Keyboard.hideFormAccessoryBar = Keyboard.hideKeyboardAccessoryBar = function (hide) { - exec(null, null, "Keyboard", "hideKeyboardAccessoryBar", [hide]); -}; - -Keyboard.hide = function () { - exec(null, null, "Keyboard", "hide", []); -}; - -Keyboard.show = function () { - exec(null, null, "Keyboard", "show", []); -}; - -Keyboard.disableScroll = function (disable) { - console.warn("Keyboard.disableScroll() was removed"); -}; - -Keyboard.setResizeMode = function (mode) { - console.warn("Keyboard.setResizeMode() not supported in Android"); -} - -channel.onCordovaReady.subscribe(function () { - exec(success, null, 'Keyboard', 'init', []); - - function success(msg) { - var action = msg.charAt(0); - if (action === 'S') { - var keyboardHeight = parseInt(msg.substr(1)); - Keyboard.fireOnShowing(keyboardHeight); - Keyboard.fireOnShow(keyboardHeight); - - } else if (action === 'H') { - Keyboard.fireOnHiding(); - Keyboard.fireOnHide(); - } - } -}); - - -Keyboard.isVisible = false; - -module.exports = Keyboard; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js deleted file mode 100644 index 5a830544..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js +++ /dev/null @@ -1,30 +0,0 @@ -cordova.define("cordova-plugin-ionic-webview.IonicWebView", function(require, exports, module) { -var exec = require('cordova/exec'); - -var WebView = { - convertFileSrc: function(url) { - if (!url) { - return url; - } - if (!url.startsWith('file://')) { - return url; - } - url = url.substr(7); // len("file://") == 7 - if (url.length === 0 || url[0] !== '/') { // ensure the new URL starts with / - url = '/' + url; - } - return window.WEBVIEW_SERVER_URL + '/_file_' + url; - }, - setServerBasePath: function(path) { - exec(null, null, 'IonicWebView', 'setServerBasePath', [path]); - }, - getServerBasePath: function(callback) { - exec(callback, null, 'IonicWebView', 'getServerBasePath', []); - }, - persistServerBasePath: function() { - exec(null, null, 'IonicWebView', 'persistServerBasePath', []); - } -} - -module.exports = WebView; -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-request-location-accuracy/www/android/RequestLocationAccuracy.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-request-location-accuracy/www/android/RequestLocationAccuracy.js deleted file mode 100644 index fe484a0a..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-request-location-accuracy/www/android/RequestLocationAccuracy.js +++ /dev/null @@ -1,154 +0,0 @@ -cordova.define("cordova-plugin-request-location-accuracy.RequestLocationAccuracy", function(require, exports, module) { -/** - * Request Location Accuracy plugin - * - * Copyright (c) 2016 Dave Alden (Working Edge Ltd.) - **/ -var RequestLocationAccuracy = function(){ - this.requesting = false; -}; - -/** - * Request location mode priority "no power": the best accuracy possible with zero additional power consumption. - * https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_NO_POWER - * @type {number} - */ -RequestLocationAccuracy.prototype.REQUEST_PRIORITY_NO_POWER = 0; - -/** - * Request location mode priority "low power": "city" level accuracy (about 10km accuracy) - * https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_LOW_POWER - * @type {number} - */ -RequestLocationAccuracy.prototype.REQUEST_PRIORITY_LOW_POWER = 1; - -/** - * Request location mode priority "balanced power": "block" level accuracy (about 100 meter accuracy) - * https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_BALANCED_POWER_ACCURACY - * @type {number} - */ -RequestLocationAccuracy.prototype.REQUEST_PRIORITY_BALANCED_POWER_ACCURACY = 2; - -/** - * Request location mode priority "high accuracy": the most accurate locations available. This will use GPS hardware to retrieve positions. - * https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html#PRIORITY_HIGH_ACCURACY - * @type {number} - */ -RequestLocationAccuracy.prototype.REQUEST_PRIORITY_HIGH_ACCURACY = 3; - - -/** - * Success due to current location settings already satisfying requested accuracy - * @type {number} - */ -RequestLocationAccuracy.prototype.SUCCESS_SETTINGS_SATISFIED = 0; - -/** - * Success due to user agreeing to requested accuracy change - * @type {number} - */ -RequestLocationAccuracy.prototype.SUCCESS_USER_AGREED = 1; - -/** - * Error due an unresolved request already being in progress. - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_ALREADY_REQUESTING = -1; - -/** - * Error due invalid action requested - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_INVALID_ACTION = 0; - -/** - * Error due invalid accuracy requested - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_INVALID_ACCURACY = 1; - -/** - * Error due to exception in the native code - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_EXCEPTION = 2; - -/** - * Error due to not being able to change location accuracy to requested state - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_CANNOT_CHANGE_ACCURACY = 3; - -/** - * Error due to user rejecting requested accuracy change - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_USER_DISAGREED = 4; - -/** - * Error due to failure to connect to Google Play Services API - * @type {number} - */ -RequestLocationAccuracy.prototype.ERROR_GOOGLE_API_CONNECTION_FAILED = 5; - -/** - * Requests a specific accuracy for Location Services. - * - * @param [Function} successCallback - callback to be invoked on successful resolution of the requested accuracy. - * A single object argument will be passed which has two keys: "code" in an integer corresponding to a SUCCESS constant and indicates the reason for success; - * "message" is a string containing a description of the success. - * @param {Function} errorCallback - callback to be invoked on failure to resolve the requested accuracy. - * A single object argument will be passed which has two keys: "code" in an integer corresponding to an ERROR constant and indicates the reason for failure; - * "message" is a string containing a description of the error. - * @param {Integer} accuracy - The location accuracy to request defined by an integer corresponding to a REQUEST constant. - */ -RequestLocationAccuracy.prototype.request = function(successCallback, errorCallback, accuracy) { - var _this = this; - - if(this.requesting){ - return errorCallback({ - code: _this.ERROR_ALREADY_REQUESTING, - message: "A request is already in progress" - }); - } - - this.requesting = true; - - return cordova.exec(function(data){ - _this.requesting = false; - successCallback(data) - }, - function(err) { - _this.requesting = false; - errorCallback(err); - }, - 'RequestLocationAccuracy', - 'request', - [accuracy]); -}; - -/** - * Indicates if a request is currently in progress. - * - * @param [Function} successCallback - callback to pass result to. - * This is passed a boolean argument indicating if a request is currently in progress; - */ -RequestLocationAccuracy.prototype.isRequesting = function(successCallback) { - successCallback(!!this.requesting); -}; - -/** - * Indicates if it is possible to request a specific location accuracy. - * This will return true if the app is authorized to use location. - * - * @param [Function} successCallback - callback to pass result to. - * This is passed a boolean argument indicating if a request can be made. - */ -RequestLocationAccuracy.prototype.canRequest = function(successCallback) { - return cordova.exec(successCallback, null, 'RequestLocationAccuracy', 'canRequest', []); -}; - -module.exports = new RequestLocationAccuracy(); - - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js deleted file mode 100644 index 5beaa5fd..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js +++ /dev/null @@ -1,36 +0,0 @@ -cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -var exec = require('cordova/exec'); - -var splashscreen = { - show:function() { - exec(null, null, "SplashScreen", "show", []); - }, - hide:function() { - exec(null, null, "SplashScreen", "hide", []); - } -}; - -module.exports = splashscreen; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js deleted file mode 100644 index 708186f9..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js +++ /dev/null @@ -1,116 +0,0 @@ -cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) { -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ - -/* global cordova */ - -var exec = require('cordova/exec'); - -var namedColors = { - "black": "#000000", - "darkGray": "#A9A9A9", - "lightGray": "#D3D3D3", - "white": "#FFFFFF", - "gray": "#808080", - "red": "#FF0000", - "green": "#00FF00", - "blue": "#0000FF", - "cyan": "#00FFFF", - "yellow": "#FFFF00", - "magenta": "#FF00FF", - "orange": "#FFA500", - "purple": "#800080", - "brown": "#A52A2A" -}; - -var StatusBar = { - - isVisible: true, - - overlaysWebView: function (doOverlay) { - exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]); - }, - - styleDefault: function () { - // dark text ( to be used on a light background ) - exec(null, null, "StatusBar", "styleDefault", []); - }, - - styleLightContent: function () { - // light text ( to be used on a dark background ) - exec(null, null, "StatusBar", "styleLightContent", []); - }, - - styleBlackTranslucent: function () { - // #88000000 ? Apple says to use lightContent instead - exec(null, null, "StatusBar", "styleBlackTranslucent", []); - }, - - styleBlackOpaque: function () { - // #FF000000 ? Apple says to use lightContent instead - exec(null, null, "StatusBar", "styleBlackOpaque", []); - }, - - backgroundColorByName: function (colorname) { - return StatusBar.backgroundColorByHexString(namedColors[colorname]); - }, - - backgroundColorByHexString: function (hexString) { - if (hexString.charAt(0) !== "#") { - hexString = "#" + hexString; - } - - if (hexString.length === 4) { - var split = hexString.split(""); - hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3]; - } - - exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]); - }, - - hide: function () { - exec(null, null, "StatusBar", "hide", []); - StatusBar.isVisible = false; - }, - - show: function () { - exec(null, null, "StatusBar", "show", []); - StatusBar.isVisible = true; - } - -}; - -// prime it. setTimeout so that proxy gets time to init -window.setTimeout(function () { - exec(function (res) { - if (typeof res == 'object') { - if (res.type == 'tap') { - cordova.fireWindowEvent('statusTap'); - } - } else { - StatusBar.isVisible = res; - } - }, null, "StatusBar", "_ready", []); -}, 0); - -module.exports = StatusBar; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-sqlite-storage/www/SQLitePlugin.js b/platforms/android/app/src/main/assets/www/plugins/cordova-sqlite-storage/www/SQLitePlugin.js deleted file mode 100644 index 115d92d0..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/cordova-sqlite-storage/www/SQLitePlugin.js +++ /dev/null @@ -1,919 +0,0 @@ -cordova.define("cordova-sqlite-storage.SQLitePlugin", function(require, exports, module) { -(function() { - var DB_STATE_INIT, DB_STATE_OPEN, READ_ONLY_REGEX, SQLiteFactory, SQLitePlugin, SQLitePluginTransaction, SelfTest, argsArray, dblocations, iosLocationMap, newSQLError, nextTick, root, txLocks; - - root = this; - - READ_ONLY_REGEX = /^(\s|;)*(?:alter|create|delete|drop|insert|reindex|replace|update)/i; - - DB_STATE_INIT = "INIT"; - - DB_STATE_OPEN = "OPEN"; - - txLocks = {}; - - newSQLError = function(error, code) { - var sqlError; - sqlError = error; - if (!code) { - code = 0; - } - if (!sqlError) { - sqlError = new Error("a plugin had an error but provided no response"); - sqlError.code = code; - } - if (typeof sqlError === "string") { - sqlError = new Error(error); - sqlError.code = code; - } - if (!sqlError.code && sqlError.message) { - sqlError.code = code; - } - if (!sqlError.code && !sqlError.message) { - sqlError = new Error("an unknown error was returned: " + JSON.stringify(sqlError)); - sqlError.code = code; - } - return sqlError; - }; - - nextTick = window.setImmediate || function(fun) { - window.setTimeout(fun, 0); - }; - - - /* - Utility that avoids leaking the arguments object. See - https://www.npmjs.org/package/argsarray - */ - - argsArray = function(fun) { - return function() { - var args, i, len; - len = arguments.length; - if (len) { - args = []; - i = -1; - while (++i < len) { - args[i] = arguments[i]; - } - return fun.call(this, args); - } else { - return fun.call(this, []); - } - }; - }; - - SQLitePlugin = function(openargs, openSuccess, openError) { - var dbname; - if (!(openargs && openargs['name'])) { - throw newSQLError("Cannot create a SQLitePlugin db instance without a db name"); - } - dbname = openargs.name; - if (typeof dbname !== 'string') { - throw newSQLError('sqlite plugin database name must be a string'); - } - this.openargs = openargs; - this.dbname = dbname; - this.openSuccess = openSuccess; - this.openError = openError; - this.openSuccess || (this.openSuccess = function() { - console.log("DB opened: " + dbname); - }); - this.openError || (this.openError = function(e) { - console.log(e.message); - }); - this.open(this.openSuccess, this.openError); - }; - - SQLitePlugin.prototype.databaseFeatures = { - isSQLitePluginDatabase: true - }; - - SQLitePlugin.prototype.openDBs = {}; - - SQLitePlugin.prototype.addTransaction = function(t) { - if (!txLocks[this.dbname]) { - txLocks[this.dbname] = { - queue: [], - inProgress: false - }; - } - txLocks[this.dbname].queue.push(t); - if (this.dbname in this.openDBs && this.openDBs[this.dbname] !== DB_STATE_INIT) { - this.startNextTransaction(); - } else { - if (this.dbname in this.openDBs) { - console.log('new transaction is queued, waiting for open operation to finish'); - } else { - console.log('database is closed, new transaction is [stuck] waiting until db is opened again!'); - } - } - }; - - SQLitePlugin.prototype.transaction = function(fn, error, success) { - if (!this.openDBs[this.dbname]) { - error(newSQLError('database not open')); - return; - } - this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, true, false)); - }; - - SQLitePlugin.prototype.readTransaction = function(fn, error, success) { - if (!this.openDBs[this.dbname]) { - error(newSQLError('database not open')); - return; - } - this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, false, true)); - }; - - SQLitePlugin.prototype.startNextTransaction = function() { - var self; - self = this; - nextTick((function(_this) { - return function() { - var txLock; - if (!(_this.dbname in _this.openDBs) || _this.openDBs[_this.dbname] !== DB_STATE_OPEN) { - console.log('cannot start next transaction: database not open'); - return; - } - txLock = txLocks[self.dbname]; - if (!txLock) { - console.log('cannot start next transaction: database connection is lost'); - return; - } else if (txLock.queue.length > 0 && !txLock.inProgress) { - txLock.inProgress = true; - txLock.queue.shift().start(); - } - }; - })(this)); - }; - - SQLitePlugin.prototype.abortAllPendingTransactions = function() { - var j, len1, ref, tx, txLock; - txLock = txLocks[this.dbname]; - if (!!txLock && txLock.queue.length > 0) { - ref = txLock.queue; - for (j = 0, len1 = ref.length; j < len1; j++) { - tx = ref[j]; - tx.abortFromQ(newSQLError('Invalid database handle')); - } - txLock.queue = []; - txLock.inProgress = false; - } - }; - - SQLitePlugin.prototype.open = function(success, error) { - var openerrorcb, opensuccesscb, step2; - if (this.dbname in this.openDBs) { - console.log('database already open: ' + this.dbname); - nextTick((function(_this) { - return function() { - success(_this); - }; - })(this)); - } else { - console.log('OPEN database: ' + this.dbname); - opensuccesscb = (function(_this) { - return function() { - var txLock; - console.log('OPEN database: ' + _this.dbname + ' - OK'); - if (!_this.openDBs[_this.dbname]) { - console.log('database was closed during open operation'); - } - if (_this.dbname in _this.openDBs) { - _this.openDBs[_this.dbname] = DB_STATE_OPEN; - } - if (!!success) { - success(_this); - } - txLock = txLocks[_this.dbname]; - if (!!txLock && txLock.queue.length > 0 && !txLock.inProgress) { - _this.startNextTransaction(); - } - }; - })(this); - openerrorcb = (function(_this) { - return function() { - console.log('OPEN database: ' + _this.dbname + ' FAILED, aborting any pending transactions'); - if (!!error) { - error(newSQLError('Could not open database')); - } - delete _this.openDBs[_this.dbname]; - _this.abortAllPendingTransactions(); - }; - })(this); - this.openDBs[this.dbname] = DB_STATE_INIT; - step2 = (function(_this) { - return function() { - cordova.exec(opensuccesscb, openerrorcb, "SQLitePlugin", "open", [_this.openargs]); - }; - })(this); - cordova.exec(step2, step2, 'SQLitePlugin', 'close', [ - { - path: this.dbname - } - ]); - } - }; - - SQLitePlugin.prototype.close = function(success, error) { - if (this.dbname in this.openDBs) { - if (txLocks[this.dbname] && txLocks[this.dbname].inProgress) { - console.log('cannot close: transaction is in progress'); - error(newSQLError('database cannot be closed while a transaction is in progress')); - return; - } - console.log('CLOSE database: ' + this.dbname); - delete this.openDBs[this.dbname]; - if (txLocks[this.dbname]) { - console.log('closing db with transaction queue length: ' + txLocks[this.dbname].queue.length); - } else { - console.log('closing db with no transaction lock state'); - } - cordova.exec(success, error, "SQLitePlugin", "close", [ - { - path: this.dbname - } - ]); - } else { - console.log('cannot close: database is not open'); - if (error) { - nextTick(function() { - return error(); - }); - } - } - }; - - SQLitePlugin.prototype.executeSql = function(statement, params, success, error) { - var myerror, myfn, mysuccess; - mysuccess = function(t, r) { - if (!!success) { - return success(r); - } - }; - myerror = function(t, e) { - if (!!error) { - return error(e); - } - }; - myfn = function(tx) { - tx.addStatement(statement, params, mysuccess, myerror); - }; - this.addTransaction(new SQLitePluginTransaction(this, myfn, null, null, false, false)); - }; - - SQLitePlugin.prototype.sqlBatch = function(sqlStatements, success, error) { - var batchList, j, len1, myfn, st; - if (!sqlStatements || sqlStatements.constructor !== Array) { - throw newSQLError('sqlBatch expects an array'); - } - batchList = []; - for (j = 0, len1 = sqlStatements.length; j < len1; j++) { - st = sqlStatements[j]; - if (st.constructor === Array) { - if (st.length === 0) { - throw newSQLError('sqlBatch array element of zero (0) length'); - } - batchList.push({ - sql: st[0], - params: st.length === 0 ? [] : st[1] - }); - } else { - batchList.push({ - sql: st, - params: [] - }); - } - } - myfn = function(tx) { - var elem, k, len2, results; - results = []; - for (k = 0, len2 = batchList.length; k < len2; k++) { - elem = batchList[k]; - results.push(tx.addStatement(elem.sql, elem.params, null, null)); - } - return results; - }; - this.addTransaction(new SQLitePluginTransaction(this, myfn, error, success, true, false)); - }; - - SQLitePluginTransaction = function(db, fn, error, success, txlock, readOnly) { - if (typeof fn !== "function") { - - /* - This is consistent with the implementation in Chrome -- it - throws if you pass anything other than a function. This also - prevents us from stalling our txQueue if somebody passes a - false value for fn. - */ - throw newSQLError("transaction expected a function"); - } - this.db = db; - this.fn = fn; - this.error = error; - this.success = success; - this.txlock = txlock; - this.readOnly = readOnly; - this.executes = []; - if (txlock) { - this.addStatement("BEGIN", [], null, function(tx, err) { - throw newSQLError("unable to begin transaction: " + err.message, err.code); - }); - } else { - this.addStatement("SELECT 1", [], null, null); - } - }; - - SQLitePluginTransaction.prototype.start = function() { - var err; - try { - this.fn(this); - this.run(); - } catch (error1) { - err = error1; - txLocks[this.db.dbname].inProgress = false; - this.db.startNextTransaction(); - if (this.error) { - this.error(newSQLError(err)); - } - } - }; - - SQLitePluginTransaction.prototype.executeSql = function(sql, values, success, error) { - if (this.finalized) { - throw { - message: 'InvalidStateError: DOM Exception 11: This transaction is already finalized. Transactions are committed after its success or failure handlers are called. If you are using a Promise to handle callbacks, be aware that implementations following the A+ standard adhere to run-to-completion semantics and so Promise resolution occurs on a subsequent tick and therefore after the transaction commits.', - code: 11 - }; - return; - } - if (this.readOnly && READ_ONLY_REGEX.test(sql)) { - this.handleStatementFailure(error, { - message: 'invalid sql for a read-only transaction' - }); - return; - } - this.addStatement(sql, values, success, error); - }; - - SQLitePluginTransaction.prototype.addStatement = function(sql, values, success, error) { - var j, len1, params, sqlStatement, t, v; - sqlStatement = typeof sql === 'string' ? sql : sql.toString(); - params = []; - if (!!values && values.constructor === Array) { - for (j = 0, len1 = values.length; j < len1; j++) { - v = values[j]; - t = typeof v; - params.push((v === null || v === void 0 ? null : t === 'number' || t === 'string' ? v : v.toString())); - } - } - this.executes.push({ - success: success, - error: error, - sql: sqlStatement, - params: params - }); - }; - - SQLitePluginTransaction.prototype.handleStatementSuccess = function(handler, response) { - var payload, rows; - if (!handler) { - return; - } - rows = response.rows || []; - payload = { - rows: { - item: function(i) { - return rows[i]; - }, - length: rows.length - }, - rowsAffected: response.rowsAffected || 0, - insertId: response.insertId || void 0 - }; - handler(this, payload); - }; - - SQLitePluginTransaction.prototype.handleStatementFailure = function(handler, response) { - if (!handler) { - throw newSQLError("a statement with no error handler failed: " + response.message, response.code); - } - if (handler(this, response) !== false) { - throw newSQLError("a statement error callback did not return false: " + response.message, response.code); - } - }; - - SQLitePluginTransaction.prototype.run = function() { - var batchExecutes, handlerFor, i, mycb, mycbmap, request, tropts, tx, txFailure, waiting; - txFailure = null; - tropts = []; - batchExecutes = this.executes; - waiting = batchExecutes.length; - this.executes = []; - tx = this; - handlerFor = function(index, didSucceed) { - return function(response) { - var err; - if (!txFailure) { - try { - if (didSucceed) { - tx.handleStatementSuccess(batchExecutes[index].success, response); - } else { - tx.handleStatementFailure(batchExecutes[index].error, newSQLError(response)); - } - } catch (error1) { - err = error1; - txFailure = newSQLError(err); - } - } - if (--waiting === 0) { - if (txFailure) { - tx.executes = []; - tx.abort(txFailure); - } else if (tx.executes.length > 0) { - tx.run(); - } else { - tx.finish(); - } - } - }; - }; - mycbmap = {}; - i = 0; - while (i < batchExecutes.length) { - request = batchExecutes[i]; - mycbmap[i] = { - success: handlerFor(i, true), - error: handlerFor(i, false) - }; - tropts.push({ - sql: request.sql, - params: request.params - }); - i++; - } - mycb = function(result) { - var j, q, r, ref, res, resultIndex, type; - for (resultIndex = j = 0, ref = result.length - 1; 0 <= ref ? j <= ref : j >= ref; resultIndex = 0 <= ref ? ++j : --j) { - r = result[resultIndex]; - type = r.type; - res = r.result; - q = mycbmap[resultIndex]; - if (q) { - if (q[type]) { - q[type](res); - } - } - } - }; - cordova.exec(mycb, null, "SQLitePlugin", "backgroundExecuteSqlBatch", [ - { - dbargs: { - dbname: this.db.dbname - }, - executes: tropts - } - ]); - }; - - SQLitePluginTransaction.prototype.abort = function(txFailure) { - var failed, succeeded, tx; - if (this.finalized) { - return; - } - tx = this; - succeeded = function(tx) { - txLocks[tx.db.dbname].inProgress = false; - tx.db.startNextTransaction(); - if (tx.error && typeof tx.error === 'function') { - tx.error(txFailure); - } - }; - failed = function(tx, err) { - txLocks[tx.db.dbname].inProgress = false; - tx.db.startNextTransaction(); - if (tx.error && typeof tx.error === 'function') { - tx.error(newSQLError('error while trying to roll back: ' + err.message, err.code)); - } - }; - this.finalized = true; - if (this.txlock) { - this.addStatement("ROLLBACK", [], succeeded, failed); - this.run(); - } else { - succeeded(tx); - } - }; - - SQLitePluginTransaction.prototype.finish = function() { - var failed, succeeded, tx; - if (this.finalized) { - return; - } - tx = this; - succeeded = function(tx) { - txLocks[tx.db.dbname].inProgress = false; - tx.db.startNextTransaction(); - if (tx.success && typeof tx.success === 'function') { - tx.success(); - } - }; - failed = function(tx, err) { - txLocks[tx.db.dbname].inProgress = false; - tx.db.startNextTransaction(); - if (tx.error && typeof tx.error === 'function') { - tx.error(newSQLError('error while trying to commit: ' + err.message, err.code)); - } - }; - this.finalized = true; - if (this.txlock) { - this.addStatement("COMMIT", [], succeeded, failed); - this.run(); - } else { - succeeded(tx); - } - }; - - SQLitePluginTransaction.prototype.abortFromQ = function(sqlerror) { - if (this.error) { - this.error(sqlerror); - } - }; - - dblocations = ["docs", "libs", "nosync"]; - - iosLocationMap = { - 'default': 'nosync', - 'Documents': 'docs', - 'Library': 'libs' - }; - - SQLiteFactory = { - - /* - NOTE: this function should NOT be translated from Javascript - back to CoffeeScript by js2coffee. - If this function is edited in Javascript then someone will - have to translate it back to CoffeeScript by hand. - */ - openDatabase: argsArray(function(args) { - var dblocation, errorcb, okcb, openargs; - if (args.length < 1 || !args[0]) { - throw newSQLError('Sorry missing mandatory open arguments object in openDatabase call'); - } - if (args[0].constructor === String) { - throw newSQLError('Sorry first openDatabase argument must be an object'); - } - openargs = args[0]; - if (!openargs.name) { - throw newSQLError('Database name value is missing in openDatabase call'); - } - if (!openargs.iosDatabaseLocation && !openargs.location && openargs.location !== 0) { - throw newSQLError('Database location or iosDatabaseLocation setting is now mandatory in openDatabase call.'); - } - if (!!openargs.location && !!openargs.iosDatabaseLocation) { - throw newSQLError('AMBIGUOUS: both location and iosDatabaseLocation settings are present in openDatabase call. Please use either setting, not both.'); - } - dblocation = !!openargs.location && openargs.location === 'default' ? iosLocationMap['default'] : !!openargs.iosDatabaseLocation ? iosLocationMap[openargs.iosDatabaseLocation] : dblocations[openargs.location]; - if (!dblocation) { - throw newSQLError('Valid iOS database location could not be determined in openDatabase call'); - } - openargs.dblocation = dblocation; - if (!!openargs.createFromLocation && openargs.createFromLocation === 1) { - openargs.createFromResource = "1"; - } - if (!!openargs.androidDatabaseProvider && !!openargs.androidDatabaseImplementation) { - throw newSQLError('AMBIGUOUS: both androidDatabaseProvider and deprecated androidDatabaseImplementation settings are present in openDatabase call. Please drop androidDatabaseImplementation in favor of androidDatabaseProvider.'); - } - if (openargs.androidDatabaseProvider !== void 0 && openargs.androidDatabaseProvider !== 'default' && openargs.androidDatabaseProvider !== 'system') { - throw newSQLError("Incorrect androidDatabaseProvider value. Valid values are: 'default', 'system'"); - } - if (!!openargs.androidDatabaseProvider && openargs.androidDatabaseProvider === 'system') { - openargs.androidOldDatabaseImplementation = 1; - } - if (!!openargs.androidDatabaseImplementation && openargs.androidDatabaseImplementation === 2) { - openargs.androidOldDatabaseImplementation = 1; - } - if (!!openargs.androidLockWorkaround && openargs.androidLockWorkaround === 1) { - openargs.androidBugWorkaround = 1; - } - okcb = null; - errorcb = null; - if (args.length >= 2) { - okcb = args[1]; - if (args.length > 2) { - errorcb = args[2]; - } - } - return new SQLitePlugin(openargs, okcb, errorcb); - }), - deleteDatabase: function(first, success, error) { - var args, dblocation, dbname; - args = {}; - if (first.constructor === String) { - throw newSQLError('Sorry first deleteDatabase argument must be an object'); - } else { - if (!(first && first['name'])) { - throw new Error("Please specify db name"); - } - dbname = first.name; - if (typeof dbname !== 'string') { - throw newSQLError('delete database name must be a string'); - } - args.path = dbname; - } - if (!first.iosDatabaseLocation && !first.location && first.location !== 0) { - throw newSQLError('Database location or iosDatabaseLocation setting is now mandatory in deleteDatabase call.'); - } - if (!!first.location && !!first.iosDatabaseLocation) { - throw newSQLError('AMBIGUOUS: both location and iosDatabaseLocation settings are present in deleteDatabase call. Please use either setting value, not both.'); - } - dblocation = !!first.location && first.location === 'default' ? iosLocationMap['default'] : !!first.iosDatabaseLocation ? iosLocationMap[first.iosDatabaseLocation] : dblocations[first.location]; - if (!dblocation) { - throw newSQLError('Valid iOS database location could not be determined in deleteDatabase call'); - } - args.dblocation = dblocation; - delete SQLitePlugin.prototype.openDBs[args.path]; - return cordova.exec(success, error, "SQLitePlugin", "delete", [args]); - } - }; - - SelfTest = { - DBNAME: '___$$$___litehelpers___$$$___test___$$$___.db', - start: function(successcb, errorcb) { - SQLiteFactory.deleteDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, (function() { - return SelfTest.step1(successcb, errorcb); - }), (function() { - return SelfTest.step1(successcb, errorcb); - })); - }, - step1: function(successcb, errorcb) { - SQLiteFactory.openDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, function(db) { - var check1; - check1 = false; - db.transaction(function(tx) { - tx.executeSql('SELECT UPPER("Test") AS upperText', [], function(ignored, resutSet) { - if (!resutSet.rows) { - return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows'); - } - if (!resutSet.rows.length) { - return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length'); - } - if (resutSet.rows.length !== 1) { - return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.length value: " + resutSet.rows.length + " (expected: 1)"); - } - if (!resutSet.rows.item(0).upperText) { - return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.item(0).upperText'); - } - if (resutSet.rows.item(0).upperText !== 'TEST') { - return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.item(0).upperText value: " + (resutSet.rows.item(0).upperText) + " (expected: 'TEST')"); - } - check1 = true; - }, function(ignored, tx_sql_err) { - return SelfTest.finishWithError(errorcb, "TX SQL error: " + tx_sql_err); - }); - }, function(tx_err) { - return SelfTest.finishWithError(errorcb, "TRANSACTION error: " + tx_err); - }, function() { - if (!check1) { - return SelfTest.finishWithError(errorcb, 'Did not get expected upperText result data'); - } - db.executeSql('BEGIN', null, function(ignored) { - return nextTick(function() { - delete db.openDBs[SelfTest.DBNAME]; - delete txLocks[SelfTest.DBNAME]; - nextTick(function() { - db.transaction(function(tx2) { - tx2.executeSql('SELECT 1'); - }, function(tx_err) { - if (!tx_err) { - return SelfTest.finishWithError(errorcb, 'Missing error object'); - } - SelfTest.step2(successcb, errorcb); - }, function() { - return SelfTest.finishWithError(errorcb, 'Missing error object'); - }); - }); - }); - }); - }); - }, function(open_err) { - return SelfTest.finishWithError(errorcb, "Open database error: " + open_err); - }); - }, - step2: function(successcb, errorcb) { - SQLiteFactory.openDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, function(db) { - db.transaction(function(tx) { - tx.executeSql('SELECT ? AS myResult', [null], function(ignored, resutSet) { - if (!resutSet.rows) { - return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows'); - } - if (!resutSet.rows.length) { - return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length'); - } - if (resutSet.rows.length !== 1) { - return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.length value: " + resutSet.rows.length + " (expected: 1)"); - } - SelfTest.step3(successcb, errorcb); - }); - }, function(txError) { - return SelfTest.finishWithError(errorcb, "UNEXPECTED TRANSACTION ERROR: " + txError); - }); - }, function(open_err) { - return SelfTest.finishWithError(errorcb, "Open database error: " + open_err); - }); - }, - step3: function(successcb, errorcb) { - SQLiteFactory.openDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, function(db) { - return db.sqlBatch(['CREATE TABLE TestTable(id integer primary key autoincrement unique, data);', ['INSERT INTO TestTable (data) VALUES (?);', ['test-value']]], function() { - var firstid; - firstid = -1; - return db.executeSql('SELECT id, data FROM TestTable', [], function(resutSet) { - if (!resutSet.rows) { - SelfTest.finishWithError(errorcb, 'Missing resutSet.rows'); - return; - } - if (!resutSet.rows.length) { - SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length'); - return; - } - if (resutSet.rows.length !== 1) { - SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.length value: " + resutSet.rows.length + " (expected: 1)"); - return; - } - if (resutSet.rows.item(0).id === void 0) { - SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.item(0).id'); - return; - } - firstid = resutSet.rows.item(0).id; - if (!resutSet.rows.item(0).data) { - SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.item(0).data'); - return; - } - if (resutSet.rows.item(0).data !== 'test-value') { - SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.item(0).data value: " + (resutSet.rows.item(0).data) + " (expected: 'test-value')"); - return; - } - return db.transaction(function(tx) { - return tx.executeSql('UPDATE TestTable SET data = ?', ['new-value']); - }, function(tx_err) { - return SelfTest.finishWithError(errorcb, "UPDATE transaction error: " + tx_err); - }, function() { - var readTransactionFinished; - readTransactionFinished = false; - return db.readTransaction(function(tx2) { - return tx2.executeSql('SELECT id, data FROM TestTable', [], function(ignored, resutSet2) { - if (!resutSet2.rows) { - throw newSQLError('Missing resutSet2.rows'); - } - if (!resutSet2.rows.length) { - throw newSQLError('Missing resutSet2.rows.length'); - } - if (resutSet2.rows.length !== 1) { - throw newSQLError("Incorrect resutSet2.rows.length value: " + resutSet2.rows.length + " (expected: 1)"); - } - if (!resutSet2.rows.item(0).id) { - throw newSQLError('Missing resutSet2.rows.item(0).id'); - } - if (resutSet2.rows.item(0).id !== firstid) { - throw newSQLError("resutSet2.rows.item(0).id value " + (resutSet2.rows.item(0).id) + " does not match previous primary key id value (" + firstid + ")"); - } - if (!resutSet2.rows.item(0).data) { - throw newSQLError('Missing resutSet2.rows.item(0).data'); - } - if (resutSet2.rows.item(0).data !== 'new-value') { - throw newSQLError("Incorrect resutSet2.rows.item(0).data value: " + (resutSet2.rows.item(0).data) + " (expected: 'test-value')"); - } - return readTransactionFinished = true; - }); - }, function(tx2_err) { - return SelfTest.finishWithError(errorcb, "readTransaction error: " + tx2_err); - }, function() { - if (!readTransactionFinished) { - SelfTest.finishWithError(errorcb, 'readTransaction did not finish'); - return; - } - return db.transaction(function(tx3) { - tx3.executeSql('DELETE FROM TestTable'); - return tx3.executeSql('INSERT INTO TestTable (data) VALUES(?)', [123]); - }, function(tx3_err) { - return SelfTest.finishWithError(errorcb, "DELETE transaction error: " + tx3_err); - }, function() { - var secondReadTransactionFinished; - secondReadTransactionFinished = false; - return db.readTransaction(function(tx4) { - return tx4.executeSql('SELECT id, data FROM TestTable', [], function(ignored, resutSet3) { - if (!resutSet3.rows) { - throw newSQLError('Missing resutSet3.rows'); - } - if (!resutSet3.rows.length) { - throw newSQLError('Missing resutSet3.rows.length'); - } - if (resutSet3.rows.length !== 1) { - throw newSQLError("Incorrect resutSet3.rows.length value: " + resutSet3.rows.length + " (expected: 1)"); - } - if (!resutSet3.rows.item(0).id) { - throw newSQLError('Missing resutSet3.rows.item(0).id'); - } - if (resutSet3.rows.item(0).id === firstid) { - throw newSQLError("resutSet3.rows.item(0).id value " + (resutSet3.rows.item(0).id) + " incorrectly matches previous unique key id value value (" + firstid + ")"); - } - if (!resutSet3.rows.item(0).data) { - throw newSQLError('Missing resutSet3.rows.item(0).data'); - } - if (resutSet3.rows.item(0).data !== 123) { - throw newSQLError("Incorrect resutSet3.rows.item(0).data value: " + (resutSet3.rows.item(0).data) + " (expected 123)"); - } - return secondReadTransactionFinished = true; - }); - }, function(tx4_err) { - return SelfTest.finishWithError(errorcb, "second readTransaction error: " + tx4_err); - }, function() { - if (!secondReadTransactionFinished) { - SelfTest.finishWithError(errorcb, 'second readTransaction did not finish'); - return; - } - db.close(function() { - SelfTest.cleanupAndFinish(successcb, errorcb); - }, function(close_err) { - SelfTest.finishWithError(errorcb, "close error: " + close_err); - }); - }); - }); - }); - }); - }, function(select_err) { - return SelfTest.finishWithError(errorcb, "SELECT error: " + select_err); - }); - }, function(batch_err) { - return SelfTest.finishWithError(errorcb, "sql batch error: " + batch_err); - }); - }, function(open_err) { - return SelfTest.finishWithError(errorcb, "Open database error: " + open_err); - }); - }, - cleanupAndFinish: function(successcb, errorcb) { - SQLiteFactory.deleteDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, successcb, function(cleanup_err) { - SelfTest.finishWithError(errorcb, "CLEANUP DELETE ERROR: " + cleanup_err); - }); - }, - finishWithError: function(errorcb, message) { - console.log("selfTest ERROR with message: " + message); - SQLiteFactory.deleteDatabase({ - name: SelfTest.DBNAME, - location: 'default' - }, function() { - errorcb(newSQLError(message)); - }, function(err2) { - console.log("selfTest CLEANUP DELETE ERROR " + err2); - errorcb(newSQLError("CLEANUP DELETE ERROR: " + err2 + " for error: " + message)); - }); - } - }; - - root.sqlitePlugin = { - sqliteFeatures: { - isSQLitePlugin: true - }, - echoTest: function(okcb, errorcb) { - var error, ok; - ok = function(s) { - if (s === 'test-string') { - return okcb(); - } else { - return errorcb("Mismatch: got: '" + s + "' expected 'test-string'"); - } - }; - error = function(e) { - return errorcb(e); - }; - return cordova.exec(ok, error, "SQLitePlugin", "echoStringValue", [ - { - value: 'test-string' - } - ]); - }, - selfTest: SelfTest.start, - openDatabase: SQLiteFactory.openDatabase, - deleteDatabase: SQLiteFactory.deleteDatabase - }; - -}).call(this); - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/android/launchnavigator.js b/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/android/launchnavigator.js deleted file mode 100644 index 50c7e7db..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/android/launchnavigator.js +++ /dev/null @@ -1,328 +0,0 @@ -cordova.define("uk.co.workingedge.phonegap.plugin.launchnavigator.LaunchNavigator", function(require, exports, module) { -/* - * Copyright (c) 2014 Dave Alden (http://github.com/dpa99c) - * Copyright (c) 2014 Working Edge Ltd. (http://www.workingedge.co.uk) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -var ln = {}, - common = launchnavigator; - -/** - * Launch modes supported by Google Maps on Android - * @type {object} - */ -ln.LAUNCH_MODE = { - MAPS: "maps", - TURN_BY_TURN: "turn-by-turn", - GEO: "geo" -}; - -// Add the Android-specific option to pass in for geo: protocol, letting the native app chooser decide. -common.APP.GEO = "geo"; -common.SUPPORTS_DEST_NAME[common.PLATFORM.ANDROID].push(common.APP.GEO); -common.APPS_BY_PLATFORM[common.PLATFORM.ANDROID].splice(1, 0, common.APP.GEO); //insert at [1] below [User select] -common.APP_NAMES[common.APP.GEO] = "[Geo intent chooser]"; - -// Add apps that support the geo: protocol -function onDiscoverSupportedApps(supportedApps){ - for(var appName in supportedApps){ - var packageName = supportedApps[appName]; - common.APP[appName.toUpperCase().replace(" ","_")] = packageName; - common.APP_NAMES[packageName] = appName; - common.APPS_BY_PLATFORM[common.PLATFORM.ANDROID].push(packageName); - common.SUPPORTS_DEST_NAME[common.PLATFORM.ANDROID].push(packageName); - } -} - -function onDiscoverSupportedAppsError(error){ - console.error("Error discovering list of supported apps: "+error); -} - -/** - * Returns a list indicating which apps are installed and available on the current device. - * @param {function} success - callback to invoke on successful determination of availability. Will be passed a key/value object where the key is the app name and the value is a boolean indicating whether the app is available. - * @param {function} error - callback to invoke on error while determining availability. Will be passed a single string argument containing the error message. - */ -ln.availableApps = function(success, error){ - cordova.exec( - success, - error, - 'LaunchNavigator', - 'availableApps', - [] - ); -}; - -/** - * Determines if the given app is installed and available on the current device. - * @param {string} appName - name of the app to check availability for. Define as a constant using ln.APP - * @param {function} success - callback to invoke on successful determination of availability. Will be passed a single boolean argument indicating the availability of the app. - * @param {function} error - callback to invoke on error while determining availability. Will be passed a single string argument containing the error message. - */ -ln.isAppAvailable = function(appName, success, error){ - common.util.validateApp(appName); - cordova.exec(function(result){ - success(!!result); - }, error, 'LaunchNavigator', 'isAppAvailable', [appName]); -}; - -/** - * Opens navigator app to navigate to given destination, specified by either place name or lat/lon. - * If a start location is not also specified, current location will be used for the start. - * - * @param {string/number[]} destination (required) - destination location to use for navigation. - * Either: - * - a {string} containing the address. e.g. "Buckingham Palace, London" - * - an {array}, where the first element is the latitude and the second element is a longitude, as decimal numbers. e.g. [50.1, -4.0] - * - * @param {object} options (optional) - optional parameters: - * - * - {function} successCallback - A callback to invoke when the navigation app is successfully launched. - * - * - {function} errorCallback - A callback to invoke if an error is encountered while launching the app. - * A single string argument containing the error message will be passed in. - * - * - {string} app - navigation app to use for directions, as a constant. e.g. launchnavigator.APP.GOOGLE_MAPS - * If not specified, defaults to user selection via native picker UI. - * - * - {string} destinationName - nickname to display in app for destination. e.g. "Bob's House". - * - * - {mixed} start - start location to use for navigation. If not specified, the current location of the device will be used. - * Either: - * - a {string} containing the address. e.g. "Buckingham Palace, London" - * - a {string} containing a latitude/longitude coordinate. e.g. "50.1. -4.0" - * - an {array}, where the first element is the latitude and the second element is a longitude, as decimal numbers. e.g. [50.1, -4.0] - * - * - {string} startName - nickname to display in app for start. e.g. "My Place". - * - * - {string} transportMode - transportation mode for navigation. - * Can only be specified if navigationMode == "turn-by-turn". - * Accepted values are "driving", "walking", "bicycling" or "transit". - * Defaults to "driving" if not specified. - * - * - {string} launchModeGoogleMaps - mode in which to open Google Maps app: - * - `launchnavigator.LAUNCH_MODE.MAPS` or `launchnavigator.LAUNCH_MODE.TURN_BY_TURN` - * - Defaults to `launchnavigator.LAUNCH_MODE.MAPS` if not specified. - * - * - {boolean} enableDebug - if true, debug log output will be generated by the plugin. Defaults to false. - * - * - {object} extras - a key/value map of extra app-specific parameters. For example, to tell Google Maps to display Satellite view in "maps" launch mode: `{"t": "k"}` - * - * - {string} appSelectionDialogHeader - text to display in the native picker which enables user to select which navigation app to launch. - * Defaults to "Select app for navigation" if not specified. - * - * - {string} appSelectionCancelButton - text to display for the cancel button in the native picker which enables user to select which navigation app to launch. - * Defaults to "Cancel" if not specified. - * - * - {array} appSelectionList - list of apps, defined as `launchnavigator.APP` constants, which should be displayed in the picker if the app is available. - * This can be used to restrict which apps are displayed, even if they are installed. By default, all available apps will be displayed. - * - * - {boolean} enableGeocoding - if true, and input location type(s) doesn't match those required by the app, use geocoding to obtain the address/coords as required. Defaults to true. - */ -ln.navigate = function(destination, options) { - options = common.util.conformNavigateOptions(arguments); - - var dType, sType = "none"; - - // Input validation - var throwError = function(errMsg){ - if(options.errorCallback){ - options.errorCallback(errMsg); - } - throw new Error(errMsg); - }; - - if(!destination){ - throwError("No destination was specified"); - } - - if(options.extras && typeof options.extras !== "object"){ - throwError("'options.extras' must be a key/value object"); - } - - options.app = options.app || common.APP.USER_SELECT; - options.enableGeocoding = typeof options.enableGeocoding !== "undefined" ? options.enableGeocoding : true; - - // If app is user-selection - if(options.app === common.APP.USER_SELECT){ - // Invoke user-selection UI and return (as it will re-invoke this method) - return common.userSelect(destination, options); - } - - destination = common.util.extractCoordsFromLocationString(destination); - if(typeof(destination) === "object"){ - if(typeof destination.length === "undefined") throw "destination must be a string or an array"; - dType = "pos"; - }else{ - dType = "name"; - } - if(options.start){ - options.start = common.util.extractCoordsFromLocationString(options.start); - if(typeof(options.start) === "object"){ - if(typeof options.start.length === "undefined") throw "start must be a string or an array"; - sType = "pos"; - }else{ - sType = "name"; - } - } - - var transportMode = null; - if(options.transportMode){ - common.util.validateTransportMode(options.transportMode); - transportMode = options.transportMode.charAt(0); - } - - // Default to Google Maps if not specified - if(!options.app) options.app = common.APP.GOOGLE_MAPS; - common.util.validateApp(options.app); - - if(!options.launchModeGoogleMaps) options.launchModeGoogleMaps = ln.LAUNCH_MODE.MAPS; - common.util.validateLaunchMode(options.launchModeGoogleMaps); - - if(options.extras) options.extras = JSON.stringify(options.extras); - - cordova.exec( - options.successCallback, - options.errorCallback, - 'LaunchNavigator', - 'navigate', - [ - options.app, - dType, - destination, - options.destinationName, - sType, - options.start, - options.startName, - transportMode, - options.launchModeGoogleMaps, - options.enableDebug || false, - options.extras, - options.enableGeocoding - ] - ); -}; - -/***************************** - * Platform-specific overrides - *****************************/ - - -/** - * Indicates if an app on a given platform supports specification of transport mode. - * Android-specific implementation supports additional specification of launch mode. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @param {string} launchMode (optional) - only applies to Google Maps on Android. Specified as a constant in `launchnavigator.LAUNCH_MODE`. e.g. `launchnavigator.LAUNCH_MODE.MAPS`. - * @return {boolean} - true if app/platform combination supports specification of transport mode. - */ -ln.supportsTransportMode = function(app, platform, launchMode){ - common.util.validateApp(app); - common.util.validatePlatform(platform); - - var result; - if(launchMode && platform === common.PLATFORM.ANDROID && app === common.APP.GOOGLE_MAPS){ - common.util.validateLaunchMode(launchMode); - result = launchMode === ln.LAUNCH_MODE.TURN_BY_TURN; - }else{ - result = common._supportsTransportMode(app, platform); - } - return result; -}; -common._supportsTransportMode = common.supportsTransportMode; - -/** - * Returns the list of transport modes supported by an app on a given platform. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @param {string} launchMode (optional) - only applies to Google Maps on Android. Specified as a constant in `launchnavigator.LAUNCH_MODE`. e.g. `launchnavigator.LAUNCH_MODE.MAPS`. - * @return {string[]} - list of transports modes as constants in `launchnavigator.TRANSPORT_MODE`. - * If app/platform combination doesn't support specification of transport mode, the list will be empty; - */ -ln.getTransportModes = function(app, platform, launchMode){ - if(ln.supportsTransportMode(app, platform, launchMode)){ - return common.TRANSPORT_MODES[platform][app]; - } - return []; -}; - -/** - * Indicates if an app on a given platform supports specification of start location. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @param {string} launchMode (optional) - only applies to Google Maps on Android. Specified as a constant in `launchnavigator.LAUNCH_MODE`. e.g. `launchnavigator.LAUNCH_MODE.MAPS`. - * @return {boolean} - true if app/platform combination supports specification of start location. - */ -ln.supportsStart = function(app, platform, launchMode){ - common.util.validateApp(app); - common.util.validatePlatform(platform); - - var result; - if(launchMode && platform === common.PLATFORM.ANDROID && app === common.APP.GOOGLE_MAPS){ - common.util.validateLaunchMode(launchMode); - result = launchMode === ln.LAUNCH_MODE.MAPS; - }else{ - result = common._supportsStart(app, platform); - } - return result; -}; -common._supportsStart = common.supportsStart; - -/** - * Indicates if an app on a given platform supports specification of a custom nickname for destination location. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @param {string} launchMode (optional) - only applies to Google Maps on Android. Specified as a constant in `launchnavigator.LAUNCH_MODE`. e.g. `launchnavigator.LAUNCH_MODE.MAPS`. - * @return {boolean} - true if app/platform combination supports specification of destination location. - */ -ln.supportsDestName = function(app, platform, launchMode){ - common.util.validateApp(app); - common.util.validatePlatform(platform); - if(launchMode && platform === common.PLATFORM.ANDROID && app === common.APP.GOOGLE_MAPS){ - common.util.validateLaunchMode(launchMode); - result = launchMode === ln.LAUNCH_MODE.GEO; - }else{ - result = common._supportsDestName(app, platform); - } - return result; -}; -common._supportsDestName = common.supportsDestName; - - -/************ - * Bootstrap - ************/ - -// Discover supported apps -cordova.exec( - onDiscoverSupportedApps, - onDiscoverSupportedAppsError, - 'LaunchNavigator', - 'discoverSupportedApps', - [] -); - -module.exports = ln; -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/common.js b/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/common.js deleted file mode 100644 index bbf2d16a..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/common.js +++ /dev/null @@ -1,866 +0,0 @@ -cordova.define("uk.co.workingedge.phonegap.plugin.launchnavigator.Common", function(require, exports, module) { -/* - * Copyright (c) 2014 Dave Alden (http://github.com/dpa99c) - * Copyright (c) 2014 Working Edge Ltd. (http://www.workingedge.co.uk) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - - -var ln = {}; - -/********************* - * Internal properties - *********************/ - -var DEFAULT_appSelectionDialogHeaderText = "Select app for navigation", - DEFAULT_appSelectionCancelButtonText = "Cancel", - DEFAULT_rememberChoicePromptDialogHeaderText = "Remember your choice?", - DEFAULT_rememberChoicePromptDialogBodyText = "Use the same app for navigating next time?", - DEFAULT_rememberChoicePromptDialogYesButtonText = "Yes", - DEFAULT_rememberChoicePromptDialogNoButtonText = "No"; - -var store; - -var emptyFn = function(){}; - -/******************** - * Internal functions - ********************/ - -var ensureStore = function(){ - store = localforage.createInstance({ - name: "launchnavigator" - }); -}; - -var setItem = function(key, value, callback){ - ensureStore(); - return store.setItem(key, value, callback); -}; - -var getItem = function(key, callback){ - ensureStore(); - return store.getItem(key, function(err, value){ - callback(value); - }); -}; - -var removeItem = function(key, callback){ - ensureStore(); - return store.removeItem(key, callback); -}; - -var itemExists = function(key, callback){ - ensureStore(); - return store.getItem(key, function(err, value){ - callback(value !== null); - }); -}; - -/****************** - * Public Constants - ******************/ - -/** - * Supported platforms - * @type {object} - */ -ln.PLATFORM = { - ANDROID: "android", - IOS: "ios", - WINDOWS: "windows" -}; - -/** - * string constants, used to identify apps in native code - * @type {object} - */ -ln.APP = { - USER_SELECT: "user_select", - APPLE_MAPS: "apple_maps", - GOOGLE_MAPS: "google_maps", - WAZE: "waze", - CITYMAPPER: "citymapper", - NAVIGON: "navigon", - TRANSIT_APP: "transit_app", - YANDEX: "yandex", - UBER: "uber", - TOMTOM: "tomtom", - BING_MAPS: "bing_maps", - SYGIC: "sygic", - HERE_MAPS: "here_maps", - MOOVIT: "moovit", - LYFT: "lyft", - MAPS_ME: "maps_me", - CABIFY: "cabify", - BAIDU: "baidu", - TAXIS_99: "taxis_99", - GAODE: "gaode" -}; - -/** - * Explicitly supported apps by platform - * @type {object} - */ -ln.APPS_BY_PLATFORM = {}; -ln.APPS_BY_PLATFORM[ln.PLATFORM.ANDROID] = [ - ln.APP.USER_SELECT, - ln.APP.GOOGLE_MAPS, - ln.APP.CITYMAPPER, - ln.APP.UBER, - ln.APP.WAZE, - ln.APP.YANDEX, - ln.APP.SYGIC, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.LYFT, - ln.APP.MAPS_ME, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.APPS_BY_PLATFORM[ln.PLATFORM.IOS] = [ - ln.APP.USER_SELECT, - ln.APP.APPLE_MAPS, - ln.APP.GOOGLE_MAPS, - ln.APP.WAZE, - ln.APP.CITYMAPPER, - ln.APP.NAVIGON, - ln.APP.TRANSIT_APP, - ln.APP.YANDEX, - ln.APP.UBER, - ln.APP.TOMTOM, - ln.APP.SYGIC, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.LYFT, - ln.APP.MAPS_ME, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.APPS_BY_PLATFORM[ln.PLATFORM.WINDOWS] = [ - ln.APP.BING_MAPS -]; - -/** - * Stock maps app that is always present on each platform - * @type {object} - */ -ln.STOCK_APP = {}; -ln.STOCK_APP[ln.PLATFORM.ANDROID] = ln.APP.GOOGLE_MAPS; -ln.STOCK_APP[ln.PLATFORM.IOS] = ln.APP.APPLE_MAPS; -ln.STOCK_APP[ln.PLATFORM.WINDOWS] = ln.APP.BING_MAPS; - -/** - * Display names for supported apps - * @type {object} - */ -ln.APP_NAMES = {}; -ln.APP_NAMES[ln.APP.USER_SELECT] = "[User select]"; -ln.APP_NAMES[ln.APP.APPLE_MAPS] = "Apple Maps"; -ln.APP_NAMES[ln.APP.GOOGLE_MAPS] = "Google Maps"; -ln.APP_NAMES[ln.APP.WAZE] = "Waze"; -ln.APP_NAMES[ln.APP.CITYMAPPER] = "Citymapper"; -ln.APP_NAMES[ln.APP.NAVIGON] = "Navigon"; -ln.APP_NAMES[ln.APP.TRANSIT_APP] = "Transit App"; -ln.APP_NAMES[ln.APP.YANDEX] = "Yandex Navigator"; -ln.APP_NAMES[ln.APP.UBER] = "Uber"; -ln.APP_NAMES[ln.APP.TOMTOM] = "Tomtom"; -ln.APP_NAMES[ln.APP.BING_MAPS] = "Bing Maps"; -ln.APP_NAMES[ln.APP.SYGIC] = "Sygic"; -ln.APP_NAMES[ln.APP.HERE_MAPS] = "HERE Maps"; -ln.APP_NAMES[ln.APP.MOOVIT] = "Moovit"; -ln.APP_NAMES[ln.APP.LYFT] = "Lyft"; -ln.APP_NAMES[ln.APP.MAPS_ME] = "MAPS.ME"; -ln.APP_NAMES[ln.APP.CABIFY] = "Cabify"; -ln.APP_NAMES[ln.APP.BAIDU] = "Baidu Maps"; -ln.APP_NAMES[ln.APP.TAXIS_99] = "99 Taxi"; -ln.APP_NAMES[ln.APP.GAODE] = "Gaode Maps (Amap)"; - -/** - * All possible transport modes - * @type {object} - */ -ln.TRANSPORT_MODE = { - DRIVING: "driving", - WALKING: "walking", - BICYCLING: "bicycling", - TRANSIT: "transit" -}; - -/** - * Supported transport modes by apps and platform - * @type {object} - */ -ln.TRANSPORT_MODES = {}; -// Android -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID] = {}; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.USER_SELECT] = [ // Allow all - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.GOOGLE_MAPS] = [ // Only launchMode=turn-by-turn - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.SYGIC] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING -]; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.MAPS_ME] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.BAIDU] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.ANDROID][ln.APP.GAODE] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; - -// Windows -ln.TRANSPORT_MODES[ln.PLATFORM.WINDOWS] = {}; -ln.TRANSPORT_MODES[ln.PLATFORM.WINDOWS][ln.APP.BING_MAPS] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.TRANSIT -]; - -// iOS -ln.TRANSPORT_MODES[ln.PLATFORM.IOS] = {}; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.USER_SELECT] = [ // Allow all - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.GOOGLE_MAPS] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.APPLE_MAPS] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.SYGIC] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.MAPS_ME] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.BAIDU] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; -ln.TRANSPORT_MODES[ln.PLATFORM.IOS][ln.APP.GAODE] = [ - ln.TRANSPORT_MODE.DRIVING, - ln.TRANSPORT_MODE.WALKING, - ln.TRANSPORT_MODE.BICYCLING, - ln.TRANSPORT_MODE.TRANSIT -]; - -/** - * Apps by platform that support specifying a start location - * @type {object} - */ -ln.SUPPORTS_START = {}; -ln.SUPPORTS_START[ln.PLATFORM.ANDROID] = [ - ln.APP.USER_SELECT, - ln.APP.GOOGLE_MAPS, // Only launchMode=maps - ln.APP.CITYMAPPER, - ln.APP.UBER, - ln.APP.YANDEX, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.LYFT, - ln.APP.MAPS_ME, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.SUPPORTS_START[ln.PLATFORM.IOS] = [ - ln.APP.USER_SELECT, - ln.APP.APPLE_MAPS, - ln.APP.GOOGLE_MAPS, - ln.APP.CITYMAPPER, - ln.APP.TRANSIT_APP, - ln.APP.YANDEX, - ln.APP.UBER, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.LYFT, - ln.APP.MAPS_ME, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.SUPPORTS_START[ln.PLATFORM.WINDOWS] = [ - ln.APP.BING_MAPS -]; - -/** - * Apps by platform that support specifying a start nickname - * @type {object} - */ -ln.SUPPORTS_START_NAME = {}; -ln.SUPPORTS_START_NAME[ln.PLATFORM.ANDROID] = [ - ln.APP.USER_SELECT, - ln.APP.CITYMAPPER, - ln.APP.UBER, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.SUPPORTS_START_NAME[ln.PLATFORM.IOS] = [ - ln.APP.USER_SELECT, - ln.APP.APPLE_MAPS, // Only launchMode=mapkit - ln.APP.CITYMAPPER, - ln.APP.UBER, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; - -/** - * Apps by platform that support specifying a destination nickname - * @type {object} - */ -ln.SUPPORTS_DEST_NAME = {}; -ln.SUPPORTS_DEST_NAME[ln.PLATFORM.ANDROID] = [ - ln.APP.USER_SELECT, - ln.APP.GOOGLE_MAPS, // only launchMode=geo - ln.APP.CITYMAPPER, - ln.APP.UBER, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; -ln.SUPPORTS_DEST_NAME[ln.PLATFORM.IOS] = [ - ln.APP.USER_SELECT, - ln.APP.APPLE_MAPS, // Only launchMode=mapkit - ln.APP.CITYMAPPER, - ln.APP.NAVIGON, - ln.APP.UBER, - ln.APP.TOMTOM, - ln.APP.HERE_MAPS, - ln.APP.MOOVIT, - ln.APP.CABIFY, - ln.APP.BAIDU, - ln.APP.TAXIS_99, - ln.APP.GAODE -]; - -/** - * Apps by platform that support specifying a launch mode - * @type {object} - */ -ln.SUPPORTS_LAUNCH_MODE = {}; -ln.SUPPORTS_LAUNCH_MODE[ln.PLATFORM.ANDROID] = [ - ln.APP.USER_SELECT, - ln.APP.GOOGLE_MAPS -]; -ln.SUPPORTS_LAUNCH_MODE[ln.PLATFORM.IOS] = [ - ln.APP.USER_SELECT, - ln.APP.APPLE_MAPS -]; - -ln.COORDS_REGEX = /^[-\d.]+,[\s]*[-\d.]+$/; - - - -/****************** - * Public API - ******************/ - -/** - * Returns the display name of the specified app. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @return {string} - app display name. e.g. "Google Maps". - */ -ln.getAppDisplayName = function(app){ - ln.util.validateApp(app); - return ln.APP_NAMES[app]; -}; - -/** - * Returns list of supported apps on a given platform. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {string[]} - apps supported on specified platform as a list of `launchnavigator.APP` constants. - */ -ln.getAppsForPlatform = function(platform){ - ln.util.validatePlatform(platform); - return ln.APPS_BY_PLATFORM[platform]; -}; - -/** - * Indicates if an app on a given platform supports specification of transport mode. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {boolean} - true if app/platform combination supports specification of transport mode. - */ -ln.supportsTransportMode = function(app, platform){ - ln.util.validateApp(app); - ln.util.validatePlatform(platform); - return !!ln.TRANSPORT_MODES[platform] && ln.util.objectContainsKey(ln.TRANSPORT_MODES[platform], app); -}; - -/** - * Returns the list of transport modes supported by an app on a given platform. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {string[]} - list of transports modes as constants in `launchnavigator.TRANSPORT_MODE`. - * If app/platform combination doesn't support specification of transport mode, the list will be empty; - */ -ln.getTransportModes = function(app, platform){ - if(ln.supportsTransportMode(app, platform)){ - return ln.TRANSPORT_MODES[platform][app]; - } - return []; -}; - -/** - * Indicates if an app on a given platform supports specification of launch mode. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.ANDROID`. - * @return {boolean} - true if app/platform combination supports specification of transport mode. - */ -ln.supportsLaunchMode = function(app, platform) { - ln.util.validateApp(app); - ln.util.validatePlatform(platform); - return !!ln.SUPPORTS_LAUNCH_MODE[platform] && ln.util.arrayContainsValue(ln.SUPPORTS_LAUNCH_MODE[platform], app); -}; - -/** - * Indicates if an app on a given platform supports specification of start location. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {boolean} - true if app/platform combination supports specification of start location. - */ -ln.supportsStart = function(app, platform){ - ln.util.validateApp(app); - ln.util.validatePlatform(platform); - return !!ln.SUPPORTS_START[platform] && ln.util.arrayContainsValue(ln.SUPPORTS_START[platform], app); -}; - -/** - * Indicates if an app on a given platform supports specification of a custom nickname for start location. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {boolean} - true if app/platform combination supports specification of start location. - */ -ln.supportsStartName = function(app, platform){ - ln.util.validateApp(app); - ln.util.validatePlatform(platform); - return !!ln.SUPPORTS_START_NAME[platform] && ln.util.arrayContainsValue(ln.SUPPORTS_START_NAME[platform], app); -}; - -/** - * Indicates if an app on a given platform supports specification of a custom nickname for destination location. - * @param {string} app - specified as a constant in `launchnavigator.APP`. e.g. `launchnavigator.APP.GOOGLE_MAPS`. - * @param {string} platform - specified as a constant in `launchnavigator.PLATFORM`. e.g. `launchnavigator.PLATFORM.IOS`. - * @return {boolean} - true if app/platform combination supports specification of destination location. - */ -ln.supportsDestName = function(app, platform){ - ln.util.validateApp(app); - ln.util.validatePlatform(platform); - return !!ln.SUPPORTS_DEST_NAME[platform] && ln.util.arrayContainsValue(ln.SUPPORTS_DEST_NAME[platform], app); -}; - - -/** - * - * @param {string/number[]} destination (required) - destination location to use for navigation - see launchnavigator.navigate() - * @param {object} [options={}] - optional parameters - see launchnavigator.navigate() - * @param {function} successCallback - function executed in case of success - * @param {function} errorCallback - function executed in case of error - */ -ln.userSelect = function(destination, options, successCallback, errorCallback){ - var userSelectDisplayed, app; - - options = options || {}; - options.errorCallback = options.errorCallback || errorCallback || emptyFn; - options.successCallback = options.successCallback || successCallback || emptyFn; - - // app selection - options.appSelection = options.appSelection || {}; - options.appSelection.dialogPositionX = options.appSelection.dialogPositionX || 550; - options.appSelection.dialogPositionY = options.appSelection.dialogPositionY || 500; - options.appSelection.callback = options.appSelection.callback || emptyFn; - options.appSelection.rememberChoice = options.appSelection.rememberChoice || {}; - options.appSelection.rememberChoice.enabled = typeof options.appSelection.rememberChoice.enabled !== "undefined" ? options.appSelection.rememberChoice.enabled : "prompt"; - options.appSelection.rememberChoice.prompt = options.appSelection.rememberChoice.prompt || {}; - options.appSelection.rememberChoice.prompt.callback = options.appSelection.rememberChoice.prompt.callback || emptyFn; - - var buttonList = [], buttonMap = {}; - - if(userSelectDisplayed) return; - - var launchApp = function(){ - options.app = app; - launchnavigator.navigate(destination, options); - }; - - var displayChooser = function(){ - userSelectDisplayed = true; - window.plugins.actionsheet.show({ - 'androidTheme': options.appSelection.androidTheme || window.plugins.actionsheet.ANDROID_THEMES.THEME_HOLO_LIGHT, - 'title': options.appSelection.dialogHeaderText || DEFAULT_appSelectionDialogHeaderText, - 'buttonLabels': buttonList, - 'androidEnableCancelButton' : true, // default false - //'winphoneEnableCancelButton' : true, // default false - 'addCancelButtonWithLabel': options.appSelection.cancelButtonText || DEFAULT_appSelectionCancelButtonText, - 'position': [options.appSelection.dialogPositionX, options.appSelection.dialogPositionY] // for iPad pass in the [x, y] position of the popover - }, onChooseApp); - }; - - var onChooseApp = function (btnNumber){ - userSelectDisplayed = false; - var idx = btnNumber - 1; - app = buttonMap[idx]; - if(app !== "cancel"){ - options.appSelection.callback(app); - if(options.appSelection.rememberChoice.enabled === true || options.appSelection.rememberChoice.enabled === "true"){ - rememberUserChoiceAndLaunch(); - }else if(options.appSelection.rememberChoice.enabled === false || options.appSelection.rememberChoice.enabled === "false"){ - // Don't remember, just launch app - launchApp(); - }else{ - // Default - checkIfAlreadyPrompted(); - } - } else { - options.errorCallback('cancelled'); - } - }; - - var rememberUserChoiceAndLaunch = function(){ - setItem("choice", app, function(){ - launchApp(); - }); - }; - - var checkForChoice = function(availableApps){ - getItem("choice", function(choice){ - if(choice){ - if(availableApps[choice]){ - app = choice; - launchApp(); - }else{ - // Chosen app is no longer available on device - ln.appSelection.userChoice.clear(function(){ - ln.appSelection.userPrompted.clear(function(){ - displayChooser(); - }); - }) - } - }else{ - displayChooser(); - } - }) - }; - - // Check if user has already been prompted whether to remember their choice - var checkIfAlreadyPrompted = function(){ - getItem("prompted", function(prompted){ - if(prompted){ - launchApp(); - }else{ - promptUser(); - } - }); - }; - - // Prompt user whether to remember their choice - var promptUser = function(){ - if(options.appSelection.rememberChoice.promptFn){ - options.appSelection.rememberChoice.promptFn(handleUserPromptChoice); - }else{ - // Show prompt using cordova dialogs - navigator.notification.confirm( - options.appSelection.rememberChoice.prompt.bodyText || DEFAULT_rememberChoicePromptDialogBodyText, - function(idx){ - handleUserPromptChoice(idx === 1); - }, - options.appSelection.rememberChoice.prompt.headerText || DEFAULT_rememberChoicePromptDialogHeaderText, - [ - options.appSelection.rememberChoice.prompt.yesButtonText || DEFAULT_rememberChoicePromptDialogYesButtonText, - options.appSelection.rememberChoice.prompt.noButtonText || DEFAULT_rememberChoicePromptDialogNoButtonText - ] - ); - } - }; - - var handleUserPromptChoice = function(shouldRemember){ - options.appSelection.rememberChoice.prompt.callback(shouldRemember); - setItem("prompted", true, function(){ - if(shouldRemember){ - rememberUserChoiceAndLaunch(); - }else{ - launchApp(); - } - }); - }; - - - // Get list of available apps - launchnavigator.availableApps(function(apps){ - for(var _app in apps){ - var isAvailable = apps[_app]; - if(!isAvailable) continue; - if(options.appSelection.list && options.appSelection.list.length > 0 && !ln.util.arrayContainsValue(options.appSelection.list, _app)) continue; - buttonList.push(ln.getAppDisplayName(_app)); - buttonMap[buttonList.length-1] = _app; - } - - if(buttonList.length === 0){ - return options.errorCallback("No supported navigation apps are available on the device"); - } - - if(buttonList.length === 1){ - app = buttonMap[0]; - return launchApp(); - } - - buttonMap[buttonList.length] = "cancel"; // Add an entry for cancel button - - // Check if a user choice exists - checkForChoice(apps); - - }, options.errorCallback); -}; - -/***************************** - * App selection API functions - *****************************/ -ln.appSelection = { - userChoice: {}, - userPrompted: {} -}; - -/** - * Indicates whether a user choice exists for a preferred navigator app. - * @param {function} cb - function to pass result to: will receive a boolean argument. - */ -ln.appSelection.userChoice.exists = function(cb){ - itemExists("choice", cb); -}; - -/** - * Returns current user choice of preferred navigator app. - * @param {function} cb - function to pass result to: will receive a string argument indicating the app, which is a constant in `launchnavigator.APP`. - * If no current choice exists, value will be null. - */ -ln.appSelection.userChoice.get = function(cb){ - getItem("choice", cb); -}; - -/** - * Sets the current user choice of preferred navigator app. - * @param {string} app - app to set as preferred choice as a constant in `launchnavigator.APP`. - * @param {function} cb - function to call once operation is complete. - */ -ln.appSelection.userChoice.set = function(app, cb){ - setItem("choice", app, cb); -}; - -/** - * Clears current user choice of preferred navigator app. - * @param {function} cb - function to call once operation is complete. - */ -ln.appSelection.userChoice.clear = function(cb){ - removeItem("choice", cb); -}; - -/** - * Indicates whether user has already been prompted whether to remember their choice a preferred navigator app. - * @param {function} cb - function to pass result to: will receive a boolean argument. - */ -ln.appSelection.userPrompted.get = function(cb){ - itemExists("prompted", cb); -}; - -/** - * Sets flag indicating user has already been prompted whether to remember their choice a preferred navigator app. - * @param {function} cb - function to call once operation is complete. - */ -ln.appSelection.userPrompted.set = function(cb){ - setItem("prompted", true, cb); -}; - -/** - * Clears flag which indicates if user has already been prompted whether to remember their choice a preferred navigator app. - * @param {function} cb - function to call once operation is complete. - */ -ln.appSelection.userPrompted.clear = function(cb){ - removeItem("prompted", cb); -}; - -/******************* - * Utility functions - *******************/ -ln.util = {}; -ln.util.arrayContainsValue = function (a, obj) { - var i = a.length; - while (i--) { - if (a[i] === obj) { - return true; - } - } - return false; -}; - -ln.util.objectContainsKey = function (o, key) { - for(var k in o){ - if(k === key){ - return true; - } - } - return false; -}; - -ln.util.objectContainsValue = function (o, value) { - for(var k in o){ - if(o[k] === value){ - return true; - } - } - return false; -}; - -ln.util.countKeysInObject = function (o){ - var count = 0; - for(var k in o){ - count++; - } - return count; -}; - -ln.util.isValidApp = function(app){ - if(app === "none") return true; // native chooser - return ln.util.objectContainsValue(ln.APP, app); -}; - -ln.util.isValidPlatform = function(platform){ - return ln.util.objectContainsValue(ln.PLATFORM, platform); -}; - -ln.util.isValidTransportMode = function(transportMode) { - return ln.util.objectContainsValue(ln.TRANSPORT_MODE, transportMode); -}; - -ln.util.validateApp = function(app){ - if(!ln.util.isValidApp(app)){ - throw new Error("'"+app+"' is not a recognised app"); - } -}; - -ln.util.validatePlatform = function(platform){ - if(!ln.util.isValidPlatform(platform)){ - throw new Error("'"+platform+"' is not a recognised platform"); - } -}; - -ln.util.validateTransportMode = function(transportMode){ - if(!ln.util.isValidTransportMode(transportMode)){ - throw new Error("'"+transportMode+"' is not a recognised transport mode"); - } -}; - -ln.util.extractCoordsFromLocationString = function(location){ - if(location && typeof(location) === "string" && location.match(ln.COORDS_REGEX)){ - location = location.replace(/\s*/g,''); - var parts = location.split(","); - location = [parts[0], parts[1]]; - } - return location; -}; - -ln.util.isValidLaunchMode = function(launchMode){ - for(var LAUNCH_MODE in ln.LAUNCH_MODE){ - if(launchMode === ln.LAUNCH_MODE[LAUNCH_MODE]) return true; - } - return false; -}; - -ln.util.validateLaunchMode = function(launchMode){ - if(!ln.util.isValidLaunchMode(launchMode)){ - throw new Error("'"+launchMode+"' is not a recognised launch mode"); - } -}; - -ln.util.conformNavigateOptions = function(args){ - var options; - if(args.length > 1 && typeof args[1] === "function"){ - // assume (dest, success, error, opts) - options = (args.length > 3 && typeof args[3] === "object") ? args[3] : {}; - options.successCallback = args[1]; - if(args.length > 2 && typeof args[2] === "function"){ - options.errorCallback = args[2]; - } - }else{ - // assume (dest, opts) - options = (args.length > 1 && typeof args[1] === "object") ? args[1] : {}; - } - return options; -}; - - -module.exports = ln; - -}); diff --git a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/localforage.v1.5.0.min.js b/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/localforage.v1.5.0.min.js deleted file mode 100644 index 5ba7d281..00000000 --- a/platforms/android/app/src/main/assets/www/plugins/uk.co.workingedge.phonegap.plugin.launchnavigator/www/localforage.v1.5.0.min.js +++ /dev/null @@ -1,9 +0,0 @@ -cordova.define("uk.co.workingedge.phonegap.plugin.launchnavigator.LocalForage", function(require, exports, module) { -/*! - localForage -- Offline Storage, Improved - Version 1.5.0 - https://localforage.github.io/localForage - (c) 2013-2017 Mozilla, Apache License 2.0 -*/ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.localforage=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;ge;e++)d[e]=a.charCodeAt(e);return c}function m(a){return new ja(function(b){var c=a.transaction(ka,"readwrite"),d=i([""]);c.objectStore(ka).put(d,"key"),c.onabort=function(a){a.preventDefault(),a.stopPropagation(),b(!1)},c.oncomplete=function(){var a=navigator.userAgent.match(/Chrome\/(\d+)/),c=navigator.userAgent.match(/Edge\//);b(c||!a||parseInt(a[1],10)>=43)}})["catch"](function(){return!1})}function n(a){return"boolean"==typeof ha?ja.resolve(ha):m(a).then(function(a){return ha=a})}function o(a){var b=ia[a.name],c={};c.promise=new ja(function(a){c.resolve=a}),b.deferredOperations.push(c),b.dbReady?b.dbReady=b.dbReady.then(function(){return c.promise}):b.dbReady=c.promise}function p(a){var b=ia[a.name],c=b.deferredOperations.pop();c&&c.resolve()}function q(a,b){return new ja(function(c,d){if(a.db){if(!b)return c(a.db);o(a),a.db.close()}var e=[a.name];b&&e.push(a.version);var f=ga.open.apply(ga,e);b&&(f.onupgradeneeded=function(b){var c=f.result;try{c.createObjectStore(a.storeName),b.oldVersion<=1&&c.createObjectStore(ka)}catch(d){if("ConstraintError"!==d.name)throw d;console.warn('The database "'+a.name+'" has been upgraded from version '+b.oldVersion+" to version "+b.newVersion+', but the storage "'+a.storeName+'" already exists.')}}),f.onerror=function(a){a.preventDefault(),d(f.error)},f.onsuccess=function(){c(f.result),p(a)}})}function r(a){return q(a,!1)}function s(a){return q(a,!0)}function t(a,b){if(!a.db)return!0;var c=!a.db.objectStoreNames.contains(a.storeName),d=a.versiona.db.version;if(d&&(a.version!==b&&console.warn('The database "'+a.name+"\" can't be downgraded from version "+a.db.version+" to version "+a.version+"."),a.version=a.db.version),e||c){if(c){var f=a.db.version+1;f>a.version&&(a.version=f)}return!0}return!1}function u(a){return new ja(function(b,c){var d=new FileReader;d.onerror=c,d.onloadend=function(c){var d=btoa(c.target.result||"");b({__local_forage_encoded_blob:!0,data:d,type:a.type})},d.readAsBinaryString(a)})}function v(a){var b=l(atob(a.data));return i([b],{type:a.type})}function w(a){return a&&a.__local_forage_encoded_blob}function x(a){var b=this,c=b._initReady().then(function(){var a=ia[b._dbInfo.name];return a&&a.dbReady?a.dbReady:void 0});return k(c,a,a),c}function y(a){function b(){return ja.resolve()}var c=this,d={db:null};if(a)for(var e in a)d[e]=a[e];ia||(ia={});var f=ia[d.name];f||(f={forages:[],db:null,dbReady:null,deferredOperations:[]},ia[d.name]=f),f.forages.push(c),c._initReady||(c._initReady=c.ready,c.ready=x);for(var g=[],h=0;ha?void b(null):void c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=!1,h=f.openCursor();h.onsuccess=function(){var c=h.result;return c?void(0===a?b(c.key):g?b(c.key):(g=!0,c.advance(a))):void b(null)},h.onerror=function(){d(h.error)}})["catch"](d)});return j(d,b),d}function G(a){var b=this,c=new ja(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readonly").objectStore(d.storeName),f=e.openCursor(),g=[];f.onsuccess=function(){var b=f.result;return b?(g.push(b.key),void b["continue"]()):void a(g)},f.onerror=function(){c(f.error)}})["catch"](c)});return j(c,a),c}function H(a){var b,c,d,e,f,g=.75*a.length,h=a.length,i=0;"="===a[a.length-1]&&(g--,"="===a[a.length-2]&&g--);var j=new ArrayBuffer(g),k=new Uint8Array(j);for(b=0;h>b;b+=4)c=na.indexOf(a[b]),d=na.indexOf(a[b+1]),e=na.indexOf(a[b+2]),f=na.indexOf(a[b+3]),k[i++]=c<<2|d>>4,k[i++]=(15&d)<<4|e>>2,k[i++]=(3&e)<<6|63&f;return j}function I(a){var b,c=new Uint8Array(a),d="";for(b=0;b>2],d+=na[(3&c[b])<<4|c[b+1]>>4],d+=na[(15&c[b+1])<<2|c[b+2]>>6],d+=na[63&c[b+2]];return c.length%3===2?d=d.substring(0,d.length-1)+"=":c.length%3===1&&(d=d.substring(0,d.length-2)+"=="),d}function J(a,b){var c="";if(a&&(c=Ea.call(a)),a&&("[object ArrayBuffer]"===c||a.buffer&&"[object ArrayBuffer]"===Ea.call(a.buffer))){var d,e=qa;a instanceof ArrayBuffer?(d=a,e+=sa):(d=a.buffer,"[object Int8Array]"===c?e+=ua:"[object Uint8Array]"===c?e+=va:"[object Uint8ClampedArray]"===c?e+=wa:"[object Int16Array]"===c?e+=xa:"[object Uint16Array]"===c?e+=za:"[object Int32Array]"===c?e+=ya:"[object Uint32Array]"===c?e+=Aa:"[object Float32Array]"===c?e+=Ba:"[object Float64Array]"===c?e+=Ca:b(new Error("Failed to get type for BinaryArray"))),b(e+I(d))}else if("[object Blob]"===c){var f=new FileReader;f.onload=function(){var c=oa+a.type+"~"+I(this.result);b(qa+ta+c)},f.readAsArrayBuffer(a)}else try{b(JSON.stringify(a))}catch(g){console.error("Couldn't convert value into a JSON string: ",a),b(null,g)}}function K(a){if(a.substring(0,ra)!==qa)return JSON.parse(a);var b,c=a.substring(Da),d=a.substring(ra,Da);if(d===ta&&pa.test(c)){var e=c.match(pa);b=e[1],c=c.substring(e[0].length)}var f=H(c);switch(d){case sa:return f;case ta:return i([f],{type:b});case ua:return new Int8Array(f);case va:return new Uint8Array(f);case wa:return new Uint8ClampedArray(f);case xa:return new Int16Array(f);case za:return new Uint16Array(f);case ya:return new Int32Array(f);case Aa:return new Uint32Array(f);case Ba:return new Float32Array(f);case Ca:return new Float64Array(f);default:throw new Error("Unkown type: "+d)}}function L(a){var b=this,c={db:null};if(a)for(var d in a)c[d]="string"!=typeof a[d]?a[d].toString():a[d];var e=new ja(function(a,d){try{c.db=openDatabase(c.name,String(c.version),c.description,c.size)}catch(e){return d(e)}c.db.transaction(function(e){e.executeSql("CREATE TABLE IF NOT EXISTS "+c.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],function(){b._dbInfo=c,a()},function(a,b){d(b)})})});return c.serializer=Fa,e}function M(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new ja(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName+" WHERE key = ? LIMIT 1",[a],function(a,c){var d=c.rows.length?c.rows.item(0).value:null;d&&(d=e.serializer.deserialize(d)),b(d)},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function N(a,b){var c=this,d=new ja(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName,[],function(c,d){for(var f=d.rows,g=f.length,h=0;g>h;h++){var i=f.item(h),j=i.value;if(j&&(j=e.serializer.deserialize(j)),j=a(j,i.key,h+1),void 0!==j)return void b(j)}b()},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function O(a,b,c,d){var e=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var f=new ja(function(f,g){e.ready().then(function(){void 0===b&&(b=null);var h=b,i=e._dbInfo;i.serializer.serialize(b,function(b,j){j?g(j):i.db.transaction(function(c){c.executeSql("INSERT OR REPLACE INTO "+i.storeName+" (key, value) VALUES (?, ?)",[a,b],function(){f(h)},function(a,b){g(b)})},function(b){if(b.code===b.QUOTA_ERR){if(d>0)return void f(O.apply(e,[a,h,c,d-1]));g(b)}})})})["catch"](g)});return j(f,c),f}function P(a,b,c){return O.apply(this,[a,b,c,1])}function Q(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=new ja(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("DELETE FROM "+e.storeName+" WHERE key = ?",[a],function(){b()},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function R(a){var b=this,c=new ja(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("DELETE FROM "+d.storeName,[],function(){a()},function(a,b){c(b)})})})["catch"](c)});return j(c,a),c}function S(a){var b=this,c=new ja(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT COUNT(key) as c FROM "+d.storeName,[],function(b,c){var d=c.rows.item(0).c;a(d)},function(a,b){c(b)})})})["catch"](c)});return j(c,a),c}function T(a,b){var c=this,d=new ja(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT key FROM "+e.storeName+" WHERE id = ? LIMIT 1",[a+1],function(a,c){var d=c.rows.length?c.rows.item(0).key:null;b(d)},function(a,b){d(b)})})})["catch"](d)});return j(d,b),d}function U(a){var b=this,c=new ja(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT key FROM "+d.storeName,[],function(b,c){for(var d=[],e=0;e=0;c--){var d=localStorage.key(c);0===d.indexOf(a)&&localStorage.removeItem(d)}});return j(c,a),c}function X(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo,d=localStorage.getItem(b.keyPrefix+a);return d&&(d=b.serializer.deserialize(d)),d});return j(d,b),d}function Y(a,b){var c=this,d=c.ready().then(function(){for(var b=c._dbInfo,d=b.keyPrefix,e=d.length,f=localStorage.length,g=1,h=0;f>h;h++){var i=localStorage.key(h);if(0===i.indexOf(d)){var j=localStorage.getItem(i);if(j&&(j=b.serializer.deserialize(j)),j=a(j,i.substring(e),g++),void 0!==j)return j}}});return j(d,b),d}function Z(a,b){var c=this,d=c.ready().then(function(){var b,d=c._dbInfo;try{b=localStorage.key(a)}catch(e){b=null}return b&&(b=b.substring(d.keyPrefix.length)),b});return j(d,b),d}function $(a){var b=this,c=b.ready().then(function(){for(var a=b._dbInfo,c=localStorage.length,d=[],e=0;c>e;e++)0===localStorage.key(e).indexOf(a.keyPrefix)&&d.push(localStorage.key(e).substring(a.keyPrefix.length));return d});return j(c,a),c}function _(a){var b=this,c=b.keys().then(function(a){return a.length});return j(c,a),c}function aa(a,b){var c=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var d=c.ready().then(function(){var b=c._dbInfo;localStorage.removeItem(b.keyPrefix+a)});return j(d,b),d}function ba(a,b,c){var d=this;"string"!=typeof a&&(console.warn(a+" used as a key, but it is not a string."),a=String(a));var e=d.ready().then(function(){void 0===b&&(b=null);var c=b;return new ja(function(e,f){var g=d._dbInfo;g.serializer.serialize(b,function(b,d){if(d)f(d);else try{localStorage.setItem(g.keyPrefix+a,b),e(c)}catch(h){"QuotaExceededError"!==h.name&&"NS_ERROR_DOM_QUOTA_REACHED"!==h.name||f(h),f(h)}})})});return j(e,c),e}function ca(a,b){a[b]=function(){var c=arguments;return a.ready().then(function(){return a[b].apply(a,c)})}}function da(){for(var a=1;ac;c++){var e=a[c];this.supports(e)&&b.push(e)}return b},a.prototype._wrapLibraryMethodsWithReady=function(){for(var a=0;a 0) { - //Call checkPermission again to verify - boolean hasAllPermissions = hasAllPermissions(permissions); - addProperty(returnObj, KEY_RESULT_PERMISSION, hasAllPermissions); - permissionsCallback.success(returnObj); - } else { - addProperty(returnObj, KEY_ERROR, ACTION_REQUEST_PERMISSION); - addProperty(returnObj, KEY_MESSAGE, "Unknown error."); - permissionsCallback.error(returnObj); - } - permissionsCallback = null; - } - - private void checkPermissionAction(CallbackContext callbackContext, JSONArray permission) { - if (permission == null || permission.length() == 0 || permission.length() > 1) { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_ERROR, ACTION_CHECK_PERMISSION); - addProperty(returnObj, KEY_MESSAGE, "One time one permission only."); - callbackContext.error(returnObj); - } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_RESULT_PERMISSION, true); - callbackContext.success(returnObj); - } else { - try { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_RESULT_PERMISSION, cordova.hasPermission(permission.getString(0))); - callbackContext.success(returnObj); - } catch (JSONException e) { - e.printStackTrace(); - } - } - } - - private void requestPermissionAction(CallbackContext callbackContext, JSONArray permissions) throws Exception { - if (permissions == null || permissions.length() == 0) { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_ERROR, ACTION_REQUEST_PERMISSION); - addProperty(returnObj, KEY_MESSAGE, "At least one permission."); - callbackContext.error(returnObj); - } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_RESULT_PERMISSION, true); - callbackContext.success(returnObj); - } else if (hasAllPermissions(permissions)) { - JSONObject returnObj = new JSONObject(); - addProperty(returnObj, KEY_RESULT_PERMISSION, true); - callbackContext.success(returnObj); - } else { - permissionsCallback = callbackContext; - String[] permissionArray = getPermissions(permissions); - cordova.requestPermissions(this, REQUEST_CODE_ENABLE_PERMISSION, permissionArray); - } - } - - private String[] getPermissions(JSONArray permissions) { - String[] stringArray = new String[permissions.length()]; - for (int i = 0; i < permissions.length(); i++) { - try { - stringArray[i] = permissions.getString(i); - } catch (JSONException ignored) { - //Believe exception only occurs when adding duplicate keys, so just ignore it - } - } - return stringArray; - } - - private boolean hasAllPermissions(JSONArray permissions) throws JSONException { - return hasAllPermissions(getPermissions(permissions)); - } - - private boolean hasAllPermissions(String[] permissions) throws JSONException { - - for (String permission : permissions) { - if(!cordova.hasPermission(permission)) { - return false; - } - } - - return true; - } - - private void addProperty(JSONObject obj, String key, Object value) { - try { - if (value == null) { - obj.put(key, JSONObject.NULL); - } else { - obj.put(key, value); - } - } catch (JSONException ignored) { - //Believe exception only occurs when adding duplicate keys, so just ignore it - } - } -} diff --git a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/AndroidProtocolHandler.java b/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/AndroidProtocolHandler.java deleted file mode 100755 index 6a331d3e..00000000 --- a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/AndroidProtocolHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.ionicframework.cordova.webview; - -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import android.content.Context; -import android.content.res.AssetManager; -import android.net.Uri; -import android.util.Log; -import android.util.TypedValue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - - -public class AndroidProtocolHandler { - private static final String TAG = "AndroidProtocolHandler"; - - private Context context; - - public AndroidProtocolHandler(Context context) { - this.context = context; - } - - public InputStream openAsset(String path, String assetPath) throws IOException { - if (path.startsWith(assetPath + "/_file_")) { - if (path.contains("content://")) { - String contentPath = path.replace(assetPath + "/_file_/", "content://"); - return context.getContentResolver().openInputStream(Uri.parse(contentPath)); - } else { - String filePath = path.replace(assetPath + "/_file_/", ""); - return new FileInputStream(new File(filePath)); - } - } else { - return context.getAssets().open(path, AssetManager.ACCESS_STREAMING); - } - } - - public InputStream openResource(Uri uri) { - assert uri.getPath() != null; - // The path must be of the form ".../asset_type/asset_name.ext". - List pathSegments = uri.getPathSegments(); - String assetType = pathSegments.get(pathSegments.size() - 2); - String assetName = pathSegments.get(pathSegments.size() - 1); - - // Drop the file extension. - assetName = assetName.split("\\.")[0]; - try { - // Use the application context for resolving the resource package name so that we do - // not use the browser's own resources. Note that if 'context' here belongs to the - // test suite, it does not have a separate application context. In that case we use - // the original context object directly. - if (context.getApplicationContext() != null) { - context = context.getApplicationContext(); - } - int fieldId = getFieldId(context, assetType, assetName); - int valueType = getValueType(context, fieldId); - if (valueType == TypedValue.TYPE_STRING) { - return context.getResources().openRawResource(fieldId); - } else { - Log.e(TAG, "Asset not of type string: " + uri); - return null; - } - } catch (ClassNotFoundException e) { - Log.e(TAG, "Unable to open resource URL: " + uri, e); - return null; - } catch (NoSuchFieldException e) { - Log.e(TAG, "Unable to open resource URL: " + uri, e); - return null; - } catch (IllegalAccessException e) { - Log.e(TAG, "Unable to open resource URL: " + uri, e); - return null; - } - } - - public InputStream openFile(String filePath) throws IOException { - File localFile = new File(filePath); - return new FileInputStream(localFile); - } - - private static int getFieldId(Context context, String assetType, String assetName) - throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { - Class d = context.getClassLoader() - .loadClass(context.getPackageName() + ".R$" + assetType); - java.lang.reflect.Field field = d.getField(assetName); - int id = field.getInt(null); - return id; - } - - private static int getValueType(Context context, int fieldId) { - TypedValue value = new TypedValue(); - context.getResources().getValue(fieldId, value, true); - return value.type; - } -} diff --git a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebView.java b/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebView.java deleted file mode 100755 index ff771371..00000000 --- a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebView.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ionicframework.cordova.webview; - -import android.app.Activity; -import android.content.SharedPreferences; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.json.JSONArray; -import org.json.JSONException; - -public class IonicWebView extends CordovaPlugin { - - public static final String WEBVIEW_PREFS_NAME = "WebViewSettings"; - public static final String CDV_SERVER_PATH = "serverBasePath"; - - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - - if (action.equals("setServerBasePath")) { - final String path = args.getString(0); - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - ((IonicWebViewEngine)webView.getEngine()).setServerBasePath(path); - } - }); - return true; - } else if (action.equals("getServerBasePath")) { - callbackContext.success(((IonicWebViewEngine)webView.getEngine()).getServerBasePath()); - return true; - } else if (action.equals("persistServerBasePath")) { - String path = ((IonicWebViewEngine)webView.getEngine()).getServerBasePath(); - SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(CDV_SERVER_PATH, path); - editor.apply(); - return true; - } - return false; - } - -} - diff --git a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebViewEngine.java deleted file mode 100755 index 08ee8ab5..00000000 --- a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/IonicWebViewEngine.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.ionicframework.cordova.webview; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.annotation.TargetApi; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.RequiresApi; -import android.util.Log; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; -import android.webkit.WebView; -import org.apache.cordova.ConfigXmlParser; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPreferences; -import org.apache.cordova.CordovaResourceApi; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CordovaWebViewEngine; -import org.apache.cordova.NativeToJsMessageQueue; -import org.apache.cordova.PluginManager; -import org.apache.cordova.engine.SystemWebViewClient; -import org.apache.cordova.engine.SystemWebViewEngine; -import org.apache.cordova.engine.SystemWebView; - -public class IonicWebViewEngine extends SystemWebViewEngine { - public static final String TAG = "IonicWebViewEngine"; - - private WebViewLocalServer localServer; - private String CDV_LOCAL_SERVER; - private static final String LAST_BINARY_VERSION_CODE = "lastBinaryVersionCode"; - private static final String LAST_BINARY_VERSION_NAME = "lastBinaryVersionName"; - - /** - * Used when created via reflection. - */ - public IonicWebViewEngine(Context context, CordovaPreferences preferences) { - super(new SystemWebView(context), preferences); - Log.d(TAG, "Ionic Web View Engine Starting Right Up 1..."); - } - - public IonicWebViewEngine(SystemWebView webView) { - super(webView, null); - Log.d(TAG, "Ionic Web View Engine Starting Right Up 2..."); - } - - public IonicWebViewEngine(SystemWebView webView, CordovaPreferences preferences) { - super(webView, preferences); - Log.d(TAG, "Ionic Web View Engine Starting Right Up 3..."); - } - - @Override - public void init(CordovaWebView parentWebView, CordovaInterface cordova, final CordovaWebViewEngine.Client client, - CordovaResourceApi resourceApi, PluginManager pluginManager, - NativeToJsMessageQueue nativeToJsMessageQueue) { - ConfigXmlParser parser = new ConfigXmlParser(); - parser.parse(cordova.getActivity()); - - String port = preferences.getString("WKPort", "8080"); - CDV_LOCAL_SERVER = "http://localhost:" + port; - - localServer = new WebViewLocalServer(cordova.getActivity(), "localhost:" + port, true, parser); - WebViewLocalServer.AssetHostingDetails ahd = localServer.hostAssets("www"); - - webView.setWebViewClient(new ServerClient(this, parser)); - - super.init(parentWebView, cordova, client, resourceApi, pluginManager, nativeToJsMessageQueue); - SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); - String path = prefs.getString(IonicWebView.CDV_SERVER_PATH, null); - if (!isDeployDisabled() && !isNewBinary() && path != null && !path.isEmpty()) { - setServerBasePath(path); - } - } - - private boolean isNewBinary() { - String versionCode = ""; - String versionName = ""; - SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); - String lastVersionCode = prefs.getString(LAST_BINARY_VERSION_CODE, null); - String lastVersionName = prefs.getString(LAST_BINARY_VERSION_NAME, null); - - try { - PackageInfo pInfo = this.cordova.getActivity().getPackageManager().getPackageInfo(this.cordova.getActivity().getPackageName(), 0); - versionCode = Integer.toString(pInfo.versionCode); - versionName = pInfo.versionName; - } catch(Exception ex) { - Log.e(TAG, "Unable to get package info", ex); - } - - if (!versionCode.equals(lastVersionCode) || !versionName.equals(lastVersionName)) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(LAST_BINARY_VERSION_CODE, versionCode); - editor.putString(LAST_BINARY_VERSION_NAME, versionName); - editor.putString(IonicWebView.CDV_SERVER_PATH, ""); - editor.apply(); - return true; - } - return false; - } - - private boolean isDeployDisabled() { - return preferences.getBoolean("DisableDeploy", false); - } - private class ServerClient extends SystemWebViewClient { - private ConfigXmlParser parser; - - public ServerClient(SystemWebViewEngine parentEngine, ConfigXmlParser parser) { - super(parentEngine); - this.parser = parser; - } - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - return localServer.shouldInterceptRequest(request.getUrl()); - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, String url) { - return localServer.shouldInterceptRequest(Uri.parse(url)); - } - - @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - super.onPageStarted(view, url, favicon); - String launchUrl = parser.getLaunchUrl(); - if (!launchUrl.contains("http") && url.equals(launchUrl)) { - view.stopLoading(); - view.loadUrl(CDV_LOCAL_SERVER); - } - } - - @Override - public void onPageFinished(WebView view, String url) { - super.onPageFinished(view, url); - view.loadUrl("javascript:(function() { " + - "window.WEBVIEW_SERVER_URL = '" + CDV_LOCAL_SERVER + "'" + - "})()"); - } - } - - public void setServerBasePath(String path) { - localServer.hostFiles(path); - webView.loadUrl(CDV_LOCAL_SERVER); - } - - public String getServerBasePath() { - return this.localServer.getBasePath(); - } -} diff --git a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/UriMatcher.java b/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/UriMatcher.java deleted file mode 100755 index d8addb9b..00000000 --- a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/UriMatcher.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.ionicframework.cordova.webview; - -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -//package com.google.webviewlocalserver.third_party.android; - -import android.net.Uri; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -public class UriMatcher { - /** - * Creates the root node of the URI tree. - * - * @param code the code to match for the root URI - */ - public UriMatcher(Object code) { - mCode = code; - mWhich = -1; - mChildren = new ArrayList(); - mText = null; - } - - private UriMatcher() { - mCode = null; - mWhich = -1; - mChildren = new ArrayList(); - mText = null; - } - - /** - * Add a URI to match, and the code to return when this URI is - * matched. URI nodes may be exact match string, the token "*" - * that matches any text, or the token "#" that matches only - * numbers. - *

- * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, - * this method will accept a leading slash in the path. - * - * @param authority the authority to match - * @param path the path to match. * may be used as a wild card for - * any text, and # may be used as a wild card for numbers. - * @param code the code that is returned when a URI is matched - * against the given components. Must be positive. - */ - public void addURI(String scheme, String authority, String path, Object code) { - if (code == null) { - throw new IllegalArgumentException("Code can't be null"); - } - - String[] tokens = null; - if (path != null) { - String newPath = path; - // Strip leading slash if present. - if (path.length() > 0 && path.charAt(0) == '/') { - newPath = path.substring(1); - } - tokens = PATH_SPLIT_PATTERN.split(newPath); - } - - int numTokens = tokens != null ? tokens.length : 0; - UriMatcher node = this; - for (int i = -2; i < numTokens; i++) { - String token; - if (i == -2) - token = scheme; - else if (i == -1) - token = authority; - else - token = tokens[i]; - ArrayList children = node.mChildren; - int numChildren = children.size(); - UriMatcher child; - int j; - for (j = 0; j < numChildren; j++) { - child = children.get(j); - if (token.equals(child.mText)) { - node = child; - break; - } - } - if (j == numChildren) { - // Child not found, create it - child = new UriMatcher(); - if (token.equals("**")) { - child.mWhich = REST; - } else if (token.equals("*")) { - child.mWhich = TEXT; - } else { - child.mWhich = EXACT; - } - child.mText = token; - node.mChildren.add(child); - node = child; - } - } - node.mCode = code; - } - - static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/"); - - /** - * Try to match against the path in a url. - * - * @param uri The url whose path we will match against. - * @return The code for the matched node (added using addURI), - * or null if there is no matched node. - */ - public Object match(Uri uri) { - final List pathSegments = uri.getPathSegments(); - final int li = pathSegments.size(); - - UriMatcher node = this; - - if (li == 0 && uri.getAuthority() == null) { - return this.mCode; - } - - for (int i = -2; i < li; i++) { - String u; - if (i == -2) - u = uri.getScheme(); - else if (i == -1) - u = uri.getAuthority(); - else - u = pathSegments.get(i); - ArrayList list = node.mChildren; - if (list == null) { - break; - } - node = null; - int lj = list.size(); - for (int j = 0; j < lj; j++) { - UriMatcher n = list.get(j); - which_switch: - switch (n.mWhich) { - case EXACT: - if (n.mText.equals(u)) { - node = n; - } - break; - case TEXT: - node = n; - break; - case REST: - return n.mCode; - } - if (node != null) { - break; - } - } - if (node == null) { - return null; - } - } - - return node.mCode; - } - - private static final int EXACT = 0; - private static final int TEXT = 1; - private static final int REST = 2; - - private Object mCode; - private int mWhich; - private String mText; - private ArrayList mChildren; -} diff --git a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/WebViewLocalServer.java b/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/WebViewLocalServer.java deleted file mode 100755 index b2b81295..00000000 --- a/platforms/android/app/src/main/java/com/ionicframework/cordova/webview/WebViewLocalServer.java +++ /dev/null @@ -1,677 +0,0 @@ -/* -Copyright 2015 Google Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - */ -package com.ionicframework.cordova.webview; - -import android.content.Context; -import android.net.Uri; -import android.os.Build; -import android.util.Log; -import android.webkit.WebResourceResponse; - -import org.apache.cordova.ConfigXmlParser; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLConnection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * Helper class meant to be used with the android.webkit.WebView class to enable hosting assets, - * resources and other data on 'virtual' http(s):// URL. - * Hosting assets and resources on http(s):// URLs is desirable as it is compatible with the - * Same-Origin policy. - *

- * This class is intended to be used from within the - * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, String)} and - * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, - * android.webkit.WebResourceRequest)} - * methods. - */ -public class WebViewLocalServer { - private static String TAG = "WebViewAssetServer"; - private String basePath; - /** - * capacitorapp.net is reserved by the Ionic team for use in local capacitor apps. - */ - public final static String knownUnusedAuthority = "capacitorapp.net"; - private final static String httpScheme = "http"; - private final static String httpsScheme = "https"; - - private final UriMatcher uriMatcher; - private final AndroidProtocolHandler protocolHandler; - private final String authority; - // Whether we're serving local files or proxying (for example, when doing livereload on a - // non-local endpoint (will be false in that case) - private final boolean isLocal; - private boolean isAsset; - // Whether to route all requests to paths without extensions back to `index.html` - private final boolean html5mode; - private ConfigXmlParser parser; - - public String getAuthority() { return authority; } - - /** - * A handler that produces responses for paths on the virtual asset server. - *

- * Methods of this handler will be invoked on a background thread and care must be taken to - * correctly synchronize access to any shared state. - *

- * On Android KitKat and above these methods may be called on more than one thread. This thread - * may be different than the thread on which the shouldInterceptRequest method was invoke. - * This means that on Android KitKat and above it is possible to block in this method without - * blocking other resources from loading. The number of threads used to parallelize loading - * is an internal implementation detail of the WebView and may change between updates which - * means that the amount of time spend blocking in this method should be kept to an absolute - * minimum. - */ - public abstract static class PathHandler { - protected String mimeType; - private String encoding; - private String charset; - private int statusCode; - private String reasonPhrase; - private Map responseHeaders; - - public PathHandler() { - this(null, null, 200, "OK", null); - } - - public PathHandler(String encoding, String charset, int statusCode, - String reasonPhrase, Map responseHeaders) { - this.encoding = encoding; - this.charset = charset; - this.statusCode = statusCode; - this.reasonPhrase = reasonPhrase; - Map tempResponseHeaders; - if (responseHeaders == null) { - tempResponseHeaders = new HashMap(); - } else { - tempResponseHeaders = responseHeaders; - } - tempResponseHeaders.put("Cache-Control", "no-cache"); - this.responseHeaders = tempResponseHeaders; - } - - abstract public InputStream handle(Uri url); - - public String getEncoding() { - return encoding; - } - - public String getCharset() { - return charset; - } - - public int getStatusCode() { - return statusCode; - } - - public String getReasonPhrase() { - return reasonPhrase; - } - - public Map getResponseHeaders() { - return responseHeaders; - } - } - - /** - * Information about the URLs used to host the assets in the WebView. - */ - public static class AssetHostingDetails { - private Uri httpPrefix; - private Uri httpsPrefix; - - /*package*/ AssetHostingDetails(Uri httpPrefix, Uri httpsPrefix) { - this.httpPrefix = httpPrefix; - this.httpsPrefix = httpsPrefix; - } - - /** - * Gets the http: scheme prefix at which assets are hosted. - * - * @return the http: scheme prefix at which assets are hosted. Can return null. - */ - public Uri getHttpPrefix() { - return httpPrefix; - } - - /** - * Gets the https: scheme prefix at which assets are hosted. - * - * @return the https: scheme prefix at which assets are hosted. Can return null. - */ - public Uri getHttpsPrefix() { - return httpsPrefix; - } - } - - WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser) { - uriMatcher = new UriMatcher(null); - this.html5mode = html5mode; - this.parser = parser; - this.protocolHandler = new AndroidProtocolHandler(context.getApplicationContext()); - if (authority != null) { - this.authority = authority; - if (authority.startsWith("localhost")) { - this.isLocal = true; - } else { - this.isLocal = false; - } - - } else { - this.isLocal = true; - this.authority = UUID.randomUUID().toString() + "" + knownUnusedAuthority; - } - } - - private static Uri parseAndVerifyUrl(String url) { - if (url == null) { - return null; - } - Uri uri = Uri.parse(url); - if (uri == null) { - Log.e(TAG, "Malformed URL: " + url); - return null; - } - String path = uri.getPath(); - if (path == null || path.length() == 0) { - Log.e(TAG, "URL does not have a path: " + url); - return null; - } - return uri; - } - - private static WebResourceResponse createWebResourceResponse(String mimeType, String encoding, int statusCode, String reasonPhrase, Map responseHeaders, InputStream data) { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return new WebResourceResponse(mimeType, encoding, statusCode, reasonPhrase, responseHeaders, data); - } else { - return new WebResourceResponse(mimeType, encoding, data); - } - } - - /** - * Attempt to retrieve the WebResourceResponse associated with the given request. - * This method should be invoked from within - * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, - * android.webkit.WebResourceRequest)}. - * - * @param uri the request Uri to process. - * @return a response if the request URL had a matching handler, null if no handler was found. - */ - public WebResourceResponse shouldInterceptRequest(Uri uri) { - PathHandler handler; - synchronized (uriMatcher) { - handler = (PathHandler) uriMatcher.match(uri); - } - if (handler == null) { - return null; - } - - if (this.isLocal) { - Log.d("SERVER", "Handling local request: " + uri.toString()); - return handleLocalRequest(uri, handler); - } else { - return handleProxyRequest(uri, handler); - } - } - - private WebResourceResponse handleLocalRequest(Uri uri, PathHandler handler) { - String path = uri.getPath(); - if (path.equals("/") || (!uri.getLastPathSegment().contains(".") && html5mode)) { - InputStream stream; - String launchURL = parser.getLaunchUrl(); - String launchFile = launchURL.substring(launchURL.lastIndexOf("/") + 1, launchURL.length()); - try { - String startPath = this.basePath + "/" + launchFile; - if (isAsset) { - stream = protocolHandler.openAsset(startPath, ""); - } else { - stream = protocolHandler.openFile(startPath); - } - - } catch (IOException e) { - Log.e(TAG, "Unable to open " + launchFile, e); - return null; - } - - return createWebResourceResponse("text/html", handler.getEncoding(), - handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); - } - - int periodIndex = path.lastIndexOf("."); - if (periodIndex >= 0) { - String ext = path.substring(path.lastIndexOf("."), path.length()); - - InputStream responseStream = new LollipopLazyInputStream(handler, uri); - InputStream stream = responseStream; - - String mimeType = getMimeType(path, stream); - - return createWebResourceResponse(mimeType, handler.getEncoding(), - handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); - } - - return null; - } - - /** - * Instead of reading files from the filesystem/assets, proxy through to the URL - * and let an external server handle it. - * @param uri - * @param handler - * @return - */ - private WebResourceResponse handleProxyRequest(Uri uri, PathHandler handler) { - try { - String path = uri.getPath(); - URL url = new URL(uri.toString()); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("GET"); - conn.setReadTimeout(30 * 1000); - conn.setConnectTimeout(30 * 1000); - - InputStream stream = conn.getInputStream(); - - if (path.equals("/") || (!uri.getLastPathSegment().contains(".") && html5mode)) { - return createWebResourceResponse("text/html", handler.getEncoding(), - handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); - } - - int periodIndex = path.lastIndexOf("."); - if (periodIndex >= 0) { - String ext = path.substring(path.lastIndexOf("."), path.length()); - - // TODO: Conjure up a bit more subtlety than this - if (ext.equals(".html")) { - } - - String mimeType = getMimeType(path, stream); - - return createWebResourceResponse(mimeType, handler.getEncoding(), - handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); - } - - return createWebResourceResponse("", handler.getEncoding(), - handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); - - } catch (SocketTimeoutException ex) { - // bridge.handleAppUrlLoadError(ex); - } catch (Exception ex) { - // bridge.handleAppUrlLoadError(ex); - } - return null; - } - - private String getMimeType(String path, InputStream stream) { - String mimeType = null; - try { - mimeType = URLConnection.guessContentTypeFromName(path); // Does not recognize *.js - if (mimeType != null && path.endsWith(".js") && mimeType.equals("image/x-icon")) { - Log.d(IonicWebViewEngine.TAG, "We shouldn't be here"); - } - if (mimeType == null) { - if (path.endsWith(".js")) { - // Make sure JS files get the proper mimetype to support ES modules - mimeType = "application/javascript"; - } else { - mimeType = URLConnection.guessContentTypeFromStream(stream); - } - } - } catch (Exception ex) { - Log.e(TAG, "Unable to get mime type" + path, ex); - } - return mimeType; - } - - /** - * Registers a handler for the given uri. The handler will be invoked - * every time the shouldInterceptRequest method of the instance is called with - * a matching uri. - * - * @param uri the uri to use the handler for. The scheme and authority (domain) will be matched - * exactly. The path may contain a '*' element which will match a single element of - * a path (so a handler registered for /a/* will be invoked for /a/b and /a/c.html - * but not for /a/b/b) or the '**' element which will match any number of path - * elements. - * @param handler the handler to use for the uri. - */ - void register(Uri uri, PathHandler handler) { - synchronized (uriMatcher) { - uriMatcher.addURI(uri.getScheme(), uri.getAuthority(), uri.getPath(), handler); - } - } - - /** - * Hosts the application's assets on an http(s):// URL. Assets from the local path - * assetPath/... will be available under - * http(s)://{uuid}.androidplatform.net/assets/.... - * - * @param assetPath the local path in the application's asset folder which will be made - * available by the server (for example "/www"). - * @return prefixes under which the assets are hosted. - */ - public AssetHostingDetails hostAssets(String assetPath) { - return hostAssets(authority, assetPath, "", true, true); - } - - - /** - * Hosts the application's assets on an http(s):// URL. Assets from the local path - * assetPath/... will be available under - * http(s)://{uuid}.androidplatform.net/{virtualAssetPath}/.... - * - * @param assetPath the local path in the application's asset folder which will be made - * available by the server (for example "/www"). - * @param virtualAssetPath the path on the local server under which the assets should be hosted. - * @param enableHttp whether to enable hosting using the http scheme. - * @param enableHttps whether to enable hosting using the https scheme. - * @return prefixes under which the assets are hosted. - */ - public AssetHostingDetails hostAssets(final String assetPath, final String virtualAssetPath, - boolean enableHttp, boolean enableHttps) { - return hostAssets(authority, assetPath, virtualAssetPath, enableHttp, - enableHttps); - } - - /** - * Hosts the application's assets on an http(s):// URL. Assets from the local path - * assetPath/... will be available under - * http(s)://{domain}/{virtualAssetPath}/.... - * - * @param domain custom domain on which the assets should be hosted (for example "example.com"). - * @param assetPath the local path in the application's asset folder which will be made - * available by the server (for example "/www"). - * @param virtualAssetPath the path on the local server under which the assets should be hosted. - * @param enableHttp whether to enable hosting using the http scheme. - * @param enableHttps whether to enable hosting using the https scheme. - * @return prefixes under which the assets are hosted. - */ - public AssetHostingDetails hostAssets(final String domain, - final String assetPath, final String virtualAssetPath, - boolean enableHttp, boolean enableHttps) { - this.isAsset = true; - this.basePath = assetPath; - Uri.Builder uriBuilder = new Uri.Builder(); - uriBuilder.scheme(httpScheme); - uriBuilder.authority(domain); - uriBuilder.path(virtualAssetPath); - - if (assetPath.indexOf('*') != -1) { - throw new IllegalArgumentException("assetPath cannot contain the '*' character."); - } - if (virtualAssetPath.indexOf('*') != -1) { - throw new IllegalArgumentException( - "virtualAssetPath cannot contain the '*' character."); - } - - Uri httpPrefix = null; - Uri httpsPrefix = null; - - PathHandler handler = new PathHandler() { - @Override - public InputStream handle(Uri url) { - InputStream stream; - String path = url.getPath().replaceFirst(virtualAssetPath, assetPath); - try { - stream = protocolHandler.openAsset(path, assetPath); - } catch (IOException e) { - Log.e(TAG, "Unable to open asset URL: " + url); - return null; - } - - return stream; - } - }; - - if (enableHttp) { - httpPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpPrefix, "/"), handler); - register(Uri.withAppendedPath(httpPrefix, "**"), handler); - } - if (enableHttps) { - uriBuilder.scheme(httpsScheme); - httpsPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpsPrefix, "/"), handler); - register(Uri.withAppendedPath(httpsPrefix, "**"), handler); - } - return new AssetHostingDetails(httpPrefix, httpsPrefix); - } - - /** - * Hosts the application's resources on an http(s):// URL. Resources - * http(s)://{uuid}.androidplatform.net/res/{resource_type}/{resource_name}. - * - * @return prefixes under which the resources are hosted. - */ - public AssetHostingDetails hostResources() { - return hostResources(authority, "/res", true, true); - } - - /** - * Hosts the application's resources on an http(s):// URL. Resources - * http(s)://{uuid}.androidplatform.net/{virtualResourcesPath}/{resource_type}/{resource_name}. - * - * @param virtualResourcesPath the path on the local server under which the resources - * should be hosted. - * @param enableHttp whether to enable hosting using the http scheme. - * @param enableHttps whether to enable hosting using the https scheme. - * @return prefixes under which the resources are hosted. - */ - public AssetHostingDetails hostResources(final String virtualResourcesPath, boolean enableHttp, - boolean enableHttps) { - return hostResources(authority, virtualResourcesPath, enableHttp, enableHttps); - } - - /** - * Hosts the application's resources on an http(s):// URL. Resources - * http(s)://{domain}/{virtualResourcesPath}/{resource_type}/{resource_name}. - * - * @param domain custom domain on which the assets should be hosted (for example "example.com"). - * If untrusted content is to be loaded into the WebView it is advised to make - * this random. - * @param virtualResourcesPath the path on the local server under which the resources - * should be hosted. - * @param enableHttp whether to enable hosting using the http scheme. - * @param enableHttps whether to enable hosting using the https scheme. - * @return prefixes under which the resources are hosted. - */ - public AssetHostingDetails hostResources(final String domain, - final String virtualResourcesPath, boolean enableHttp, - boolean enableHttps) { - if (virtualResourcesPath.indexOf('*') != -1) { - throw new IllegalArgumentException( - "virtualResourcesPath cannot contain the '*' character."); - } - - Uri.Builder uriBuilder = new Uri.Builder(); - uriBuilder.scheme(httpScheme); - uriBuilder.authority(domain); - uriBuilder.path(virtualResourcesPath); - - Uri httpPrefix = null; - Uri httpsPrefix = null; - - PathHandler handler = new PathHandler() { - @Override - public InputStream handle(Uri url) { - InputStream stream = protocolHandler.openResource(url); - String mimeType = null; - try { - mimeType = URLConnection.guessContentTypeFromStream(stream); - } catch (Exception ex) { - Log.e(TAG, "Unable to get mime type" + url); - } - - return stream; - } - }; - - if (enableHttp) { - httpPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpPrefix, "**"), handler); - } - if (enableHttps) { - uriBuilder.scheme(httpsScheme); - httpsPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpsPrefix, "**"), handler); - } - return new AssetHostingDetails(httpPrefix, httpsPrefix); - } - - - /** - * Hosts the application's files on an http(s):// URL. Files from the basePath - * basePath/... will be available under - * http(s)://{uuid}.androidplatform.net/.... - * - * @param basePath the local path in the application's data folder which will be made - * available by the server (for example "/www"). - * @return prefixes under which the assets are hosted. - */ - public AssetHostingDetails hostFiles(String basePath) { - return hostFiles(basePath, true, true); - } - - public AssetHostingDetails hostFiles(final String basePath, boolean enableHttp, - boolean enableHttps) { - this.isAsset = false; - this.basePath = basePath; - Uri.Builder uriBuilder = new Uri.Builder(); - uriBuilder.scheme(httpScheme); - uriBuilder.authority(authority); - uriBuilder.path(""); - - Uri httpPrefix = null; - Uri httpsPrefix = null; - - PathHandler handler = new PathHandler() { - @Override - public InputStream handle(Uri url) { - InputStream stream; - try { - if (url.getPath().startsWith("/_file_/")) { - stream = protocolHandler.openFile( url.getPath().replace("/_file_/", "")); - } else { - stream = protocolHandler.openFile(basePath + url.getPath()); - } - } catch (IOException e) { - Log.e(TAG, "Unable to open asset URL: " + url); - return null; - } - - String mimeType = null; - try { - mimeType = URLConnection.guessContentTypeFromStream(stream); - } catch (Exception ex) { - Log.e(TAG, "Unable to get mime type" + url); - } - - return stream; - } - }; - - if (enableHttp) { - httpPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpPrefix, "/"), handler); - register(Uri.withAppendedPath(httpPrefix, "**"), handler); - } - if (enableHttps) { - uriBuilder.scheme(httpsScheme); - httpsPrefix = uriBuilder.build(); - register(Uri.withAppendedPath(httpsPrefix, "/"), handler); - register(Uri.withAppendedPath(httpsPrefix, "**"), handler); - } - return new AssetHostingDetails(httpPrefix, httpsPrefix); - } - - /** - * The KitKat WebView reads the InputStream on a separate threadpool. We can use that to - * parallelize loading. - */ - private static abstract class LazyInputStream extends InputStream { - protected final PathHandler handler; - private InputStream is = null; - - public LazyInputStream(PathHandler handler) { - this.handler = handler; - } - - private InputStream getInputStream() { - if (is == null) { - is = handle(); - } - return is; - } - - protected abstract InputStream handle(); - - @Override - public int available() throws IOException { - InputStream is = getInputStream(); - return (is != null) ? is.available() : 0; - } - - @Override - public int read() throws IOException { - InputStream is = getInputStream(); - return (is != null) ? is.read() : -1; - } - - @Override - public int read(byte b[]) throws IOException { - InputStream is = getInputStream(); - return (is != null) ? is.read(b) : -1; - } - - @Override - public int read(byte b[], int off, int len) throws IOException { - InputStream is = getInputStream(); - return (is != null) ? is.read(b, off, len) : -1; - } - - @Override - public long skip(long n) throws IOException { - InputStream is = getInputStream(); - return (is != null) ? is.skip(n) : 0; - } - } - - // For L and above. - private static class LollipopLazyInputStream extends LazyInputStream { - private Uri uri; - private InputStream is; - - public LollipopLazyInputStream(PathHandler handler, Uri uri) { - super(handler); - this.uri = uri; - } - - @Override - protected InputStream handle() { - return handler.handle(uri); - } - } - - public String getBasePath(){ - return this.basePath; - } -} diff --git a/platforms/android/app/src/main/java/com/plugin/datepicker/DatePickerPlugin.java b/platforms/android/app/src/main/java/com/plugin/datepicker/DatePickerPlugin.java deleted file mode 100755 index 6130b9a0..00000000 --- a/platforms/android/app/src/main/java/com/plugin/datepicker/DatePickerPlugin.java +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @author Bikas Vaibhav (http://bikasv.com) 2013 - * Rewrote the plug-in at https://github.com/phonegap/phonegap-plugins/tree/master/Android/DatePicker - * It can now accept `min` and `max` dates for DatePicker. - * - * @author Andre Moraes (https://github.com/andrelsmoraes) - * Refactored code, changed default mode to show date and time dialog. - * Added options `okText`, `cancelText`, `todayText`, `nowText`, `is24Hour`. - * - * @author Diego Silva (https://github.com/diego-silva) - * Added option `titleText`. - */ - -package com.plugin.datepicker; - -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.TimeZone; -import java.util.Random; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.annotation.SuppressLint; -import android.app.DatePickerDialog; -import android.app.DatePickerDialog.OnDateSetListener; -import android.app.TimePickerDialog; -import android.app.TimePickerDialog.OnTimeSetListener; -import android.content.Context; -import android.content.DialogInterface; -import android.os.Build; -import android.util.Log; -import android.widget.DatePicker; -import android.widget.DatePicker.OnDateChangedListener; -import android.widget.TimePicker; - -@SuppressLint("NewApi") -public class DatePickerPlugin extends CordovaPlugin { - - private static final String ACTION_DATE = "date"; - private static final String ACTION_TIME = "time"; - private static final String RESULT_ERROR = "error"; - private static final String RESULT_CANCEL = "cancel"; - private final String pluginName = "DatePickerPlugin"; - - // On some devices, onDateSet or onTimeSet are being called twice - private boolean called = false; - private boolean canceled = false; - - @Override - public boolean execute(final String action, final JSONArray data, final CallbackContext callbackContext) { - Log.d(pluginName, "DatePicker called with options: " + data); - called = false; - canceled = false; - boolean result = false; - - this.show(data, callbackContext); - result = true; - - return result; - } - - public synchronized void show(final JSONArray data, final CallbackContext callbackContext) { - DatePickerPlugin datePickerPlugin = this; - Context currentCtx = cordova.getActivity(); - Runnable runnable; - JsonDate jsonDate = new JsonDate().fromJson(data); - - // Retrieve Android theme - JSONObject options = data.optJSONObject(0); - int theme = options.optInt("androidTheme", 1); - - if (ACTION_TIME.equalsIgnoreCase(jsonDate.action)) { - runnable = runnableTimeDialog(datePickerPlugin, theme, currentCtx, - callbackContext, jsonDate, Calendar.getInstance(TimeZone.getDefault())); - - } else { - runnable = runnableDatePicker(datePickerPlugin, theme, currentCtx, callbackContext, jsonDate); - } - - cordova.getActivity().runOnUiThread(runnable); - } - - private TimePicker timePicker; - private int timePickerHour = 0; - private int timePickerMinute = 0; - - private Runnable runnableTimeDialog(final DatePickerPlugin datePickerPlugin, - final int theme, final Context currentCtx, final CallbackContext callbackContext, - final JsonDate jsonDate, final Calendar calendarDate) { - return new Runnable() { - @Override - public void run() { - final TimeSetListener timeSetListener = new TimeSetListener(datePickerPlugin, callbackContext, calendarDate); - final TimePickerDialog timeDialog = new TimePickerDialog(currentCtx, theme, timeSetListener, jsonDate.hour, - jsonDate.minutes, jsonDate.is24Hour) { - public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { - timePicker = view; - timePickerHour = hourOfDay; - timePickerMinute = minute; - } - }; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - timeDialog.setCancelable(true); - timeDialog.setCanceledOnTouchOutside(false); - - if (!jsonDate.titleText.isEmpty()){ - timeDialog.setTitle(jsonDate.titleText); - } - if (!jsonDate.nowText.isEmpty()){ - timeDialog.setButton(DialogInterface.BUTTON_NEUTRAL, jsonDate.nowText, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (timePicker != null) { - Calendar now = Calendar.getInstance(); - timeSetListener.onTimeSet(timePicker, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE)); - } - } - }); - } - String labelCancel = jsonDate.cancelText.isEmpty() ? currentCtx.getString(android.R.string.cancel) : jsonDate.cancelText; - timeDialog.setButton(DialogInterface.BUTTON_NEGATIVE, labelCancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - canceled = true; - callbackContext.error(RESULT_CANCEL); - } - }); - String labelOk = jsonDate.okText.isEmpty() ? currentCtx.getString(android.R.string.ok) : jsonDate.okText; - timeDialog.setButton(DialogInterface.BUTTON_POSITIVE, labelOk, timeDialog); - } - timeDialog.show(); - timeDialog.updateTime(new Random().nextInt(23), new Random().nextInt(59)); - timeDialog.updateTime(jsonDate.hour, jsonDate.minutes); - } - }; - } - - private Runnable runnableDatePicker( - final DatePickerPlugin datePickerPlugin, - final int theme, final Context currentCtx, - final CallbackContext callbackContext, final JsonDate jsonDate) { - return new Runnable() { - @Override - public void run() { - final DateSetListener dateSetListener = new DateSetListener(datePickerPlugin, theme, callbackContext, jsonDate); - final DatePickerDialog dateDialog = new DatePickerDialog(currentCtx, theme, dateSetListener, jsonDate.year, - jsonDate.month, jsonDate.day); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - prepareDialog(dateDialog, dateSetListener, callbackContext, currentCtx, jsonDate); - } - else { - prepareDialogPreHoneycomb(dateDialog, callbackContext, currentCtx, jsonDate); - } - - dateDialog.show(); - } - }; - } - - private void prepareDialog(final DatePickerDialog dateDialog, final OnDateSetListener dateListener, - final CallbackContext callbackContext, Context currentCtx, JsonDate jsonDate) { - dateDialog.setCancelable(true); - dateDialog.setCanceledOnTouchOutside(false); - if (!jsonDate.titleText.isEmpty()){ - dateDialog.setTitle(jsonDate.titleText); - } - if (!jsonDate.todayText.isEmpty()){ - dateDialog.setButton(DialogInterface.BUTTON_NEUTRAL, jsonDate.todayText, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Calendar now = Calendar.getInstance(); - DatePicker datePicker = dateDialog.getDatePicker(); - dateListener.onDateSet(datePicker, now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH)); - } - }); - } - String labelCancel = jsonDate.cancelText.isEmpty() ? currentCtx.getString(android.R.string.cancel) : jsonDate.cancelText; - dateDialog.setButton(DialogInterface.BUTTON_NEGATIVE, labelCancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - canceled = true; - callbackContext.error(RESULT_CANCEL); - } - }); - String labelOk = jsonDate.okText.isEmpty() ? currentCtx.getString(android.R.string.ok) : jsonDate.okText; - dateDialog.setButton(DialogInterface.BUTTON_POSITIVE, labelOk, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - DatePicker datePicker = dateDialog.getDatePicker(); - datePicker.clearFocus(); - dateListener.onDateSet(datePicker, datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth()); - } - }); - - DatePicker dp = dateDialog.getDatePicker(); - if(jsonDate.minDate > 0) { - dp.setMinDate(jsonDate.minDate); - } - if(jsonDate.maxDate > 0 && jsonDate.maxDate > jsonDate.minDate) { - dp.setMaxDate(jsonDate.maxDate); - } - } - - private void prepareDialogPreHoneycomb(DatePickerDialog dateDialog, - final CallbackContext callbackContext, Context currentCtx, final JsonDate jsonDate){ - java.lang.reflect.Field mDatePickerField = null; - try { - mDatePickerField = dateDialog.getClass().getDeclaredField("mDatePicker"); - } catch (NoSuchFieldException e) { - callbackContext.error(RESULT_ERROR); - } - mDatePickerField.setAccessible(true); - DatePicker pickerView = null; - try { - pickerView = (DatePicker) mDatePickerField.get(dateDialog); - } catch (IllegalArgumentException e) { - callbackContext.error(RESULT_ERROR); - } catch (IllegalAccessException e) { - callbackContext.error(RESULT_ERROR); - } - - final Calendar startDate = Calendar.getInstance(); - startDate.setTimeInMillis(jsonDate.minDate); - final Calendar endDate = Calendar.getInstance(); - endDate.setTimeInMillis(jsonDate.maxDate); - - final int minYear = startDate.get(Calendar.YEAR); - final int minMonth = startDate.get(Calendar.MONTH); - final int minDay = startDate.get(Calendar.DAY_OF_MONTH); - final int maxYear = endDate.get(Calendar.YEAR); - final int maxMonth = endDate.get(Calendar.MONTH); - final int maxDay = endDate.get(Calendar.DAY_OF_MONTH); - - if(startDate !=null || endDate != null) { - pickerView.init(jsonDate.year, jsonDate.month, jsonDate.day, new OnDateChangedListener() { - @Override - public void onDateChanged(DatePicker view, int year, int month, int day) { - if(jsonDate.maxDate > 0 && jsonDate.maxDate > jsonDate.minDate) { - if(year > maxYear || month > maxMonth && year == maxYear || day > maxDay && year == maxYear && month == maxMonth){ - view.updateDate(maxYear, maxMonth, maxDay); - } - } - if(jsonDate.minDate > 0) { - if(year < minYear || month < minMonth && year == minYear || day < minDay && year == minYear && month == minMonth) { - view.updateDate(minYear, minMonth, minDay); - } - } - } - }); - } - } - - private final class DateSetListener implements OnDateSetListener { - private JsonDate jsonDate; - private final DatePickerPlugin datePickerPlugin; - private final CallbackContext callbackContext; - private final int theme; - - private DateSetListener(DatePickerPlugin datePickerPlugin, int theme, CallbackContext callbackContext, JsonDate jsonDate) { - this.datePickerPlugin = datePickerPlugin; - this.callbackContext = callbackContext; - this.jsonDate = jsonDate; - this.theme = theme; - } - - /** - * Return a string containing the date in the format YYYY/MM/DD or call TimeDialog if action != date - */ - @Override - public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) { - if (canceled || called) { - return; - } - called = true; - canceled = false; - - Log.d("onDateSet", "called: " + called); - Log.d("onDateSet", "canceled: " + canceled); - Log.d("onDateSet", "mode: " + jsonDate.action); - - if (ACTION_DATE.equalsIgnoreCase(jsonDate.action)) { - String returnDate = year + "/" + (monthOfYear + 1) + "/" + dayOfMonth; - Log.d("onDateSet", "returnDate: " + returnDate); - - callbackContext.success(returnDate); - - } else { - // Open time dialog - Calendar selectedDate = Calendar.getInstance(); - selectedDate.set(Calendar.YEAR, year); - selectedDate.set(Calendar.MONTH, monthOfYear); - selectedDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); - - cordova.getActivity().runOnUiThread(runnableTimeDialog(datePickerPlugin, theme, cordova.getActivity(), - callbackContext, jsonDate, selectedDate)); - } - } - } - - private final class TimeSetListener implements OnTimeSetListener { - private Calendar calendarDate; - private final CallbackContext callbackContext; - - private TimeSetListener(DatePickerPlugin datePickerPlugin, CallbackContext callbackContext, Calendar selectedDate) { - this.callbackContext = callbackContext; - this.calendarDate = selectedDate != null ? selectedDate : Calendar.getInstance(); - } - - /** - * Return the current date with the time modified as it was set in the - * time picker. - */ - @Override - public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) { - if (canceled) { - return; - } - - calendarDate.set(Calendar.HOUR_OF_DAY, hourOfDay); - calendarDate.set(Calendar.MINUTE, minute); - calendarDate.set(Calendar.SECOND, 0); - - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - String toReturn = sdf.format(calendarDate.getTime()); - - callbackContext.success(toReturn); - } - } - - private final class JsonDate { - - private String action = ACTION_DATE; - private String titleText = ""; - private String okText = ""; - private String cancelText = ""; - private String todayText = ""; - private String nowText = ""; - private long minDate = 0; - private long maxDate = 0; - private int month = 0; - private int day = 0; - private int year = 0; - private int hour = 0; - private int minutes = 0; - private boolean is24Hour = false; - - public JsonDate() { - reset(Calendar.getInstance()); - } - - private void reset(Calendar c) { - year = c.get(Calendar.YEAR); - month = c.get(Calendar.MONTH); - day = c.get(Calendar.DAY_OF_MONTH); - hour = c.get(Calendar.HOUR_OF_DAY); - minutes = c.get(Calendar.MINUTE); - } - - public JsonDate fromJson(JSONArray data) { - try { - JSONObject obj = data.getJSONObject(0); - action = isNotEmpty(obj, "mode") ? obj.getString("mode") - : ACTION_DATE; - - minDate = isNotEmpty(obj, "minDate") ? obj.getLong("minDate") : 0l; - maxDate = isNotEmpty(obj, "maxDate") ? obj.getLong("maxDate") : 0l; - - titleText = isNotEmpty(obj, "titleText") ? obj.getString("titleText") : ""; - okText = isNotEmpty(obj, "okText") ? obj.getString("okText") : ""; - cancelText = isNotEmpty(obj, "cancelText") ? obj - .getString("cancelText") : ""; - todayText = isNotEmpty(obj, "todayText") ? obj - .getString("todayText") : ""; - nowText = isNotEmpty(obj, "nowText") ? obj.getString("nowText") - : ""; - is24Hour = isNotEmpty(obj, "is24Hour") ? obj.getBoolean("is24Hour") - : false; - - String optionDate = obj.getString("date"); - - String[] datePart = optionDate.split("/"); - month = Integer.parseInt(datePart[0]) - 1; - day = Integer.parseInt(datePart[1]); - year = Integer.parseInt(datePart[2]); - hour = Integer.parseInt(datePart[3]); - minutes = Integer.parseInt(datePart[4]); - - } catch (JSONException e) { - reset(Calendar.getInstance()); - } - - return this; - } - - public boolean isNotEmpty(JSONObject object, String key) - throws JSONException { - return object.has(key) - && !object.isNull(key) - && object.get(key).toString().length() > 0 - && !JSONObject.NULL.toString().equals( - object.get(key).toString()); - } - - } - -} diff --git a/platforms/android/app/src/main/java/cordova/plugin/RequestLocationAccuracy.java b/platforms/android/app/src/main/java/cordova/plugin/RequestLocationAccuracy.java deleted file mode 100755 index 65bd1d4c..00000000 --- a/platforms/android/app/src/main/java/cordova/plugin/RequestLocationAccuracy.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package cordova.plugin; - -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaInterface; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.Manifest; -import android.app.Dialog; -import android.content.DialogInterface; -import android.util.Log; -import android.os.Bundle; -import android.app.Activity; -import android.content.Intent; -import android.content.IntentSender; - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.PendingResult; -import com.google.android.gms.common.api.ResultCallback; -import com.google.android.gms.common.api.Status; -import com.google.android.gms.location.LocationRequest; -import com.google.android.gms.location.LocationServices; -import com.google.android.gms.location.LocationSettingsRequest; -import com.google.android.gms.location.LocationSettingsResult; -import com.google.android.gms.location.LocationSettingsStatusCodes; - -import java.lang.reflect.Method; - -public class RequestLocationAccuracy extends CordovaPlugin implements - GoogleApiClient.ConnectionCallbacks, - GoogleApiClient.OnConnectionFailedListener, - ResultCallback { - public static final String TAG = "RequestLocationAccuracy"; - - /** - * Provides the entry point to Google Play services. - */ - protected GoogleApiClient mGoogleApiClient = null; - - /** - * Google API availability - */ - protected GoogleApiAvailability googleApiAvailability; - - - /** - * Stores parameters for requests to the FusedLocationProviderApi. - */ - protected LocationRequest mLocationRequest; - - /** - * Stores the types of location services the client is interested in using. Used for checking - * settings to determine if the device has optimal location settings. - */ - protected LocationSettingsRequest mLocationSettingsRequest; - - /** - * Constant used in the location settings dialog. - */ - protected static final int REQUEST_CHECK_SETTINGS = 0x1; - - /** - * Constant to indicated request for LocationRequest.PRIORITY_NO_POWER - */ - protected static final int REQUEST_PRIORITY_NO_POWER = 0; - - /** - * Constant to indicated request for LocationRequest.PRIORITY_LOW_POWER - */ - protected static final int REQUEST_PRIORITY_LOW_POWER = 1; - - /** - * Constant to indicated request for LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY - */ - protected static final int REQUEST_PRIORITY_BALANCED_POWER_ACCURACY = 2; - - /** - * Constant to indicated request for LocationRequest.HIGH_ACCURACY - */ - protected static final int REQUEST_PRIORITY_HIGH_ACCURACY = 3; - - /** - * Success due to current location settings already satisfying requested - * accuracy - */ - protected static final int SUCCESS_SETTINGS_SATISFIED = 0; - - /** - * Success due to user agreeing to requested accuracy change - */ - protected static final int SUCCESS_USER_AGREED = 1; - - /** - * Error due invalid action requested - */ - protected static final int ERROR_INVALID_ACTION = 0; - - /** - * Error due invalid accuracy requested - */ - protected static final int ERROR_INVALID_ACCURACY = 1; - - /** - * Error due to exception - */ - protected static final int ERROR_EXCEPTION = 2; - - /** - * Error due to not being able to change location accuracy to requested state - */ - protected static final int ERROR_CANNOT_CHANGE_ACCURACY = 3; - - /** - * Error due to user rejecting requested accuracy change - */ - protected static final int ERROR_USER_DISAGREED = 4; - - /** - * Error due to failure to connect to Google Play Services API - */ - protected static final int ERROR_GOOGLE_API_CONNECTION_FAILED = 5; - - /** - * Cordova callback context - */ - protected CallbackContext context = null; - - /** - * Indicates a permanent error, so doesn't recheck since the Google APIs won't invoke the listeners on subsequent calls. - */ - protected ConnectionResult permanentError = null; - - /** - * Constructor. - */ - public RequestLocationAccuracy() {} - - - /** - * Sets the context of the Command. This can then be used to do things like - * get file paths associated with the Activity. - * - * @param cordova The context of the main Activity. - * @param webView The CordovaWebView Cordova is running in. - */ - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - try { - googleApiAvailability = GoogleApiAvailability.getInstance(); - buildGoogleApiClient(); - }catch(Exception e ) { - handleError(e.getMessage(), ERROR_EXCEPTION); - } - } - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback id used when calling back into JavaScript. - * @return True if the action was valid, false if not. - */ - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - boolean result; - context = callbackContext; - try { - if(action.equals("request")) { - result = request(args.getInt(0)); - }else if(action.equals("canRequest")) { - result = canRequest(); - }else { - handleError("Invalid action", ERROR_INVALID_ACTION); - result = false; - } - }catch(Exception e ) { - handleError(e.getMessage(), ERROR_EXCEPTION); - result = false; - } - return result; - } - - public boolean request(int requestedAccuracy) throws Exception{ - if(permanentError != null){ - this.onConnectionFailed(permanentError); - return true; - } - - if(mGoogleApiClient == null){ - handleError("Google Play Services Client failed to initialize", ERROR_GOOGLE_API_CONNECTION_FAILED); - return true; - } - - int priority; - switch(requestedAccuracy){ - case REQUEST_PRIORITY_NO_POWER: - priority = LocationRequest.PRIORITY_NO_POWER; - break; - case REQUEST_PRIORITY_LOW_POWER: - priority = LocationRequest.PRIORITY_LOW_POWER; - break; - case REQUEST_PRIORITY_BALANCED_POWER_ACCURACY: - priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY; - break; - case REQUEST_PRIORITY_HIGH_ACCURACY: - priority = LocationRequest.PRIORITY_HIGH_ACCURACY; - break; - default: - handleError("'"+requestedAccuracy+"' is not a valid accuracy constant", ERROR_INVALID_ACCURACY); - return false; - } - - createLocationRequest(priority); - buildLocationSettingsRequest(); - checkLocationSettings(); - return true; - } - - public boolean canRequest() throws Exception{ - boolean _canRequest = isLocationAuthorized(); - context.success(_canRequest ? 1 : 0); - return true; - } - - private boolean isLocationAuthorized() throws Exception { - boolean authorized = hasPermission(Manifest.permission.ACCESS_FINE_LOCATION) || hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION); - Log.v(TAG, "Location permission is " + (authorized ? "authorized" : "unauthorized")); - return authorized; - } - - private boolean hasPermission(String permission) throws Exception{ - boolean hasPermission = true; - Method method = null; - try { - method = cordova.getClass().getMethod("hasPermission", permission.getClass()); - Boolean bool = (Boolean) method.invoke(cordova, permission); - hasPermission = bool.booleanValue(); - } catch (NoSuchMethodException e) { - Log.w(TAG, "Cordova v" + CordovaWebView.CORDOVA_VERSION + " does not support runtime permissions so defaulting to GRANTED for " + permission); - } - return hasPermission; - } - - protected void handleError(String errorMsg, int errorCode){ - try { - Log.e(TAG, errorMsg); - if(context != null){ - JSONObject error = new JSONObject(); - error.put("message", errorMsg); - error.put("code", errorCode); - context.error(error); - } - } catch (JSONException e) { - Log.e(TAG, e.toString()); - } - } - - protected void handleSuccess(String msg, int code){ - try { - Log.i(TAG, msg); - if(context != null){ - JSONObject success = new JSONObject(); - success.put("message", msg); - success.put("code", code); - context.success(success); - } - } catch (JSONException e) { - handleError(e.getMessage(), ERROR_EXCEPTION); - } - } - - /** - * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the - * LocationServices API. - */ - protected synchronized void buildGoogleApiClient() { - Log.i(TAG, "Building GoogleApiClient"); - mGoogleApiClient = new GoogleApiClient.Builder(this.cordova.getActivity()) - .addConnectionCallbacks(this) - .addOnConnectionFailedListener(this) - .addApi(LocationServices.API) - .build(); - - Log.i(TAG, "Connect Google API client"); - mGoogleApiClient.connect(); - } - - /** - * Sets up the location request. Android has two location request settings: - * {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control - * the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in - * the AndroidManifest.xml. - *

- * When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update - * interval (5 seconds), the Fused Location Provider API returns location updates that are - * accurate to within a few feet. - *

- * These settings are appropriate for mapping applications that show real-time location - * updates. - */ - protected void createLocationRequest(int priority) { - Log.i(TAG, "Create location request"); - mLocationRequest = new LocationRequest(); - mLocationRequest.setPriority(priority); - } - - /** - * Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build - * a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking - * if a device has the needed location settings. - */ - protected void buildLocationSettingsRequest() { - Log.i(TAG, "Build location settings request"); - LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); - builder.addLocationRequest(mLocationRequest); - builder.setAlwaysShow(true); - mLocationSettingsRequest = builder.build(); - } - - /** - * Check if the device's location settings are adequate for the app's needs using the - * {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient, - * LocationSettingsRequest)} method, with the results provided through a {@code PendingResult}. - */ - protected void checkLocationSettings() { - Log.i(TAG, "Check location settings"); - PendingResult result = - LocationServices.SettingsApi.checkLocationSettings( - mGoogleApiClient, - mLocationSettingsRequest - ); - result.setResultCallback(this); - } - - /** - * The callback invoked when - * {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient, - * LocationSettingsRequest)} is called. Examines the - * {@link com.google.android.gms.location.LocationSettingsResult} object and determines if - * location settings are adequate. If they are not, begins the process of presenting a location - * settings dialog to the user. - */ - @Override - public void onResult(LocationSettingsResult locationSettingsResult) { - Log.i(TAG, "onResult()"); - final Status status = locationSettingsResult.getStatus(); - switch (status.getStatusCode()) { - case LocationSettingsStatusCodes.SUCCESS: - String msg = "All location settings are satisfied."; - Log.i(TAG, msg); - handleSuccess(msg, SUCCESS_SETTINGS_SATISFIED); - break; - case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: - Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings "); - try { - // Show the dialog by calling startResolutionForResult(), and check the result - // in onActivityResult(). - this.cordova.setActivityResultCallback(this); - status.startResolutionForResult(this.cordova.getActivity(), REQUEST_CHECK_SETTINGS); - } catch (IntentSender.SendIntentException e) { - handleError("PendingIntent unable to execute request: ".concat(e.getMessage()), ERROR_CANNOT_CHANGE_ACCURACY); - } - break; - case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: - handleError("Location settings are inadequate, and cannot be fixed here. Dialog not created.", ERROR_CANNOT_CHANGE_ACCURACY); - break; - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - Log.i(TAG, "onActivityResult()"); - switch (requestCode) { - // Check for the integer request code originally supplied to startResolutionForResult(). - case REQUEST_CHECK_SETTINGS: - switch (resultCode) { - case Activity.RESULT_OK: - String msg = "User agreed to make required location settings changes."; - Log.i(TAG, msg); - handleSuccess(msg, SUCCESS_USER_AGREED); - break; - case Activity.RESULT_CANCELED: - handleError("User chose not to make required location settings changes.", ERROR_USER_DISAGREED); - break; - } - break; - } - } - - /** - * Runs when a GoogleApiClient object successfully connects. - */ - @Override - public void onConnected(Bundle connectionHint) { - Log.i(TAG, "Connected to GoogleApiClient"); - } - - @Override - public void onConnectionSuspended(int cause) { - Log.i(TAG, "Connection suspended"); - } - - @Override - public void onStart() { - Log.i(TAG, "On start"); - super.onStart(); - } - - @Override - public void onDestroy() { - Log.i(TAG, "On onDestroy"); - if(mGoogleApiClient != null){ - super.onStop(); - Log.i(TAG, "Disconnect Google API client"); - try { - mGoogleApiClient.disconnect(); - }catch(Exception e ) { - handleError(e.getMessage(), ERROR_EXCEPTION); - } - } - } - - @Override - public void onConnectionFailed(ConnectionResult result) { - // https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult - permanentError = result; - String reason; - switch (result.getErrorCode()){ - case ConnectionResult.API_UNAVAILABLE: - reason = "One of the API components you attempted to connect to is not available."; - break; - case ConnectionResult.CANCELED: - reason = "The connection was canceled."; - break; - case ConnectionResult.DEVELOPER_ERROR: - reason = "The application is misconfigured."; - break; - case ConnectionResult.INTERNAL_ERROR: - reason = "An internal error occurred."; - break; - case ConnectionResult.INTERRUPTED: - reason = "An interrupt occurred while waiting for the connection complete."; - break; - case ConnectionResult.INVALID_ACCOUNT: - reason = "he client attempted to connect to the service with an invalid account name specified."; - break; - case ConnectionResult.LICENSE_CHECK_FAILED: - reason = "The application is not licensed to the user."; - break; - case ConnectionResult.NETWORK_ERROR: - reason = "A network error occurred."; - break; - case ConnectionResult.RESOLUTION_REQUIRED: - reason = "Completing the connection requires some form of resolution."; - break; - case ConnectionResult.SERVICE_DISABLED: - reason = "The installed version of Google Play services has been disabled on this device."; - break; - case ConnectionResult.SERVICE_INVALID: - reason = "The version of the Google Play services installed on this device is not authentic."; - break; - case ConnectionResult.SERVICE_MISSING: - reason = "Google Play services is missing on this device."; - break; - case ConnectionResult.SERVICE_MISSING_PERMISSION: - reason = "Google Play service doesn't have one or more required permissions."; - break; - case ConnectionResult.SERVICE_UPDATING: - reason = "Google Play service is currently being updated on this device."; - break; - case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: - reason = "The installed version of Google Play services is out of date."; - break; - case ConnectionResult.SIGN_IN_FAILED: - reason = "The client attempted to connect to the service but the user is not signed in."; - break; - case ConnectionResult.SIGN_IN_REQUIRED: - reason = "The client attempted to connect to the service but the user is not signed in."; - break; - case ConnectionResult.TIMEOUT: - reason = "The timeout was exceeded while waiting for the connection to complete."; - break; - default: - reason = "Unknown reason"; - } - handleError("Failed to connect to Google Play Services: ".concat(reason), ERROR_GOOGLE_API_CONNECTION_FAILED); - - int status = googleApiAvailability.isGooglePlayServicesAvailable(cordova.getActivity().getApplicationContext()); - if (googleApiAvailability.isUserResolvableError (status)) { - Dialog dialog = googleApiAvailability.getErrorDialog(cordova.getActivity(),status, 0); - dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - cordova.getActivity().finish(); - } - }); - dialog.show(); - permanentError = null; - } - } -} \ No newline at end of file diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java deleted file mode 100755 index 98332b95..00000000 --- a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (C) https://github.com/mjwheatley/cordova-plugin-android-fingerprint-auth - * Modifications copyright (C) 2016 Niklas Merz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package de.niklasmerz.cordova.fingerprint; - -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaInterface; - -import android.annotation.TargetApi; -import android.app.FragmentTransaction; -import android.app.KeyguardManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Bundle; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyPermanentlyInvalidatedException; -import android.security.keystore.KeyProperties; -import android.util.Base64; -import android.util.DisplayMetrics; -import android.util.Log; - -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.util.Locale; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.KeyGenerator; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; - -@TargetApi(23) -public class Fingerprint extends CordovaPlugin { - - public static final String TAG = "Fingerprint"; - public static String packageName; - - private static final String DIALOG_FRAGMENT_TAG = "FpAuthDialog"; - private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; - - KeyguardManager mKeyguardManager; - FingerprintAuthenticationDialogFragment mFragment; - public static KeyStore mKeyStore; - public static KeyGenerator mKeyGenerator; - public static Cipher mCipher; - private FingerprintManager mFingerPrintManager; - - public static CallbackContext mCallbackContext; - public static PluginResult mPluginResult; - - /** - * Alias for our key in the Android Key Store - */ - private static String mClientId; - /** - * Used to encrypt token - */ - private static String mClientSecret; - - /** - * Options - */ - private static boolean mDisableBackup = false; - - /** - * Constructor. - */ - public Fingerprint() { - } - - /** - * Sets the context of the Command. This can then be used to do things like - * get file paths associated with the Activity. - * - * @param cordova The context of the main Activity. - * @param webView The CordovaWebView Cordova is running in. - */ - - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - Log.v(TAG, "Init Fingerprint"); - packageName = cordova.getActivity().getApplicationContext().getPackageName(); - mPluginResult = new PluginResult(PluginResult.Status.NO_RESULT); - - if (android.os.Build.VERSION.SDK_INT < 23) { - return; - } - - mKeyguardManager = cordova.getActivity().getSystemService(KeyguardManager.class); - mFingerPrintManager = cordova.getActivity().getApplicationContext() - .getSystemService(FingerprintManager.class); - - try { - mKeyGenerator = KeyGenerator.getInstance( - KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE); - mKeyStore = KeyStore.getInstance(ANDROID_KEY_STORE); - - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Failed to get an instance of KeyGenerator", e); - } catch (NoSuchProviderException e) { - throw new RuntimeException("Failed to get an instance of KeyGenerator", e); - } catch (KeyStoreException e) { - throw new RuntimeException("Failed to get an instance of KeyStore", e); - } - - try { - mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" - + KeyProperties.BLOCK_MODE_CBC + "/" - + KeyProperties.ENCRYPTION_PADDING_PKCS7); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Failed to get an instance of Cipher", e); - } catch (NoSuchPaddingException e) { - throw new RuntimeException("Failed to get an instance of Cipher", e); - } - } - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback id used when calling back into JavaScript. - * @return A PluginResult object with a status and message. - */ - public boolean execute(final String action, - JSONArray args, - CallbackContext callbackContext) throws JSONException { - mCallbackContext = callbackContext; - Log.v(TAG, "Fingerprint action: " + action); - if (android.os.Build.VERSION.SDK_INT < 23) { - Log.e(TAG, "minimum SDK version 23 required"); - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - mCallbackContext.error("minimum SDK version 23 required"); - mCallbackContext.sendPluginResult(mPluginResult); - return true; - } - - final JSONObject arg_object = args.getJSONObject(0); - - if (action.equals("authenticate")) { - if (!arg_object.has("clientId") || !arg_object.has("clientSecret")) { - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - mCallbackContext.error("Missing required parameters"); - mCallbackContext.sendPluginResult(mPluginResult); - return true; - } - mClientId = arg_object.getString("clientId"); - mClientSecret = arg_object.getString("clientSecret"); - if (arg_object.has("disableBackup")) { - mDisableBackup = arg_object.getBoolean("disableBackup"); - } - // Set language - Resources res = cordova.getActivity().getResources(); - // Change locale settings in the app. - DisplayMetrics dm = res.getDisplayMetrics(); - Configuration conf = res.getConfiguration(); - //Do not change locale - res.updateConfiguration(conf, dm); - - if (isFingerprintAuthAvailable()) { - SecretKey key = getSecretKey(); - boolean isCipherInit = true; - if (key == null) { - if (createKey()) { - key = getSecretKey(); - } - } - if (key != null && !initCipher()) { - isCipherInit = false; - } - if (key != null) { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - // Set up the crypto object for later. The object will be authenticated by use - // of the fingerprint. - mFragment = new FingerprintAuthenticationDialogFragment(); - Bundle bundle = new Bundle(); - bundle.putBoolean("disableBackup", mDisableBackup); - mFragment.setArguments(bundle); - - if (initCipher()) { - mFragment.setCancelable(false); - // Show the fingerprint dialog. The user has the option to use the fingerprint with - // crypto, or you can fall back to using a server-side verified password. - mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher)); - FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction(); - transaction.add(mFragment, DIALOG_FRAGMENT_TAG); - transaction.commitAllowingStateLoss(); - } else { - if (!mDisableBackup) { - // This happens if the lock screen has been disabled or or a fingerprint got - // enrolled. Thus show the dialog to authenticate with their password - mFragment.setCryptoObject(new FingerprintManager - .CryptoObject(mCipher)); - mFragment.setStage(FingerprintAuthenticationDialogFragment - .Stage.NEW_FINGERPRINT_ENROLLED); - FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction(); - transaction.add(mFragment, DIALOG_FRAGMENT_TAG); - transaction.commitAllowingStateLoss(); - } else { - mCallbackContext.error("Failed to init Cipher and backup disabled."); - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - mCallbackContext.sendPluginResult(mPluginResult); - } - } - } - }); - mPluginResult.setKeepCallback(true); - } else { - mCallbackContext.sendPluginResult(mPluginResult); - } - - } else { - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - mCallbackContext.error("Fingerprint authentication not available"); - mCallbackContext.sendPluginResult(mPluginResult); - } - return true; - } else if (action.equals("isAvailable")) { - if(isFingerprintAuthAvailable() && mFingerPrintManager.isHardwareDetected() && mFingerPrintManager.hasEnrolledFingerprints()){ - mPluginResult = new PluginResult(PluginResult.Status.OK, "finger"); - mCallbackContext.success("finger"); - }else{ - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - mCallbackContext.error("Fingerprint authentication not ready"); - } - mCallbackContext.sendPluginResult(mPluginResult); - return true; - } - return false; - } - - private boolean isFingerprintAuthAvailable() { - return mFingerPrintManager.isHardwareDetected() - && mFingerPrintManager.hasEnrolledFingerprints(); - } - - /** - * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()} - * method. - * - * @return {@code true} if initialization is successful, {@code false} if the lock screen has - * been disabled or reset after the key was generated, or if a fingerprint got enrolled after - * the key was generated. - */ - private static boolean initCipher() { - boolean initCipher = false; - String errorMessage = ""; - String initCipherExceptionErrorPrefix = "Failed to init Cipher: "; - try { - SecretKey key = getSecretKey(); - mCipher.init(Cipher.ENCRYPT_MODE, key); - initCipher = true; - } catch (InvalidKeyException e) { - errorMessage = initCipherExceptionErrorPrefix + "InvalidKeyException: " + e.toString(); - - } - if (!initCipher) { - Log.e(TAG, errorMessage); - createKey(); - } - return initCipher; - } - - private static SecretKey getSecretKey() { - String errorMessage = ""; - String getSecretKeyExceptionErrorPrefix = "Failed to get SecretKey from KeyStore: "; - SecretKey key = null; - try { - mKeyStore.load(null); - key = (SecretKey) mKeyStore.getKey(mClientId, null); - } catch (KeyStoreException e) { - errorMessage = getSecretKeyExceptionErrorPrefix - + "KeyStoreException: " + e.toString();; - } catch (CertificateException e) { - errorMessage = getSecretKeyExceptionErrorPrefix - + "CertificateException: " + e.toString();; - } catch (UnrecoverableKeyException e) { - errorMessage = getSecretKeyExceptionErrorPrefix - + "UnrecoverableKeyException: " + e.toString();; - } catch (IOException e) { - errorMessage = getSecretKeyExceptionErrorPrefix - + "IOException: " + e.toString();; - } catch (NoSuchAlgorithmException e) { - errorMessage = getSecretKeyExceptionErrorPrefix - + "NoSuchAlgorithmException: " + e.toString();; - } - if (key == null) { - Log.e(TAG, errorMessage); - } - return key; - } - - /** - * Creates a symmetric key in the Android Key Store which can only be used after the user has - * authenticated with fingerprint. - */ - public static boolean createKey() { - String errorMessage = ""; - String createKeyExceptionErrorPrefix = "Failed to create key: "; - boolean isKeyCreated = false; - // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint - // for your flow. Use of keys is necessary if you need to know if the set of - // enrolled fingerprints has changed. - try { - mKeyStore.load(null); - // Set the alias of the entry in Android KeyStore where the key will appear - // and the constrains (purposes) in the constructor of the Builder - mKeyGenerator.init(new KeyGenParameterSpec.Builder(mClientId, - KeyProperties.PURPOSE_ENCRYPT | - KeyProperties.PURPOSE_DECRYPT) - .setBlockModes(KeyProperties.BLOCK_MODE_CBC) - // Require the user to authenticate with a fingerprint to authorize every use - // of the key - .setUserAuthenticationRequired(true) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) - .build()); - mKeyGenerator.generateKey(); - isKeyCreated = true; - } catch (NoSuchAlgorithmException e) { - errorMessage = createKeyExceptionErrorPrefix - + "NoSuchAlgorithmException: " + e.toString();; - } catch (InvalidAlgorithmParameterException e) { - errorMessage = createKeyExceptionErrorPrefix - + "InvalidAlgorithmParameterException: " + e.toString();; - } catch (CertificateException e) { - errorMessage = createKeyExceptionErrorPrefix - + "CertificateException: " + e.toString();; - } catch (IOException e) { - errorMessage = createKeyExceptionErrorPrefix - + "IOException: " + e.toString();; - } - if (!isKeyCreated) { - Log.e(TAG, errorMessage); - setPluginResultError(errorMessage); - } - return isKeyCreated; - } - - public static void onAuthenticated(boolean withFingerprint) { - JSONObject resultJson = new JSONObject(); - String errorMessage = ""; - boolean createdResultJson = false; - try { - - if (withFingerprint) { - // If the user has authenticated with fingerprint, verify that using cryptography and - // then return the encrypted token - byte[] encrypted = tryEncrypt(); - resultJson.put("withFingerprint", Base64.encodeToString(encrypted, 0 /* flags */)); - } else { - // Authentication happened with backup password. - resultJson.put("withPassword", true); - - // if failed to init cipher because of InvalidKeyException, create new key - if (!initCipher()) { - createKey(); - } - } - createdResultJson = true; - } catch (BadPaddingException e) { - errorMessage = "Failed to encrypt the data with the generated key:" + - " BadPaddingException: " + e.getMessage(); - Log.e(TAG, errorMessage); - } catch (IllegalBlockSizeException e) { - errorMessage = "Failed to encrypt the data with the generated key: " + - "IllegalBlockSizeException: " + e.getMessage(); - Log.e(TAG, errorMessage); - } catch (JSONException e) { - errorMessage = "Failed to set resultJson key value pair: " + e.getMessage(); - Log.e(TAG, errorMessage); - } - - if (createdResultJson) { - mCallbackContext.success(resultJson); - mPluginResult = new PluginResult(PluginResult.Status.OK); - } else { - mCallbackContext.error(errorMessage); - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - } - mCallbackContext.sendPluginResult(mPluginResult); - } - - public static void onCancelled() { - mCallbackContext.error("Cancelled"); - } - - /** - * Tries to encrypt some data with the generated key in {@link #createKey} which is - * only works if the user has just authenticated via fingerprint. - */ - private static byte[] tryEncrypt() throws BadPaddingException, IllegalBlockSizeException { - return mCipher.doFinal(mClientSecret.getBytes()); - } - - public static boolean setPluginResultError(String errorMessage) { - mCallbackContext.error(errorMessage); - mPluginResult = new PluginResult(PluginResult.Status.ERROR); - return false; - } -} \ No newline at end of file diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java deleted file mode 100755 index e06c5e06..00000000 --- a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * Modifications copyright (C) 2016 Niklas Merz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package de.niklasmerz.cordova.fingerprint; - -import android.app.DialogFragment; -import android.app.KeyguardManager; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -/** - * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password - * authentication if fingerprint is not available. - */ -public class FingerprintAuthenticationDialogFragment extends DialogFragment - implements FingerprintUiHelper.Callback { - - private static final String TAG = "FingerprintAuthDialog"; - private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1; - - private Button mCancelButton; - private Button mSecondDialogButton; - private View mFingerprintContent; - - private Stage mStage = Stage.FINGERPRINT; - - private KeyguardManager mKeyguardManager; - private FingerprintManager.CryptoObject mCryptoObject; - private FingerprintUiHelper mFingerprintUiHelper; - FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder; - - boolean disableBackup; - - public FingerprintAuthenticationDialogFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Do not create a new Fragment when the Activity is re-created such as orientation changes. - setRetainInstance(true); - setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog); - - mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); - mFingerprintUiHelperBuilder = new FingerprintUiHelper.FingerprintUiHelperBuilder( - getContext(), getContext().getSystemService(FingerprintManager.class)); - - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - Bundle args = getArguments(); - disableBackup = args.getBoolean("disableBackup"); - Log.d(TAG, "disableBackup: " + disableBackup); - - int fingerprint_auth_dialog_title_id = getResources() - .getIdentifier("fingerprint_auth_dialog_title", "string", - Fingerprint.packageName); - getDialog().setTitle(getString(fingerprint_auth_dialog_title_id)); - int fingerprint_dialog_container_id = getResources() - .getIdentifier("fingerprint_dialog_container", "layout", - Fingerprint.packageName); - View v = inflater.inflate(fingerprint_dialog_container_id, container, false); - int cancel_button_id = getResources() - .getIdentifier("cancel_button", "id", Fingerprint.packageName); - mCancelButton = (Button) v.findViewById(cancel_button_id); - mCancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Fingerprint.onCancelled(); - dismiss(); - } - }); - - int second_dialog_button_id = getResources() - .getIdentifier("second_dialog_button", "id", Fingerprint.packageName); - mSecondDialogButton = (Button) v.findViewById(second_dialog_button_id); - if (disableBackup) { - mSecondDialogButton.setVisibility(View.GONE); - } - mSecondDialogButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - goToBackup(); - } - }); - int fingerprint_container_id = getResources() - .getIdentifier("fingerprint_container", "id", Fingerprint.packageName); - mFingerprintContent = v.findViewById(fingerprint_container_id); - - int new_fingerprint_enrolled_description_id = getResources() - .getIdentifier("new_fingerprint_enrolled_description", "id", - Fingerprint.packageName); - - int fingerprint_icon_id = getResources() - .getIdentifier("fingerprint_icon", "id", Fingerprint.packageName); - int fingerprint_status_id = getResources() - .getIdentifier("fingerprint_status", "id", Fingerprint.packageName); - mFingerprintUiHelper = mFingerprintUiHelperBuilder.build( - (ImageView) v.findViewById(fingerprint_icon_id), - (TextView) v.findViewById(fingerprint_status_id), this); - updateStage(); - - // If fingerprint authentication is not available, switch immediately to the backup - // (password) screen. - if (!mFingerprintUiHelper.isFingerprintAuthAvailable()) { - goToBackup(); - } - return v; - } - - - @Override - public void onResume() { - super.onResume(); - if (mStage == Stage.FINGERPRINT) { - mFingerprintUiHelper.startListening(mCryptoObject); - } - } - - public void setStage(Stage stage) { - mStage = stage; - } - - @Override - public void onPause() { - super.onPause(); - mFingerprintUiHelper.stopListening(); - } - - /** - * Sets the crypto object to be passed in when authenticating with fingerprint. - */ - public void setCryptoObject(FingerprintManager.CryptoObject cryptoObject) { - mCryptoObject = cryptoObject; - } - - /** - * Switches to backup (password) screen. This either can happen when fingerprint is not - * available or the user chooses to use the password authentication method by pressing the - * button. This can also happen when the user had too many fingerprint attempts. - */ - private void goToBackup() { - if(disableBackup) - { - Fingerprint.onCancelled(); - dismiss(); - } - else{ - mStage = Stage.BACKUP; - updateStage(); - } - } - - private void updateStage() { - int cancel_id = getResources() - .getIdentifier("fingerprint_cancel", "string", Fingerprint.packageName); - switch (mStage) { - case FINGERPRINT: - mCancelButton.setText(cancel_id); - int use_backup_id = getResources() - .getIdentifier("fingerprint_use_backup", "string", Fingerprint.packageName); - mSecondDialogButton.setText(use_backup_id); - mFingerprintContent.setVisibility(View.VISIBLE); - break; - case NEW_FINGERPRINT_ENROLLED: - // Intentional fall through - case BACKUP: - if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) { - - } - if (!mKeyguardManager.isKeyguardSecure()) { - // Show a message that the user hasn't set up a lock screen. - int secure_lock_screen_required_id = getResources() - .getIdentifier("secure_lock_screen_required", "string", - Fingerprint.packageName); - Toast.makeText(getContext(), - getString(secure_lock_screen_required_id), - Toast.LENGTH_LONG).show(); - return; - } - showAuthenticationScreen(); - break; - } - } - - private void showAuthenticationScreen() { - // Create the Confirm Credentials screen. You can customize the title and description. Or - // we will provide a generic one for you if you leave it null - Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null); - if (intent != null) { - startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS); - } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) { - // Challenge completed, proceed with using cipher - if (resultCode == getActivity().RESULT_OK) { - Fingerprint.onAuthenticated(false /* used backup */); - } else { - // The user canceled or didn’t complete the lock screen - // operation. Go to error/cancellation flow. - Fingerprint.onCancelled(); - } - dismiss(); - } - } - - @Override - public void onAuthenticated() { - // Callback from FingerprintUiHelper. Let the activity know that authentication was - // successful. - Fingerprint.onAuthenticated(true /* withFingerprint */); - dismiss(); - } - - @Override - public void onError() { - if(this.getActivity() != null) - goToBackup(); - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - Fingerprint.onCancelled(); - } - - /** - * Enumeration to indicate which authentication method the user is trying to authenticate with. - */ - public enum Stage { - FINGERPRINT, - NEW_FINGERPRINT_ENROLLED, - BACKUP - } -} diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java deleted file mode 100755 index e1402c58..00000000 --- a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * Modifications copyright (C) 2016 Niklas Merz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package de.niklasmerz.cordova.fingerprint; - -import android.annotation.TargetApi; -import android.content.Context; -import android.hardware.fingerprint.FingerprintManager; -import android.os.CancellationSignal; -import android.widget.ImageView; -import android.widget.TextView; - - -/** - * Small helper class to manage text/icon around fingerprint authentication UI. - */ -@TargetApi(23) -public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback { - - static final long ERROR_TIMEOUT_MILLIS = 1600; - static final long SUCCESS_DELAY_MILLIS = 1300; - - private final Context mContext; - private final FingerprintManager mFingerprintManager; - private final ImageView mIcon; - private final TextView mErrorTextView; - private final Callback mCallback; - private CancellationSignal mCancellationSignal; - - boolean mSelfCancelled; - - /** - * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger - * holds its fields and takes other arguments in the {@link #build} method. - */ - public static class FingerprintUiHelperBuilder { - private final FingerprintManager mFingerPrintManager; - private final Context mContext; - - public FingerprintUiHelperBuilder(Context context, FingerprintManager fingerprintManager) { - mFingerPrintManager = fingerprintManager; - mContext = context; - } - - public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) { - return new FingerprintUiHelper(mContext, mFingerPrintManager, icon, errorTextView, - callback); - } - } - - /** - * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from - * only the {@link FingerprintUiHelperBuilder} class. - */ - private FingerprintUiHelper(Context context, FingerprintManager fingerprintManager, - ImageView icon, TextView errorTextView, Callback callback) { - mFingerprintManager = fingerprintManager; - mIcon = icon; - mErrorTextView = errorTextView; - mCallback = callback; - mContext = context; - } - - public boolean isFingerprintAuthAvailable() { - return mFingerprintManager.isHardwareDetected() - && mFingerprintManager.hasEnrolledFingerprints(); - } - - public void startListening(FingerprintManager.CryptoObject cryptoObject) { - if (!isFingerprintAuthAvailable()) { - return; - } - mCancellationSignal = new CancellationSignal(); - mSelfCancelled = false; - mFingerprintManager - .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null); - - int ic_fp_40px_id = mContext.getResources() - .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName); - mIcon.setImageResource(ic_fp_40px_id); - } - - public void stopListening() { - if (mCancellationSignal != null) { - mSelfCancelled = true; - mCancellationSignal.cancel(); - mCancellationSignal = null; - } - } - - @Override - public void onAuthenticationError(int errMsgId, CharSequence errString) { - if (!mSelfCancelled) { - showError(errString); - mIcon.postDelayed(new Runnable() { - @Override - public void run() { - mCallback.onError(); - } - }, ERROR_TIMEOUT_MILLIS); - } - } - - @Override - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { - showError(helpString); - } - - @Override - public void onAuthenticationFailed() { - int fingerprint_not_recognized_id = mContext.getResources() - .getIdentifier("fingerprint_not_recognized", "string", Fingerprint.packageName); - showError(mIcon.getResources().getString( - fingerprint_not_recognized_id)); - } - - @Override - public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { - mErrorTextView.removeCallbacks(mResetErrorTextRunnable); - int ic_fingerprint_success_id = mContext.getResources() - .getIdentifier("ic_fingerprint_success", "drawable", Fingerprint.packageName); - mIcon.setImageResource(ic_fingerprint_success_id); - int success_color_id = mContext.getResources() - .getIdentifier("success_color", "color", Fingerprint.packageName); - mErrorTextView.setTextColor( - mErrorTextView.getResources().getColor(success_color_id, null)); - int fingerprint_success_id = mContext.getResources() - .getIdentifier("fingerprint_success", "string", Fingerprint.packageName); - mErrorTextView.setText( - mErrorTextView.getResources().getString(fingerprint_success_id)); - mIcon.postDelayed(new Runnable() { - @Override - public void run() { - mCallback.onAuthenticated(); - } - }, SUCCESS_DELAY_MILLIS); - } - - private void showError(CharSequence error) { - int ic_fingerprint_error_id = mContext.getResources() - .getIdentifier("ic_fingerprint_error", "drawable", Fingerprint.packageName); - mIcon.setImageResource(ic_fingerprint_error_id); - mErrorTextView.setText(error); - int warning_color_id = mContext.getResources() - .getIdentifier("warning_color", "color", Fingerprint.packageName); - mErrorTextView.setTextColor( - mErrorTextView.getResources().getColor(warning_color_id, null)); - mErrorTextView.removeCallbacks(mResetErrorTextRunnable); - mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS); - } - - Runnable mResetErrorTextRunnable = new Runnable() { - @Override - public void run() { - int hint_color_id = mContext.getResources() - .getIdentifier("hint_color", "color", Fingerprint.packageName); - mErrorTextView.setTextColor( - mErrorTextView.getResources().getColor(hint_color_id, null)); - int fingerprint_hint_id = mContext.getResources() - .getIdentifier("fingerprint_hint", "string", Fingerprint.packageName); - mErrorTextView.setText( - mErrorTextView.getResources().getString(fingerprint_hint_id)); - int ic_fp_40px_id = mContext.getResources() - .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName); - mIcon.setImageResource(ic_fp_40px_id); - } - }; - - public interface Callback { - - void onAuthenticated(); - - void onError(); - } -} diff --git a/platforms/android/app/src/main/java/io/ionic/keyboard/IonicKeyboard.java b/platforms/android/app/src/main/java/io/ionic/keyboard/IonicKeyboard.java deleted file mode 100755 index 3abd5f80..00000000 --- a/platforms/android/app/src/main/java/io/ionic/keyboard/IonicKeyboard.java +++ /dev/null @@ -1,134 +0,0 @@ -package io.ionic.keyboard; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.PluginResult; -import org.apache.cordova.PluginResult.Status; -import org.json.JSONArray; -import org.json.JSONException; - -import android.content.Context; -import android.graphics.Rect; -import android.util.DisplayMetrics; -import android.view.View; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; -import android.view.inputmethod.InputMethodManager; - -// import additionally required classes for calculating screen height -import android.view.Display; -import android.graphics.Point; -import android.os.Build; - -public class IonicKeyboard extends CordovaPlugin { - private OnGlobalLayoutListener list; - private View rootView; - - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - } - - public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { - if ("hide".equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - //http://stackoverflow.com/a/7696791/1091751 - InputMethodManager inputManager = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - View v = cordova.getActivity().getCurrentFocus(); - - if (v == null) { - callbackContext.error("No current focus"); - } else { - inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - callbackContext.success(); // Thread-safe. - } - } - }); - return true; - } - if ("show".equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - ((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); - callbackContext.success(); // Thread-safe. - } - }); - return true; - } - if ("init".equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - //calculate density-independent pixels (dp) - //http://developer.android.com/guide/practices/screens_support.html - DisplayMetrics dm = new DisplayMetrics(); - cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - final float density = dm.density; - - //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing - rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView(); - list = new OnGlobalLayoutListener() { - int previousHeightDiff = 0; - @Override - public void onGlobalLayout() { - Rect r = new Rect(); - //r will be populated with the coordinates of your view that area still visible. - rootView.getWindowVisibleDisplayFrame(r); - - PluginResult result; - - // cache properties for later use - int rootViewHeight = rootView.getRootView().getHeight(); - int resultBottom = r.bottom; - - // calculate screen height differently for android versions >= 21: Lollipop 5.x, Marshmallow 6.x - //http://stackoverflow.com/a/29257533/3642890 beware of nexus 5 - int screenHeight; - - if (Build.VERSION.SDK_INT >= 21) { - Display display = cordova.getActivity().getWindowManager().getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - screenHeight = size.y; - } else { - screenHeight = rootViewHeight; - } - - int heightDiff = screenHeight - resultBottom; - - int pixelHeightDiff = (int)(heightDiff / density); - if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard... - String msg = "S" + Integer.toString(pixelHeightDiff); - result = new PluginResult(PluginResult.Status.OK, msg); - result.setKeepCallback(true); - callbackContext.sendPluginResult(result); - } - else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){ - String msg = "H"; - result = new PluginResult(PluginResult.Status.OK, msg); - result.setKeepCallback(true); - callbackContext.sendPluginResult(result); - } - previousHeightDiff = pixelHeightDiff; - } - }; - - rootView.getViewTreeObserver().addOnGlobalLayoutListener(list); - - - PluginResult dataResult = new PluginResult(PluginResult.Status.OK); - dataResult.setKeepCallback(true); - callbackContext.sendPluginResult(dataResult); - } - }); - return true; - } - return false; // Returning false results in a "MethodNotFound" error. - } - - @Override - public void onDestroy() { - rootView.getViewTreeObserver().removeOnGlobalLayoutListener(list); - } - -} diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java b/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java deleted file mode 100755 index b7c72789..00000000 --- a/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody) - * Copyright (c) 2005-2010, Nitobi Software Inc. - * Copyright (c) 2010, IBM Corporation - */ - -package io.sqlc; - -import android.database.Cursor; -import android.database.CursorWindow; - -import android.database.sqlite.SQLiteConstraintException; -import android.database.sqlite.SQLiteCursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteStatement; - -import android.util.Log; - -import java.io.File; - -import java.lang.IllegalArgumentException; -import java.lang.Number; - -import java.util.Locale; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.cordova.CallbackContext; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Android Database helper class - */ -class SQLiteAndroidDatabase -{ - private static final Pattern FIRST_WORD = Pattern.compile("^[\\s;]*([^\\s;]+)", - Pattern.CASE_INSENSITIVE); - - private static final Pattern WHERE_CLAUSE = Pattern.compile("\\s+WHERE\\s+(.+)$", - Pattern.CASE_INSENSITIVE); - - private static final Pattern UPDATE_TABLE_NAME = Pattern.compile("^\\s*UPDATE\\s+(\\S+)", - Pattern.CASE_INSENSITIVE); - - private static final Pattern DELETE_TABLE_NAME = Pattern.compile("^\\s*DELETE\\s+FROM\\s+(\\S+)", - Pattern.CASE_INSENSITIVE); - - private static final boolean isPostHoneycomb = android.os.Build.VERSION.SDK_INT >= 11; - - File dbFile; - - SQLiteDatabase mydb; - - boolean isTransactionActive = false; - - /** - * NOTE: Using default constructor, no explicit constructor. - */ - - /** - * Open a database. - * - * @param dbfile The database File specification - */ - void open(File dbfile) throws Exception { - if (!isPostHoneycomb) { - Log.v("SQLiteAndroidDatabase.open", - "INTERNAL PLUGIN ERROR: deprecated android.os.Build.VERSION not supported: " + - android.os.Build.VERSION.SDK_INT); - throw new RuntimeException( - "INTERNAL PLUGIN ERROR: deprecated android.os.Build.VERSION not supported: " + - android.os.Build.VERSION.SDK_INT); - } - dbFile = dbfile; // for possible bug workaround - mydb = SQLiteDatabase.openOrCreateDatabase(dbfile, null); - } - - /** - * Close a database (in the current thread). - */ - void closeDatabaseNow() { - if (mydb != null) { - if (isTransactionActive) { - try { - mydb.endTransaction(); - } catch (Exception ex) { - Log.v("closeDatabaseNow", "INTERNAL PLUGIN ERROR IGNORED: Not able to end active transaction before closing database: " + ex.getMessage()); - ex.printStackTrace(); - } - isTransactionActive = false; - } - mydb.close(); - mydb = null; - } - } - - void bugWorkaround() throws Exception { - this.closeDatabaseNow(); - this.open(dbFile); - } - - /** - * Executes a batch request and sends the results via cbc. - * - * @param queryarr Array of query strings - * @param jsonparamsArr Array of JSON query parameters - * @param cbc Callback context from Cordova API - */ - void executeSqlBatch(String[] queryarr, JSONArray[] jsonparamsArr, CallbackContext cbc) { - - if (mydb == null) { - // not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database - // (internal plugin error) - cbc.error("INTERNAL PLUGIN ERROR: database not open"); - return; - } - - int len = queryarr.length; - JSONArray batchResults = new JSONArray(); - - for (int i = 0; i < len; i++) { - executeSqlBatchStatement(queryarr[i], jsonparamsArr[i], batchResults); - } - - cbc.success(batchResults); - } - - private void executeSqlBatchStatement(String query, JSONArray json_params, JSONArray batchResults) { - - if (mydb == null) { - // Should not happen here - return; - - } else { - - int rowsAffectedCompat = 0; - boolean needRowsAffectedCompat = false; - - JSONObject queryResult = null; - - String errorMessage = "unknown"; - int code = 0; // SQLException.UNKNOWN_ERR - - try { - boolean needRawQuery = true; - - //Log.v("executeSqlBatch", "get query type"); - QueryType queryType = getQueryType(query); - //Log.v("executeSqlBatch", "query type: " + queryType); - - if (queryType == QueryType.update || queryType == queryType.delete) { - // if (isPostHoneycomb) { - SQLiteStatement myStatement = mydb.compileStatement(query); - - if (json_params != null) { - bindArgsToStatement(myStatement, json_params); - } - - int rowsAffected = -1; // (assuming invalid) - - // Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying: - // (Catch SQLiteException here to avoid extra retry) - try { - rowsAffected = myStatement.executeUpdateDelete(); - // Indicate valid results: - needRawQuery = false; - } catch (SQLiteConstraintException ex) { - // Indicate problem & stop this query: - ex.printStackTrace(); - errorMessage = "constraint failure: " + ex.getMessage(); - code = 6; // SQLException.CONSTRAINT_ERR - Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): Error=" + errorMessage); - needRawQuery = false; - } catch (SQLiteException ex) { - // Indicate problem & stop this query: - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): Error=" + errorMessage); - needRawQuery = false; - } catch (Exception ex) { - // Assuming SDK_INT was lying & method not found: - // do nothing here & try again with raw query. - ex.printStackTrace(); - // Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): runtime error (fallback to old API): " + errorMessage); - Log.v("SQLiteAndroidDatabase.executeSqlBatchStatement", - "INTERNAL PLUGIN ERROR: could not do myStatement.executeUpdateDelete(): " + ex.getMessage()); - throw(ex); - } - - // "finally" cleanup myStatement - myStatement.close(); - - if (rowsAffected != -1) { - queryResult = new JSONObject(); - queryResult.put("rowsAffected", rowsAffected); - } - // } - - if (needRawQuery) { // for pre-honeycomb behavior - rowsAffectedCompat = countRowsAffectedCompat(queryType, query, json_params, mydb); - needRowsAffectedCompat = true; - } - } - - // INSERT: - if (queryType == QueryType.insert && json_params != null) { - needRawQuery = false; - - SQLiteStatement myStatement = mydb.compileStatement(query); - - bindArgsToStatement(myStatement, json_params); - - long insertId = -1; // (invalid) - - try { - insertId = myStatement.executeInsert(); - - // statement has finished with no constraint violation: - queryResult = new JSONObject(); - if (insertId != -1) { - queryResult.put("insertId", insertId); - queryResult.put("rowsAffected", 1); - } else { - queryResult.put("rowsAffected", 0); - } - } catch (SQLiteConstraintException ex) { - // report constraint violation error result with the error message - ex.printStackTrace(); - errorMessage = "constraint failure: " + ex.getMessage(); - code = 6; // SQLException.CONSTRAINT_ERR - Log.v("executeSqlBatch", "SQLiteDatabase.executeInsert(): Error=" + errorMessage); - } catch (SQLiteException ex) { - // report some other error result with the error message - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteDatabase.executeInsert(): Error=" + errorMessage); - } - - // "finally" cleanup myStatement - myStatement.close(); - } - - if (queryType == QueryType.begin) { - needRawQuery = false; - try { - mydb.beginTransaction(); - isTransactionActive = true; - - queryResult = new JSONObject(); - queryResult.put("rowsAffected", 0); - } catch (SQLiteException ex) { - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteDatabase.beginTransaction(): Error=" + errorMessage); - } - } - - if (queryType == QueryType.commit) { - needRawQuery = false; - try { - mydb.setTransactionSuccessful(); - mydb.endTransaction(); - isTransactionActive = false; - - queryResult = new JSONObject(); - queryResult.put("rowsAffected", 0); - } catch (SQLiteException ex) { - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteDatabase.setTransactionSuccessful/endTransaction(): Error=" + errorMessage); - } - } - - if (queryType == QueryType.rollback) { - needRawQuery = false; - try { - mydb.endTransaction(); - isTransactionActive = false; - - queryResult = new JSONObject(); - queryResult.put("rowsAffected", 0); - } catch (SQLiteException ex) { - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteDatabase.endTransaction(): Error=" + errorMessage); - } - } - - // raw query for other statements: - if (needRawQuery) { - try { - queryResult = this.executeSqlStatementQuery(mydb, query, json_params); - - } catch (SQLiteConstraintException ex) { - // report constraint violation error result with the error message - ex.printStackTrace(); - errorMessage = "constraint failure: " + ex.getMessage(); - code = 6; // SQLException.CONSTRAINT_ERR - Log.v("executeSqlBatch", "Raw query error=" + errorMessage); - } catch (SQLiteException ex) { - // report some other error result with the error message - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "Raw query error=" + errorMessage); - } - - if (needRowsAffectedCompat) { - queryResult.put("rowsAffected", rowsAffectedCompat); - } - } - } catch (Exception ex) { - ex.printStackTrace(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage); - } - - try { - if (queryResult != null) { - JSONObject r = new JSONObject(); - - r.put("type", "success"); - r.put("result", queryResult); - - batchResults.put(r); - } else { - JSONObject r = new JSONObject(); - r.put("type", "error"); - - JSONObject er = new JSONObject(); - er.put("message", errorMessage); - er.put("code", code); - r.put("result", er); - - batchResults.put(r); - } - } catch (JSONException ex) { - ex.printStackTrace(); - Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + ex.getMessage()); - // TODO what to do? - } - } - } - - private final int countRowsAffectedCompat(QueryType queryType, String query, JSONArray json_params, - SQLiteDatabase mydb) throws JSONException { - // quick and dirty way to calculate the rowsAffected in pre-Honeycomb. just do a SELECT - // beforehand using the same WHERE clause. might not be perfect, but it's better than nothing - Matcher whereMatcher = WHERE_CLAUSE.matcher(query); - - String where = ""; - - int pos = 0; - while (whereMatcher.find(pos)) { - where = " WHERE " + whereMatcher.group(1); - pos = whereMatcher.start(1); - } - // WHERE clause may be omitted, and also be sure to find the last one, - // e.g. for cases where there's a subquery - - // bindings may be in the update clause, so only take the last n - int numQuestionMarks = 0; - for (int j = 0; j < where.length(); j++) { - if (where.charAt(j) == '?') { - numQuestionMarks++; - } - } - - JSONArray subParams = null; - - if (json_params != null) { - // only take the last n of every array of sqlArgs - JSONArray origArray = json_params; - subParams = new JSONArray(); - int startPos = origArray.length() - numQuestionMarks; - for (int j = startPos; j < origArray.length(); j++) { - subParams.put(j - startPos, origArray.get(j)); - } - } - - if (queryType == QueryType.update) { - Matcher tableMatcher = UPDATE_TABLE_NAME.matcher(query); - if (tableMatcher.find()) { - String table = tableMatcher.group(1); - try { - SQLiteStatement statement = mydb.compileStatement( - "SELECT count(*) FROM " + table + where); - - if (subParams != null) { - bindArgsToStatement(statement, subParams); - } - - return (int)statement.simpleQueryForLong(); - } catch (Exception e) { - // assume we couldn't count for whatever reason, keep going - Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e); - } - } - } else { // delete - Matcher tableMatcher = DELETE_TABLE_NAME.matcher(query); - if (tableMatcher.find()) { - String table = tableMatcher.group(1); - try { - SQLiteStatement statement = mydb.compileStatement( - "SELECT count(*) FROM " + table + where); - bindArgsToStatement(statement, subParams); - - return (int)statement.simpleQueryForLong(); - } catch (Exception e) { - // assume we couldn't count for whatever reason, keep going - Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e); - - } - } - } - - return 0; - } - - private void bindArgsToStatement(SQLiteStatement myStatement, JSONArray sqlArgs) throws JSONException { - for (int i = 0; i < sqlArgs.length(); i++) { - if (sqlArgs.get(i) instanceof Float || sqlArgs.get(i) instanceof Double) { - myStatement.bindDouble(i + 1, sqlArgs.getDouble(i)); - } else if (sqlArgs.get(i) instanceof Number) { - myStatement.bindLong(i + 1, sqlArgs.getLong(i)); - } else if (sqlArgs.isNull(i)) { - myStatement.bindNull(i + 1); - } else { - myStatement.bindString(i + 1, sqlArgs.getString(i)); - } - } - } - - /** - * Get rows results from query cursor. - * - * @param cur Cursor into query results - * @return results in string form - */ - private JSONObject executeSqlStatementQuery(SQLiteDatabase mydb, String query, - JSONArray paramsAsJson) throws Exception { - JSONObject rowsResult = new JSONObject(); - - Cursor cur = null; - try { - String[] params = null; - - params = new String[paramsAsJson.length()]; - - for (int j = 0; j < paramsAsJson.length(); j++) { - if (paramsAsJson.isNull(j)) - params[j] = ""; - else - params[j] = paramsAsJson.getString(j); - } - - cur = mydb.rawQuery(query, params); - } catch (Exception ex) { - ex.printStackTrace(); - String errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage); - throw ex; - } - - // If query result has rows - if (cur != null && cur.moveToFirst()) { - JSONArray rowsArrayResult = new JSONArray(); - String key = ""; - int colCount = cur.getColumnCount(); - - // Build up JSON result object for each row - do { - JSONObject row = new JSONObject(); - try { - for (int i = 0; i < colCount; ++i) { - key = cur.getColumnName(i); - - if (isPostHoneycomb) { - // Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying: - try { - bindPostHoneycomb(row, key, cur, i); - } catch (Exception ex) { - // bindPreHoneycomb(row, key, cur, i); - Log.v("SQLiteAndroidDatabase.executeSqlStatementQuery", - "INTERNAL PLUGIN ERROR: could not bindPostHoneycomb: " + ex.getMessage()); - throw(ex); - } - } else { - // NOT EXPECTED: - // bindPreHoneycomb(row, key, cur, i); - Log.v("SQLiteAndroidDatabase.executeSqlStatementQuery", - "INTERNAL PLUGIN ERROR: deprecated android.os.Build.VERSION not supported: " + android.os.Build.VERSION.SDK_INT); - throw new RuntimeException( - "INTERNAL PLUGIN ERROR: deprecated android.os.Build.VERSION not supported: " + - android.os.Build.VERSION.SDK_INT); - } - } - - rowsArrayResult.put(row); - - } catch (JSONException e) { - e.printStackTrace(); - } - } while (cur.moveToNext()); - - try { - rowsResult.put("rows", rowsArrayResult); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - if (cur != null) { - cur.close(); - } - - return rowsResult; - } - - private void bindPostHoneycomb(JSONObject row, String key, Cursor cur, int i) throws JSONException { - int curType = cur.getType(i); - - switch (curType) { - case Cursor.FIELD_TYPE_NULL: - row.put(key, JSONObject.NULL); - break; - case Cursor.FIELD_TYPE_INTEGER: - row.put(key, cur.getLong(i)); - break; - case Cursor.FIELD_TYPE_FLOAT: - row.put(key, cur.getDouble(i)); - break; - case Cursor.FIELD_TYPE_STRING: - default: /* (BLOB) */ - row.put(key, cur.getString(i)); - break; - } - } - - /* ** NO LONGER SUPPORTED: - private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i) throws JSONException { - // Since cursor.getType() is not available pre-honeycomb, this is - // a workaround so we don't have to bind everything as a string - // Details here: http://stackoverflow.com/q/11658239 - SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor; - CursorWindow cursorWindow = sqLiteCursor.getWindow(); - int pos = cursor.getPosition(); - if (cursorWindow.isNull(pos, i)) { - row.put(key, JSONObject.NULL); - } else if (cursorWindow.isLong(pos, i)) { - row.put(key, cursor.getLong(i)); - } else if (cursorWindow.isFloat(pos, i)) { - row.put(key, cursor.getDouble(i)); - } else { - // STRING or BLOB: - row.put(key, cursor.getString(i)); - } - } - // */ - - static QueryType getQueryType(String query) { - Matcher matcher = FIRST_WORD.matcher(query); - - // FIND & return query type, or throw: - if (matcher.find()) { - try { - String first = matcher.group(1); - - // explictly reject if blank - // (needed for SQLCipher version) - if (first.length() == 0) throw new RuntimeException("query not found"); - - return QueryType.valueOf(first.toLowerCase(Locale.ENGLISH)); - } catch (IllegalArgumentException ignore) { - // unknown verb (NOT blank) - return QueryType.other; - } - } else { - // explictly reject if blank - // (needed for SQLCipher version) - throw new RuntimeException("query not found"); - } - } - - static enum QueryType { - update, - insert, - delete, - select, - begin, - commit, - rollback, - other - } -} /* vim: set expandtab : */ diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java b/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java deleted file mode 100755 index d0b494a8..00000000 --- a/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody) - * Copyright (c) 2005-2010, Nitobi Software Inc. - * Copyright (c) 2010, IBM Corporation - */ - -package io.sqlc; - -import android.util.Log; - -import java.io.File; - -import java.lang.IllegalArgumentException; -import java.lang.Number; - -import java.sql.SQLException; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.cordova.CallbackContext; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import io.liteglue.SQLCode; -import io.liteglue.SQLColumnType; -import io.liteglue.SQLiteConnector; -import io.liteglue.SQLiteConnection; -import io.liteglue.SQLiteOpenFlags; -import io.liteglue.SQLiteStatement; - -/** - * Android SQLite-Connector Database helper class - */ -class SQLiteConnectorDatabase extends SQLiteAndroidDatabase -{ - static SQLiteConnector connector = new SQLiteConnector(); - - SQLiteConnection mydb; - - /** - * NOTE: Using default constructor, no explicit constructor. - */ - - - /** - * Open a database. - * - * @param dbFile The database File specification - */ - @Override - void open(File dbFile) throws Exception { - mydb = connector.newSQLiteConnection(dbFile.getAbsolutePath(), - SQLiteOpenFlags.READWRITE | SQLiteOpenFlags.CREATE); - } - - /** - * Close a database (in the current thread). - */ - @Override - void closeDatabaseNow() { - try { - if (mydb != null) - mydb.dispose(); - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database, ignoring", e); - } - } - - /** - * Ignore Android bug workaround for NDK version - */ - @Override - void bugWorkaround() { } - - /** - * Executes a batch request and sends the results via cbc. - * - * @param dbname The name of the database. - * @param queryarr Array of query strings - * @param jsonparams Array of JSON query parameters - * @param cbc Callback context from Cordova API - */ - @Override - void executeSqlBatch( String[] queryarr, JSONArray[] jsonparams, CallbackContext cbc) { - - if (mydb == null) { - // not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database - cbc.error("database has been closed"); - return; - } - - int len = queryarr.length; - JSONArray batchResults = new JSONArray(); - - for (int i = 0; i < len; i++) { - int rowsAffectedCompat = 0; - boolean needRowsAffectedCompat = false; - - JSONObject queryResult = null; - - String errorMessage = "unknown"; - int sqliteErrorCode = -1; - int code = 0; // SQLException.UNKNOWN_ERR - - try { - String query = queryarr[i]; - - long lastTotal = mydb.getTotalChanges(); - queryResult = this.executeSQLiteStatement(query, jsonparams[i], cbc); - long newTotal = mydb.getTotalChanges(); - long rowsAffected = newTotal - lastTotal; - - queryResult.put("rowsAffected", rowsAffected); - if (rowsAffected > 0) { - long insertId = mydb.getLastInsertRowid(); - if (insertId > 0) { - queryResult.put("insertId", insertId); - } - } - } catch (SQLException ex) { - ex.printStackTrace(); - sqliteErrorCode = ex.getErrorCode(); - errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): SQL Error code = " + sqliteErrorCode + " message = " + errorMessage); - - switch(sqliteErrorCode) { - case SQLCode.ERROR: - code = 5; // SQLException.SYNTAX_ERR - break; - case 13: // SQLITE_FULL - code = 4; // SQLException.QUOTA_ERR - break; - case SQLCode.CONSTRAINT: - code = 6; // SQLException.CONSTRAINT_ERR - break; - default: - /* do nothing */ - } - } catch (JSONException ex) { - // NOT expected: - ex.printStackTrace(); - errorMessage = ex.getMessage(); - code = 0; // SQLException.UNKNOWN_ERR - Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): UNEXPECTED JSON Error=" + errorMessage); - } - - try { - if (queryResult != null) { - JSONObject r = new JSONObject(); - - r.put("type", "success"); - r.put("result", queryResult); - - batchResults.put(r); - } else { - JSONObject r = new JSONObject(); - r.put("type", "error"); - - JSONObject er = new JSONObject(); - er.put("message", errorMessage); - er.put("code", code); - r.put("result", er); - - batchResults.put(r); - } - } catch (JSONException ex) { - ex.printStackTrace(); - Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + ex.getMessage()); - // TODO what to do? - } - } - - cbc.success(batchResults); - } - - /** - * Get rows results from query cursor. - * - * @param cur Cursor into query results - * @return results in string form - */ - private JSONObject executeSQLiteStatement(String query, JSONArray paramsAsJson, - CallbackContext cbc) throws JSONException, SQLException { - JSONObject rowsResult = new JSONObject(); - - boolean hasRows = false; - - SQLiteStatement myStatement = mydb.prepareStatement(query); - - try { - String[] params = null; - - params = new String[paramsAsJson.length()]; - - for (int i = 0; i < paramsAsJson.length(); ++i) { - if (paramsAsJson.isNull(i)) { - myStatement.bindNull(i + 1); - } else { - Object p = paramsAsJson.get(i); - if (p instanceof Float || p instanceof Double) - myStatement.bindDouble(i + 1, paramsAsJson.getDouble(i)); - else if (p instanceof Number) - myStatement.bindLong(i + 1, paramsAsJson.getLong(i)); - else - myStatement.bindTextNativeString(i + 1, paramsAsJson.getString(i)); - } - } - - hasRows = myStatement.step(); - } catch (SQLException ex) { - ex.printStackTrace(); - String errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage); - - // cleanup statement and throw the exception: - myStatement.dispose(); - throw ex; - } catch (JSONException ex) { - ex.printStackTrace(); - String errorMessage = ex.getMessage(); - Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage); - - // cleanup statement and throw the exception: - myStatement.dispose(); - throw ex; - } - - // If query result has rows - if (hasRows) { - JSONArray rowsArrayResult = new JSONArray(); - String key = ""; - int colCount = myStatement.getColumnCount(); - - // Build up JSON result object for each row - do { - JSONObject row = new JSONObject(); - try { - for (int i = 0; i < colCount; ++i) { - key = myStatement.getColumnName(i); - - switch (myStatement.getColumnType(i)) { - case SQLColumnType.NULL: - row.put(key, JSONObject.NULL); - break; - - case SQLColumnType.REAL: - row.put(key, myStatement.getColumnDouble(i)); - break; - - case SQLColumnType.INTEGER: - row.put(key, myStatement.getColumnLong(i)); - break; - - case SQLColumnType.BLOB: - case SQLColumnType.TEXT: - default: // (just in case) - row.put(key, myStatement.getColumnTextNativeString(i)); - } - - } - - rowsArrayResult.put(row); - - } catch (JSONException e) { - e.printStackTrace(); - } - } while (myStatement.step()); - - try { - rowsResult.put("rows", rowsArrayResult); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - myStatement.dispose(); - - return rowsResult; - } - -} /* vim: set expandtab : */ diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java b/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java deleted file mode 100755 index 69d4afa6..00000000 --- a/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody) - * Copyright (c) 2005-2010, Nitobi Software Inc. - * Copyright (c) 2010, IBM Corporation - */ - -package io.sqlc; - -import android.util.Log; - -import java.io.File; - -import java.lang.IllegalArgumentException; -import java.lang.Number; - -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -public class SQLitePlugin extends CordovaPlugin { - - /** - * Concurrent database runner map. - * - * NOTE: no public static accessor to db (runner) map since it is not - * expected to work properly with db threading. - * - * FUTURE TBD put DBRunner into a public class that can provide external accessor. - * - * ADDITIONAL NOTE: Storing as Map to avoid portabiity issue - * between Java 6/7/8 as discussed in: - * https://gist.github.com/AlainODea/1375759b8720a3f9f094 - * - * THANKS to @NeoLSN (Jason Yang/楊朝傑) for giving the pointer in: - * https://github.com/litehelpers/Cordova-sqlite-storage/issues/727 - */ - private Map dbrmap = new ConcurrentHashMap(); - - /** - * NOTE: Using default constructor, no explicit constructor. - */ - - /** - * Executes the request and returns PluginResult. - * - * @param actionAsString The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param cbc Callback context from Cordova API - * @return Whether the action was valid. - */ - @Override - public boolean execute(String actionAsString, JSONArray args, CallbackContext cbc) { - - Action action; - try { - action = Action.valueOf(actionAsString); - } catch (IllegalArgumentException e) { - // shouldn't ever happen - Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e); - return false; - } - - try { - return executeAndPossiblyThrow(action, args, cbc); - } catch (JSONException e) { - // TODO: signal JSON problem to JS - Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e); - return false; - } - } - - private boolean executeAndPossiblyThrow(Action action, JSONArray args, CallbackContext cbc) - throws JSONException { - - boolean status = true; - JSONObject o; - String echo_value; - String dbname; - - switch (action) { - case echoStringValue: - o = args.getJSONObject(0); - echo_value = o.getString("value"); - cbc.success(echo_value); - break; - - case open: - o = args.getJSONObject(0); - dbname = o.getString("name"); - // open database and start reading its queue - this.startDatabase(dbname, o, cbc); - break; - - case close: - o = args.getJSONObject(0); - dbname = o.getString("path"); - // put request in the q to close the db - this.closeDatabase(dbname, cbc); - break; - - case delete: - o = args.getJSONObject(0); - dbname = o.getString("path"); - - deleteDatabase(dbname, cbc); - - break; - - case executeSqlBatch: - case backgroundExecuteSqlBatch: - JSONObject allargs = args.getJSONObject(0); - JSONObject dbargs = allargs.getJSONObject("dbargs"); - dbname = dbargs.getString("dbname"); - JSONArray txargs = allargs.getJSONArray("executes"); - - if (txargs.isNull(0)) { - cbc.error("INTERNAL PLUGIN ERROR: missing executes list"); - } else { - int len = txargs.length(); - String[] queries = new String[len]; - JSONArray[] jsonparams = new JSONArray[len]; - - for (int i = 0; i < len; i++) { - JSONObject a = txargs.getJSONObject(i); - queries[i] = a.getString("sql"); - jsonparams[i] = a.getJSONArray("params"); - } - - // put db query in the queue to be executed in the db thread: - DBQuery q = new DBQuery(queries, jsonparams, cbc); - DBRunner r = dbrmap.get(dbname); - if (r != null) { - try { - r.q.put(q); - } catch(Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't add to queue", e); - cbc.error("INTERNAL PLUGIN ERROR: couldn't add to queue"); - } - } else { - cbc.error("INTERNAL PLUGIN ERROR: database not open"); - } - } - break; - } - - return status; - } - - /** - * Clean up and close all open databases. - */ - @Override - public void onDestroy() { - while (!dbrmap.isEmpty()) { - String dbname = dbrmap.keySet().iterator().next(); - - this.closeDatabaseNow(dbname); - - DBRunner r = dbrmap.get(dbname); - try { - // stop the db runner thread: - r.q.put(new DBQuery()); - } catch(Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "INTERNAL PLUGIN CLEANUP ERROR: could not stop db thread due to exception", e); - } - dbrmap.remove(dbname); - } - } - - // -------------------------------------------------------------------------- - // LOCAL METHODS - // -------------------------------------------------------------------------- - - private void startDatabase(String dbname, JSONObject options, CallbackContext cbc) { - DBRunner r = dbrmap.get(dbname); - - if (r != null) { - // NO LONGER EXPECTED due to BUG 666 workaround solution: - cbc.error("INTERNAL ERROR: database already open for db name: " + dbname); - } else { - r = new DBRunner(dbname, options, cbc); - dbrmap.put(dbname, r); - this.cordova.getThreadPool().execute(r); - } - } - /** - * Open a database. - * - * @param dbName The name of the database file - */ - private SQLiteAndroidDatabase openDatabase(String dbname, CallbackContext cbc, boolean old_impl) throws Exception { - try { - // ASSUMPTION: no db (connection/handle) is already stored in the map - // [should be true according to the code in DBRunner.run()] - - File dbfile = this.cordova.getActivity().getDatabasePath(dbname); - - if (!dbfile.exists()) { - dbfile.getParentFile().mkdirs(); - } - - Log.v("info", "Open sqlite db: " + dbfile.getAbsolutePath()); - - SQLiteAndroidDatabase mydb = old_impl ? new SQLiteAndroidDatabase() : new SQLiteConnectorDatabase(); - mydb.open(dbfile); - - if (cbc != null) // XXX Android locking/closing BUG workaround - cbc.success(); - - return mydb; - } catch (Exception e) { - if (cbc != null) // XXX Android locking/closing BUG workaround - cbc.error("can't open database " + e); - throw e; - } - } - - /** - * Close a database (in another thread). - * - * @param dbName The name of the database file - */ - private void closeDatabase(String dbname, CallbackContext cbc) { - DBRunner r = dbrmap.get(dbname); - if (r != null) { - try { - r.q.put(new DBQuery(false, cbc)); - } catch(Exception e) { - if (cbc != null) { - cbc.error("couldn't close database" + e); - } - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e); - } - } else { - if (cbc != null) { - cbc.success(); - } - } - } - - /** - * Close a database (in the current thread). - * - * @param dbname The name of the database file - */ - private void closeDatabaseNow(String dbname) { - DBRunner r = dbrmap.get(dbname); - - if (r != null) { - SQLiteAndroidDatabase mydb = r.mydb; - - if (mydb != null) - mydb.closeDatabaseNow(); - } - } - - private void deleteDatabase(String dbname, CallbackContext cbc) { - DBRunner r = dbrmap.get(dbname); - if (r != null) { - try { - r.q.put(new DBQuery(true, cbc)); - } catch(Exception e) { - if (cbc != null) { - cbc.error("couldn't close database" + e); - } - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e); - } - } else { - boolean deleteResult = this.deleteDatabaseNow(dbname); - if (deleteResult) { - cbc.success(); - } else { - cbc.error("couldn't delete database"); - } - } - } - - /** - * Delete a database. - * - * @param dbName The name of the database file - * - * @return true if successful or false if an exception was encountered - */ - private boolean deleteDatabaseNow(String dbname) { - File dbfile = this.cordova.getActivity().getDatabasePath(dbname); - - try { - return cordova.getActivity().deleteDatabase(dbfile.getAbsolutePath()); - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e); - return false; - } - } - - private class DBRunner implements Runnable { - final String dbname; - private boolean oldImpl; - private boolean bugWorkaround; - - final BlockingQueue q; - final CallbackContext openCbc; - - SQLiteAndroidDatabase mydb; - - DBRunner(final String dbname, JSONObject options, CallbackContext cbc) { - this.dbname = dbname; - this.oldImpl = options.has("androidOldDatabaseImplementation"); - Log.v(SQLitePlugin.class.getSimpleName(), "Android db implementation: built-in android.database.sqlite package"); - this.bugWorkaround = this.oldImpl && options.has("androidBugWorkaround"); - if (this.bugWorkaround) - Log.v(SQLitePlugin.class.getSimpleName(), "Android db closing/locking workaround applied"); - - this.q = new LinkedBlockingQueue(); - this.openCbc = cbc; - } - - public void run() { - try { - this.mydb = openDatabase(dbname, this.openCbc, this.oldImpl); - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error, stopping db thread", e); - dbrmap.remove(dbname); - return; - } - - DBQuery dbq = null; - - try { - dbq = q.take(); - - while (!dbq.stop) { - mydb.executeSqlBatch(dbq.queries, dbq.jsonparams, dbq.cbc); - - if (this.bugWorkaround && dbq.queries.length == 1 && dbq.queries[0] == "COMMIT") - mydb.bugWorkaround(); - - dbq = q.take(); - } - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e); - } - - if (dbq != null && dbq.close) { - try { - closeDatabaseNow(dbname); - - dbrmap.remove(dbname); // (should) remove ourself - - if (!dbq.delete) { - dbq.cbc.success(); - } else { - try { - boolean deleteResult = deleteDatabaseNow(dbname); - if (deleteResult) { - dbq.cbc.success(); - } else { - dbq.cbc.error("couldn't delete database"); - } - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e); - dbq.cbc.error("couldn't delete database: " + e); - } - } - } catch (Exception e) { - Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e); - if (dbq.cbc != null) { - dbq.cbc.error("couldn't close database: " + e); - } - } - } - } - } - - private final class DBQuery { - // XXX TODO replace with DBRunner action enum: - final boolean stop; - final boolean close; - final boolean delete; - final String[] queries; - final JSONArray[] jsonparams; - final CallbackContext cbc; - - DBQuery(String[] myqueries, JSONArray[] params, CallbackContext c) { - this.stop = false; - this.close = false; - this.delete = false; - this.queries = myqueries; - this.jsonparams = params; - this.cbc = c; - } - - DBQuery(boolean delete, CallbackContext cbc) { - this.stop = true; - this.close = true; - this.delete = delete; - this.queries = null; - this.jsonparams = null; - this.cbc = cbc; - } - - // signal the DBRunner thread to stop: - DBQuery() { - this.stop = true; - this.close = false; - this.delete = false; - this.queries = null; - this.jsonparams = null; - this.cbc = null; - } - } - - private static enum Action { - echoStringValue, - open, - close, - delete, - executeSqlBatch, - backgroundExecuteSqlBatch, - } -} - -/* vim: set expandtab : */ diff --git a/platforms/android/app/src/main/java/nl/xservices/plugins/actionsheet/ActionSheet.java b/platforms/android/app/src/main/java/nl/xservices/plugins/actionsheet/ActionSheet.java deleted file mode 100755 index c90c507a..00000000 --- a/platforms/android/app/src/main/java/nl/xservices/plugins/actionsheet/ActionSheet.java +++ /dev/null @@ -1,196 +0,0 @@ -package nl.xservices.plugins.actionsheet; - -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.os.Build; -import android.text.TextUtils; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Original excellent PR by: Brill Pappin - * @author Mantainer of the code: Eddy Verbruggen - */ -public class ActionSheet extends CordovaPlugin { - - private AlertDialog dialog; - - public ActionSheet() { - super(); - } - - private static final String ACTION_SHOW = "show"; - private static final String ACTION_HIDE = "hide"; - - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - - if (ACTION_SHOW.equals(action)) { - JSONObject options = args.optJSONObject(0); - - String title = options.optString("title"); - String subtitle = options.optString("subtitle"); - int theme = options.optInt("androidTheme", 1); - JSONArray buttons = options.optJSONArray("buttonLabels"); - - boolean androidEnableCancelButton = options.optBoolean("androidEnableCancelButton", false); - boolean destructiveButtonLast = options.optBoolean("destructiveButtonLast", false); - - String addCancelButtonWithLabel = options.optString("addCancelButtonWithLabel"); - String addDestructiveButtonWithLabel = options.optString("addDestructiveButtonWithLabel"); - - this.show(title, subtitle, buttons, addCancelButtonWithLabel, androidEnableCancelButton, - addDestructiveButtonWithLabel, destructiveButtonLast, - theme, callbackContext); - // need to return as this call is async. - return true; - - } else if (ACTION_HIDE.equals(action)) { - if (dialog != null && dialog.isShowing()) { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, -1)); - } - return true; - } - - return false; - } - - public synchronized void show(final String title, - final String subtitle, - final JSONArray buttonLabels, - final String addCancelButtonWithLabel, - final boolean androidEnableCancelButton, - final String addDestructiveButtonWithLabel, - final boolean destructiveButtonLast, - final int theme, - final CallbackContext callbackContext) { - - final CordovaInterface cordova = this.cordova; - - Runnable runnable = new Runnable() { - public void run() { - - final AlertDialog.Builder builder; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - builder = new AlertDialog.Builder(cordova.getActivity(), theme); - } else { - builder = new AlertDialog.Builder(cordova.getActivity()); - } - - builder - .setTitle(title) - .setCancelable(true); - - - // Although there is not really anything technically wrong - // with adding a cancel button, Android typically doesn't use - // one for this kind of list dialog. - // We'll allow the user to override the "smart" option and - // include it if they insist anyway. - - if (androidEnableCancelButton && !TextUtils.isEmpty(addCancelButtonWithLabel)) { - builder.setNegativeButton(addCancelButtonWithLabel, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - // We catch the cancel event and return - // the index then. - } - }); - } - - // So what do we do with the iOS destructive button? - // Android doesn't really have the concept, so we're going to - // ignore it until we have a situation where we can come up with - // a good way to implement it. Most likely adding an image - // or some other indicator. -// if (!TextUtils.isEmpty(addDestructiveButtonWithLabel)) { -// builder.setPositiveButton(addDestructiveButtonWithLabel, -// new OnClickListener() { -// @Override -// public void onClick(DialogInterface dialog, int which) { -// dialog.dismiss(); -// callbackContext -// .sendPluginResult(new PluginResult( -// PluginResult.Status.OK, 0)); -// } -// }); -// } - - final String[] buttons = getStringArray( - buttonLabels, - destructiveButtonLast, - (TextUtils.isEmpty(addDestructiveButtonWithLabel) ? null - : addDestructiveButtonWithLabel)); - - builder.setItems(buttons, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // java 0 based index converted to cordova 1 based - // index, so we don't confuse the webbies. - callbackContext.sendPluginResult(new PluginResult( - PluginResult.Status.OK, which + 1)); - } - }); - - builder.setOnCancelListener(new AlertDialog.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - // Match the way the iOS plugin works. Cancel is - // always the last index and destructive is always the - // first, if it exists. Even though we don't handle the - // destructive button, we want the selected index to - // match. - int cancelButtonIndex = buttons.length + 1; - callbackContext.sendPluginResult(new PluginResult( - PluginResult.Status.OK, cancelButtonIndex)); - } - }); - - dialog = builder.create(); - dialog.show(); - } - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - private String[] getStringArray(JSONArray jsonArray, boolean append, String... additionalButtons) { - - List btns = new ArrayList(); - - // Add prefix items - if (!append) { - for (String btn : additionalButtons) { - if (!TextUtils.isEmpty(btn)) { - btns.add(btn); - } - } - } - - // add the rest of the buttons from the list. - if (jsonArray != null) { - for (int i = 0; i < jsonArray.length(); i++) { - btns.add(jsonArray.optString(i)); - } - } - - // Add postfix items - if (append) { - for (String btn : additionalButtons) { - if (!TextUtils.isEmpty(btn)) { - btns.add(btn); - } - } - } - return btns.toArray(new String[btns.size()]); - } -} \ No newline at end of file diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java deleted file mode 100755 index fbe8470e..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java +++ /dev/null @@ -1,1407 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.camera; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.cordova.BuildHelper; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaResourceApi; -import org.apache.cordova.LOG; -import org.apache.cordova.PermissionHelper; -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; - -import android.Manifest; -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.media.ExifInterface; -import android.media.MediaScannerConnection; -import android.media.MediaScannerConnection.MediaScannerConnectionClient; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.support.v4.content.FileProvider; -import android.util.Base64; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; - -/** - * This class launches the camera view, allows the user to take a picture, closes the camera view, - * and returns the captured image. When the camera view is closed, the screen displayed before - * the camera view was shown is redisplayed. - */ -public class CameraLauncher extends CordovaPlugin implements MediaScannerConnectionClient { - - private static final int DATA_URL = 0; // Return base64 encoded string - private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android) - private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI - - private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android) - private static final int CAMERA = 1; // Take picture from camera - private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android) - - private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType - private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL - private static final int ALLMEDIA = 2; // allow selection from all media types - - private static final int JPEG = 0; // Take a picture of type JPEG - private static final int PNG = 1; // Take a picture of type PNG - private static final String GET_PICTURE = "Get Picture"; - private static final String GET_VIDEO = "Get Video"; - private static final String GET_All = "Get All"; - - public static final int PERMISSION_DENIED_ERROR = 20; - public static final int TAKE_PIC_SEC = 0; - public static final int SAVE_TO_ALBUM_SEC = 1; - - private static final String LOG_TAG = "CameraLauncher"; - - //Where did this come from? - private static final int CROP_CAMERA = 100; - - private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) - private int targetWidth; // desired width of the image - private int targetHeight; // desired height of the image - private CordovaUri imageUri; // Uri of captured image - private int encodingType; // Type of encoding to use - private int mediaType; // What type of media to retrieve - private int destType; // Source type (needs to be saved for the permission handling) - private int srcType; // Destination type (needs to be saved for permission handling) - private boolean saveToPhotoAlbum; // Should the picture be saved to the device's photo album - private boolean correctOrientation; // Should the pictures orientation be corrected - private boolean orientationCorrected; // Has the picture's orientation been corrected - private boolean allowEdit; // Should we allow the user to crop the image. - - protected final static String[] permissions = { Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; - - public CallbackContext callbackContext; - private int numPics; - - private MediaScannerConnection conn; // Used to update gallery app with newly-written files - private Uri scanMe; // Uri of image to be added to content store - private Uri croppedUri; - private ExifHelper exifData; // Exif data from source - private String applicationId; - - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback id used when calling back into JavaScript. - * @return A PluginResult object with a status and message. - */ - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - this.callbackContext = callbackContext; - //Adding an API to CoreAndroid to get the BuildConfigValue - //This allows us to not make this a breaking change to embedding - this.applicationId = (String) BuildHelper.getBuildConfigValue(cordova.getActivity(), "APPLICATION_ID"); - this.applicationId = preferences.getString("applicationId", this.applicationId); - - - if (action.equals("takePicture")) { - this.srcType = CAMERA; - this.destType = FILE_URI; - this.saveToPhotoAlbum = false; - this.targetHeight = 0; - this.targetWidth = 0; - this.encodingType = JPEG; - this.mediaType = PICTURE; - this.mQuality = 50; - - //Take the values from the arguments if they're not already defined (this is tricky) - this.destType = args.getInt(1); - this.srcType = args.getInt(2); - this.mQuality = args.getInt(0); - this.targetWidth = args.getInt(3); - this.targetHeight = args.getInt(4); - this.encodingType = args.getInt(5); - this.mediaType = args.getInt(6); - this.allowEdit = args.getBoolean(7); - this.correctOrientation = args.getBoolean(8); - this.saveToPhotoAlbum = args.getBoolean(9); - - // If the user specifies a 0 or smaller width/height - // make it -1 so later comparisons succeed - if (this.targetWidth < 1) { - this.targetWidth = -1; - } - if (this.targetHeight < 1) { - this.targetHeight = -1; - } - - // We don't return full-quality PNG files. The camera outputs a JPEG - // so requesting it as a PNG provides no actual benefit - if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 && - !this.correctOrientation && this.encodingType == PNG && this.srcType == CAMERA) { - this.encodingType = JPEG; - } - - try { - if (this.srcType == CAMERA) { - this.callTakePicture(destType, encodingType); - } - else if ((this.srcType == PHOTOLIBRARY) || (this.srcType == SAVEDPHOTOALBUM)) { - // FIXME: Stop always requesting the permission - if(!PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) { - PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE); - } else { - this.getImage(this.srcType, destType, encodingType); - } - } - } - catch (IllegalArgumentException e) - { - callbackContext.error("Illegal Argument Exception"); - PluginResult r = new PluginResult(PluginResult.Status.ERROR); - callbackContext.sendPluginResult(r); - return true; - } - - PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); - r.setKeepCallback(true); - callbackContext.sendPluginResult(r); - - return true; - } - return false; - } - - //-------------------------------------------------------------------------- - // LOCAL METHODS - //-------------------------------------------------------------------------- - - private String getTempDirectoryPath() { - File cache = null; - - // SD Card Mounted - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - cache = cordova.getActivity().getExternalCacheDir(); - } - // Use internal storage - else { - cache = cordova.getActivity().getCacheDir(); - } - - // Create the cache directory if it doesn't exist - cache.mkdirs(); - return cache.getAbsolutePath(); - } - - /** - * Take a picture with the camera. - * When an image is captured or the camera view is cancelled, the result is returned - * in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult. - * - * The image can either be returned as a base64 string or a URI that points to the file. - * To display base64 string in an img tag, set the source to: - * img.src="data:image/jpeg;base64,"+result; - * or to display URI in an img tag - * img.src=result; - * - * @param returnType Set the type of image to return. - * @param encodingType Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) - */ - public void callTakePicture(int returnType, int encodingType) { - boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) - && PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); - boolean takePicturePermission = PermissionHelper.hasPermission(this, Manifest.permission.CAMERA); - - // CB-10120: The CAMERA permission does not need to be requested unless it is declared - // in AndroidManifest.xml. This plugin does not declare it, but others may and so we must - // check the package info to determine if the permission is present. - - if (!takePicturePermission) { - takePicturePermission = true; - try { - PackageManager packageManager = this.cordova.getActivity().getPackageManager(); - String[] permissionsInPackage = packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions; - if (permissionsInPackage != null) { - for (String permission : permissionsInPackage) { - if (permission.equals(Manifest.permission.CAMERA)) { - takePicturePermission = false; - break; - } - } - } - } catch (NameNotFoundException e) { - // We are requesting the info for our package, so this should - // never be caught - } - } - - if (takePicturePermission && saveAlbumPermission) { - takePicture(returnType, encodingType); - } else if (saveAlbumPermission && !takePicturePermission) { - PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA); - } else if (!saveAlbumPermission && takePicturePermission) { - PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}); - } else { - PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions); - } - } - - public void takePicture(int returnType, int encodingType) - { - // Save the number of images currently on disk for later - this.numPics = queryImgDB(whichContentStore()).getCount(); - - // Let's use the intent and see what happens - Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - - // Specify file so that large image is captured and returned - File photo = createCaptureFile(encodingType); - this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(), - applicationId + ".provider", - photo)); - intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri()); - //We can write to this URI, this will hopefully allow us to write files to get to the next step - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - - if (this.cordova != null) { - // Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code) - PackageManager mPm = this.cordova.getActivity().getPackageManager(); - if(intent.resolveActivity(mPm) != null) - { - - this.cordova.startActivityForResult((CordovaPlugin) this, intent, (CAMERA + 1) * 16 + returnType + 1); - } - else - { - LOG.d(LOG_TAG, "Error: You don't have a default camera. Your device may not be CTS complaint."); - } - } -// else -// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); - } - - /** - * Create a file in the applications temporary directory based upon the supplied encoding. - * - * @param encodingType of the image to be taken - * @return a File object pointing to the temporary picture - */ - private File createCaptureFile(int encodingType) { - return createCaptureFile(encodingType, ""); - } - - /** - * Create a file in the applications temporary directory based upon the supplied encoding. - * - * @param encodingType of the image to be taken - * @param fileName or resultant File object. - * @return a File object pointing to the temporary picture - */ - private File createCaptureFile(int encodingType, String fileName) { - if (fileName.isEmpty()) { - fileName = ".Pic"; - } - - if (encodingType == JPEG) { - fileName = fileName + ".jpg"; - } else if (encodingType == PNG) { - fileName = fileName + ".png"; - } else { - throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); - } - - return new File(getTempDirectoryPath(), fileName); - } - - - - /** - * Get image from photo library. - * - * @param srcType The album to get image from. - * @param returnType Set the type of image to return. - * @param encodingType - */ - // TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do! - // TODO: Images from kitkat filechooser not going into crop function - public void getImage(int srcType, int returnType, int encodingType) { - Intent intent = new Intent(); - String title = GET_PICTURE; - croppedUri = null; - if (this.mediaType == PICTURE) { - intent.setType("image/*"); - if (this.allowEdit) { - intent.setAction(Intent.ACTION_PICK); - intent.putExtra("crop", "true"); - if (targetWidth > 0) { - intent.putExtra("outputX", targetWidth); - } - if (targetHeight > 0) { - intent.putExtra("outputY", targetHeight); - } - if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) { - intent.putExtra("aspectX", 1); - intent.putExtra("aspectY", 1); - } - File photo = createCaptureFile(JPEG); - croppedUri = Uri.fromFile(photo); - intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, croppedUri); - } else { - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - } - } else if (this.mediaType == VIDEO) { - intent.setType("video/*"); - title = GET_VIDEO; - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - } else if (this.mediaType == ALLMEDIA) { - // I wanted to make the type 'image/*, video/*' but this does not work on all versions - // of android so I had to go with the wildcard search. - intent.setType("*/*"); - title = GET_All; - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - } - if (this.cordova != null) { - this.cordova.startActivityForResult((CordovaPlugin) this, Intent.createChooser(intent, - new String(title)), (srcType + 1) * 16 + returnType + 1); - } - } - - - /** - * Brings up the UI to perform crop on passed image URI - * - * @param picUri - */ - private void performCrop(Uri picUri, int destType, Intent cameraIntent) { - try { - Intent cropIntent = new Intent("com.android.camera.action.CROP"); - // indicate image type and Uri - cropIntent.setDataAndType(picUri, "image/*"); - // set crop properties - cropIntent.putExtra("crop", "true"); - - - // indicate output X and Y - if (targetWidth > 0) { - cropIntent.putExtra("outputX", targetWidth); - } - if (targetHeight > 0) { - cropIntent.putExtra("outputY", targetHeight); - } - if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) { - cropIntent.putExtra("aspectX", 1); - cropIntent.putExtra("aspectY", 1); - } - // create new file handle to get full resolution crop - croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); - cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - cropIntent.putExtra("output", croppedUri); - - - // start the activity - we handle returning in onActivityResult - - if (this.cordova != null) { - this.cordova.startActivityForResult((CordovaPlugin) this, - cropIntent, CROP_CAMERA + destType); - } - } catch (ActivityNotFoundException anfe) { - LOG.e(LOG_TAG, "Crop operation not supported on this device"); - try { - processResultFromCamera(destType, cameraIntent); - } - catch (IOException e) - { - e.printStackTrace(); - LOG.e(LOG_TAG, "Unable to write to file"); - } - } - } - - /** - * Applies all needed transformation to the image received from the camera. - * - * @param destType In which form should we return the image - * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). - */ - private void processResultFromCamera(int destType, Intent intent) throws IOException { - int rotate = 0; - - // Create an ExifHelper to save the exif data that is lost during compression - ExifHelper exif = new ExifHelper(); - - String sourcePath = (this.allowEdit && this.croppedUri != null) ? - FileHelper.stripFileProtocol(this.croppedUri.toString()) : - this.imageUri.getFilePath(); - - - if (this.encodingType == JPEG) { - try { - //We don't support PNG, so let's not pretend we do - exif.createInFile(sourcePath); - exif.readExifData(); - rotate = exif.getOrientation(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - Bitmap bitmap = null; - Uri galleryUri = null; - - // CB-5479 When this option is given the unchanged image should be saved - // in the gallery and the modified image is saved in the temporary - // directory - if (this.saveToPhotoAlbum) { - galleryUri = Uri.fromFile(new File(getPicturesPath())); - - if (this.allowEdit && this.croppedUri != null) { - writeUncompressedImage(croppedUri, galleryUri); - } else { - Uri imageUri = this.imageUri.getFileUri(); - writeUncompressedImage(imageUri, galleryUri); - } - - refreshGallery(galleryUri); - } - - // If sending base64 image back - if (destType == DATA_URL) { - bitmap = getScaledAndRotatedBitmap(sourcePath); - - if (bitmap == null) { - // Try to get the bitmap from intent. - bitmap = (Bitmap) intent.getExtras().get("data"); - } - - // Double-check the bitmap. - if (bitmap == null) { - LOG.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to create bitmap!"); - return; - } - - - this.processPicture(bitmap, this.encodingType); - - if (!this.saveToPhotoAlbum) { - checkForDuplicateImage(DATA_URL); - } - } - - // If sending filename back - else if (destType == FILE_URI || destType == NATIVE_URI) { - // If all this is true we shouldn't compress the image. - if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 && - !this.correctOrientation) { - - // If we saved the uncompressed photo to the album, we can just - // return the URI we already created - if (this.saveToPhotoAlbum) { - this.callbackContext.success(galleryUri.toString()); - } else { - Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); - - if (this.allowEdit && this.croppedUri != null) { - Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri))); - writeUncompressedImage(croppedUri, uri); - } else { - Uri imageUri = this.imageUri.getFileUri(); - writeUncompressedImage(imageUri, uri); - } - - this.callbackContext.success(uri.toString()); - } - } else { - Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + "")); - bitmap = getScaledAndRotatedBitmap(sourcePath); - - // Double-check the bitmap. - if (bitmap == null) { - LOG.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to create bitmap!"); - return; - } - - - // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); - CompressFormat compressFormat = encodingType == JPEG ? - CompressFormat.JPEG : - CompressFormat.PNG; - - bitmap.compress(compressFormat, this.mQuality, os); - os.close(); - - // Restore exif data to file - if (this.encodingType == JPEG) { - String exifPath; - exifPath = uri.getPath(); - //We just finished rotating it by an arbitrary orientation, just make sure it's normal - if(rotate != ExifInterface.ORIENTATION_NORMAL) - exif.resetOrientation(); - exif.createOutFile(exifPath); - exif.writeExifData(); - } - - // Send Uri back to JavaScript for viewing image - this.callbackContext.success(uri.toString()); - - } - } else { - throw new IllegalStateException(); - } - - this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap); - bitmap = null; - } - - private String getPicturesPath() { - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); - File storageDir = Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES); - storageDir.mkdirs(); - String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName; - return galleryPath; - } - - private void refreshGallery(Uri contentUri) { - Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - mediaScanIntent.setData(contentUri); - this.cordova.getActivity().sendBroadcast(mediaScanIntent); - } - - /** - * Converts output image format int value to string value of mime type. - * @param outputFormat int Output format of camera API. - * Must be value of either JPEG or PNG constant - * @return String String value of mime type or empty string if mime type is not supported - */ - private String getMimetypeForFormat(int outputFormat) { - if (outputFormat == PNG) return "image/png"; - if (outputFormat == JPEG) return "image/jpeg"; - return ""; - } - - - private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException { - // Some content: URIs do not map to file paths (e.g. picasa). - String realPath = FileHelper.getRealPath(uri, this.cordova); - - // Get filename from uri - String fileName = realPath != null ? - realPath.substring(realPath.lastIndexOf('/') + 1) : - "modified." + (this.encodingType == JPEG ? "jpg" : "png"); - - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - //String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); - String modifiedPath = getTempDirectoryPath() + "/" + fileName; - - OutputStream os = new FileOutputStream(modifiedPath); - CompressFormat compressFormat = this.encodingType == JPEG ? - CompressFormat.JPEG : - CompressFormat.PNG; - - bitmap.compress(compressFormat, this.mQuality, os); - os.close(); - - if (exifData != null && this.encodingType == JPEG) { - try { - if (this.correctOrientation && this.orientationCorrected) { - exifData.resetOrientation(); - } - exifData.createOutFile(modifiedPath); - exifData.writeExifData(); - exifData = null; - } catch (IOException e) { - e.printStackTrace(); - } - } - return modifiedPath; - } - - - /** - * Applies all needed transformation to the image received from the gallery. - * - * @param destType In which form should we return the image - * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). - */ - private void processResultFromGallery(int destType, Intent intent) { - Uri uri = intent.getData(); - if (uri == null) { - if (croppedUri != null) { - uri = croppedUri; - } else { - this.failPicture("null data from photo library"); - return; - } - } - int rotate = 0; - - String fileLocation = FileHelper.getRealPath(uri, this.cordova); - LOG.d(LOG_TAG, "File locaton is: " + fileLocation); - - // If you ask for video or all media type you will automatically get back a file URI - // and there will be no attempt to resize any returned data - if (this.mediaType != PICTURE) { - this.callbackContext.success(fileLocation); - } - else { - String uriString = uri.toString(); - // Get the path to the image. Makes loading so much easier. - String mimeType = FileHelper.getMimeType(uriString, this.cordova); - - // This is a special case to just return the path as no scaling, - // rotating, nor compressing needs to be done - if (this.targetHeight == -1 && this.targetWidth == -1 && - (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation && - mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType))) - { - this.callbackContext.success(uriString); - } else { - // If we don't have a valid image so quit. - if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) { - LOG.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to retrieve path to picture!"); - return; - } - Bitmap bitmap = null; - try { - bitmap = getScaledAndRotatedBitmap(uriString); - } catch (IOException e) { - e.printStackTrace(); - } - if (bitmap == null) { - LOG.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to create bitmap!"); - return; - } - - // If sending base64 image back - if (destType == DATA_URL) { - this.processPicture(bitmap, this.encodingType); - } - - // If sending filename back - else if (destType == FILE_URI || destType == NATIVE_URI) { - // Did we modify the image? - if ( (this.targetHeight > 0 && this.targetWidth > 0) || - (this.correctOrientation && this.orientationCorrected) || - !mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType))) - { - try { - String modifiedPath = this.outputModifiedBitmap(bitmap, uri); - // The modified image is cached by the app in order to get around this and not have to delete you - // application cache I'm adding the current system time to the end of the file url. - this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis()); - - } catch (Exception e) { - e.printStackTrace(); - this.failPicture("Error retrieving image."); - } - } else { - this.callbackContext.success(fileLocation); - } - } - if (bitmap != null) { - bitmap.recycle(); - bitmap = null; - } - System.gc(); - } - } - } - - /** - * Called when the camera view exits. - * - * @param requestCode The request code originally supplied to startActivityForResult(), - * allowing you to identify who this result came from. - * @param resultCode The integer result code returned by the child activity through its setResult(). - * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). - */ - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - - // Get src and dest types from request code for a Camera Activity - int srcType = (requestCode / 16) - 1; - int destType = (requestCode % 16) - 1; - - // If Camera Crop - if (requestCode >= CROP_CAMERA) { - if (resultCode == Activity.RESULT_OK) { - - // Because of the inability to pass through multiple intents, this hack will allow us - // to pass arcane codes back. - destType = requestCode - CROP_CAMERA; - try { - processResultFromCamera(destType, intent); - } catch (IOException e) { - e.printStackTrace(); - LOG.e(LOG_TAG, "Unable to write to file"); - } - - }// If cancelled - else if (resultCode == Activity.RESULT_CANCELED) { - this.failPicture("No Image Selected"); - } - - // If something else - else { - this.failPicture("Did not complete!"); - } - } - // If CAMERA - else if (srcType == CAMERA) { - // If image available - if (resultCode == Activity.RESULT_OK) { - try { - if (this.allowEdit) { - Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(), - applicationId + ".provider", - createCaptureFile(this.encodingType)); - performCrop(tmpFile, destType, intent); - } else { - this.processResultFromCamera(destType, intent); - } - } catch (IOException e) { - e.printStackTrace(); - this.failPicture("Error capturing image."); - } - } - - // If cancelled - else if (resultCode == Activity.RESULT_CANCELED) { - this.failPicture("No Image Selected"); - } - - // If something else - else { - this.failPicture("Did not complete!"); - } - } - // If retrieving photo from library - else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) { - if (resultCode == Activity.RESULT_OK && intent != null) { - final Intent i = intent; - final int finalDestType = destType; - cordova.getThreadPool().execute(new Runnable() { - public void run() { - processResultFromGallery(finalDestType, i); - } - }); - } else if (resultCode == Activity.RESULT_CANCELED) { - this.failPicture("No Image Selected"); - } else { - this.failPicture("Selection did not complete!"); - } - } - } - - private int exifToDegrees(int exifOrientation) { - if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { - return 90; - } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { - return 180; - } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { - return 270; - } else { - return 0; - } - } - - /** - * Write an inputstream to local disk - * - * @param fis - The InputStream to write - * @param dest - Destination on disk to write to - * @throws FileNotFoundException - * @throws IOException - */ - private void writeUncompressedImage(InputStream fis, Uri dest) throws FileNotFoundException, - IOException { - OutputStream os = null; - try { - os = this.cordova.getActivity().getContentResolver().openOutputStream(dest); - byte[] buffer = new byte[4096]; - int len; - while ((len = fis.read(buffer)) != -1) { - os.write(buffer, 0, len); - } - os.flush(); - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - LOG.d(LOG_TAG, "Exception while closing output stream."); - } - } - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - LOG.d(LOG_TAG, "Exception while closing file input stream."); - } - } - } - } - /** - * In the special case where the default width, height and quality are unchanged - * we just write the file out to disk saving the expensive Bitmap.compress function. - * - * @param src - * @throws FileNotFoundException - * @throws IOException - */ - private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException, - IOException { - - FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString())); - writeUncompressedImage(fis, dest); - - } - - /** - * Create entry in media store for image - * - * @return uri - */ - private Uri getUriFromMediaStore() { - ContentValues values = new ContentValues(); - values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - Uri uri; - try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - } catch (RuntimeException e) { - LOG.d(LOG_TAG, "Can't write to external media storage."); - try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); - } catch (RuntimeException ex) { - LOG.d(LOG_TAG, "Can't write to internal media storage."); - return null; - } - } - return uri; - } - - /** - * Return a scaled and rotated bitmap based on the target width and height - * - * @param imageUrl - * @return - * @throws IOException - */ - private Bitmap getScaledAndRotatedBitmap(String imageUrl) throws IOException { - // If no new width or height were specified, and orientation is not needed return the original bitmap - if (this.targetWidth <= 0 && this.targetHeight <= 0 && !(this.correctOrientation)) { - InputStream fileStream = null; - Bitmap image = null; - try { - fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova); - image = BitmapFactory.decodeStream(fileStream); - } catch (OutOfMemoryError e) { - callbackContext.error(e.getLocalizedMessage()); - } catch (Exception e){ - callbackContext.error(e.getLocalizedMessage()); - } - finally { - if (fileStream != null) { - try { - fileStream.close(); - } catch (IOException e) { - LOG.d(LOG_TAG, "Exception while closing file input stream."); - } - } - } - return image; - } - - - /* Copy the inputstream to a temporary file on the device. - We then use this temporary file to determine the width/height/orientation. - This is the only way to determine the orientation of the photo coming from 3rd party providers (Google Drive, Dropbox,etc) - This also ensures we create a scaled bitmap with the correct orientation - - We delete the temporary file once we are done - */ - File localFile = null; - Uri galleryUri = null; - int rotate = 0; - try { - InputStream fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova); - if (fileStream != null) { - // Generate a temporary file - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png"); - localFile = new File(getTempDirectoryPath() + fileName); - galleryUri = Uri.fromFile(localFile); - writeUncompressedImage(fileStream, galleryUri); - try { - String mimeType = FileHelper.getMimeType(imageUrl.toString(), cordova); - if ("image/jpeg".equalsIgnoreCase(mimeType)) { - // ExifInterface doesn't like the file:// prefix - String filePath = galleryUri.toString().replace("file://", ""); - // read exifData of source - exifData = new ExifHelper(); - exifData.createInFile(filePath); - // Use ExifInterface to pull rotation information - if (this.correctOrientation) { - ExifInterface exif = new ExifInterface(filePath); - rotate = exifToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)); - } - } - } catch (Exception oe) { - LOG.w(LOG_TAG,"Unable to read Exif data: "+ oe.toString()); - rotate = 0; - } - } - } - catch (Exception e) - { - LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString()); - return null; - } - - - - try { - // figure out the original width and height of the image - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - InputStream fileStream = null; - try { - fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova); - BitmapFactory.decodeStream(fileStream, null, options); - } finally { - if (fileStream != null) { - try { - fileStream.close(); - } catch (IOException e) { - LOG.d(LOG_TAG, "Exception while closing file input stream."); - } - } - } - - - //CB-2292: WTF? Why is the width null? - if (options.outWidth == 0 || options.outHeight == 0) { - return null; - } - - // User didn't specify output dimensions, but they need orientation - if (this.targetWidth <= 0 && this.targetHeight <= 0) { - this.targetWidth = options.outWidth; - this.targetHeight = options.outHeight; - } - - // Setup target width/height based on orientation - int rotatedWidth, rotatedHeight; - boolean rotated= false; - if (rotate == 90 || rotate == 270) { - rotatedWidth = options.outHeight; - rotatedHeight = options.outWidth; - rotated = true; - } else { - rotatedWidth = options.outWidth; - rotatedHeight = options.outHeight; - } - - // determine the correct aspect ratio - int[] widthHeight = calculateAspectRatio(rotatedWidth, rotatedHeight); - - - // Load in the smallest bitmap possible that is closest to the size we want - options.inJustDecodeBounds = false; - options.inSampleSize = calculateSampleSize(rotatedWidth, rotatedHeight, widthHeight[0], widthHeight[1]); - Bitmap unscaledBitmap = null; - try { - fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova); - unscaledBitmap = BitmapFactory.decodeStream(fileStream, null, options); - } finally { - if (fileStream != null) { - try { - fileStream.close(); - } catch (IOException e) { - LOG.d(LOG_TAG, "Exception while closing file input stream."); - } - } - } - if (unscaledBitmap == null) { - return null; - } - - int scaledWidth = (!rotated) ? widthHeight[0] : widthHeight[1]; - int scaledHeight = (!rotated) ? widthHeight[1] : widthHeight[0]; - - Bitmap scaledBitmap = Bitmap.createScaledBitmap(unscaledBitmap, scaledWidth, scaledHeight, true); - if (scaledBitmap != unscaledBitmap) { - unscaledBitmap.recycle(); - unscaledBitmap = null; - } - if (this.correctOrientation && (rotate != 0)) { - Matrix matrix = new Matrix(); - matrix.setRotate(rotate); - try { - scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true); - this.orientationCorrected = true; - } catch (OutOfMemoryError oom) { - this.orientationCorrected = false; - } - } - return scaledBitmap; - } - finally { - // delete the temporary copy - if (localFile != null) { - localFile.delete(); - } - } - - } - - /** - * Maintain the aspect ratio so the resulting image does not look smooshed - * - * @param origWidth - * @param origHeight - * @return - */ - public int[] calculateAspectRatio(int origWidth, int origHeight) { - int newWidth = this.targetWidth; - int newHeight = this.targetHeight; - - // If no new width or height were specified return the original bitmap - if (newWidth <= 0 && newHeight <= 0) { - newWidth = origWidth; - newHeight = origHeight; - } - // Only the width was specified - else if (newWidth > 0 && newHeight <= 0) { - newHeight = (int)((double)(newWidth / (double)origWidth) * origHeight); - } - // only the height was specified - else if (newWidth <= 0 && newHeight > 0) { - newWidth = (int)((double)(newHeight / (double)origHeight) * origWidth); - } - // If the user specified both a positive width and height - // (potentially different aspect ratio) then the width or height is - // scaled so that the image fits while maintaining aspect ratio. - // Alternatively, the specified width and height could have been - // kept and Bitmap.SCALE_TO_FIT specified when scaling, but this - // would result in whitespace in the new image. - else { - double newRatio = newWidth / (double) newHeight; - double origRatio = origWidth / (double) origHeight; - - if (origRatio > newRatio) { - newHeight = (newWidth * origHeight) / origWidth; - } else if (origRatio < newRatio) { - newWidth = (newHeight * origWidth) / origHeight; - } - } - - int[] retval = new int[2]; - retval[0] = newWidth; - retval[1] = newHeight; - return retval; - } - - /** - * Figure out what ratio we can load our image into memory at while still being bigger than - * our desired width and height - * - * @param srcWidth - * @param srcHeight - * @param dstWidth - * @param dstHeight - * @return - */ - public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight) { - final float srcAspect = (float) srcWidth / (float) srcHeight; - final float dstAspect = (float) dstWidth / (float) dstHeight; - - if (srcAspect > dstAspect) { - return srcWidth / dstWidth; - } else { - return srcHeight / dstHeight; - } - } - - /** - * Creates a cursor that can be used to determine how many images we have. - * - * @return a cursor - */ - private Cursor queryImgDB(Uri contentStore) { - return this.cordova.getActivity().getContentResolver().query( - contentStore, - new String[]{MediaStore.Images.Media._ID}, - null, - null, - null); - } - - /** - * Cleans up after picture taking. Checking for duplicates and that kind of stuff. - * - * @param newImage - */ - private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) { - if (bitmap != null) { - bitmap.recycle(); - } - - // Clean up initial camera-written image file. - (new File(FileHelper.stripFileProtocol(oldImage.toString()))).delete(); - - checkForDuplicateImage(imageType); - // Scan for the gallery to update pic refs in gallery - if (this.saveToPhotoAlbum && newImage != null) { - this.scanForGallery(newImage); - } - - System.gc(); - } - - /** - * Used to find out if we are in a situation where the Camera Intent adds to images - * to the content store. If we are using a FILE_URI and the number of images in the DB - * increases by 2 we have a duplicate, when using a DATA_URL the number is 1. - * - * @param type FILE_URI or DATA_URL - */ - private void checkForDuplicateImage(int type) { - int diff = 1; - Uri contentStore = whichContentStore(); - Cursor cursor = queryImgDB(contentStore); - int currentNumOfImages = cursor.getCount(); - - if (type == FILE_URI && this.saveToPhotoAlbum) { - diff = 2; - } - - // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL - if ((currentNumOfImages - numPics) == diff) { - cursor.moveToLast(); - int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))); - if (diff == 2) { - id--; - } - Uri uri = Uri.parse(contentStore + "/" + id); - this.cordova.getActivity().getContentResolver().delete(uri, null, null); - cursor.close(); - } - } - - /** - * Determine if we are storing the images in internal or external storage - * - * @return Uri - */ - private Uri whichContentStore() { - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - return android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else { - return android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI; - } - } - - /** - * Compress bitmap using jpeg, convert to Base64 encoded string, and return to JavaScript. - * - * @param bitmap - */ - public void processPicture(Bitmap bitmap, int encodingType) { - ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream(); - CompressFormat compressFormat = encodingType == JPEG ? - CompressFormat.JPEG : - CompressFormat.PNG; - - try { - if (bitmap.compress(compressFormat, mQuality, jpeg_data)) { - byte[] code = jpeg_data.toByteArray(); - byte[] output = Base64.encode(code, Base64.NO_WRAP); - String js_out = new String(output); - this.callbackContext.success(js_out); - js_out = null; - output = null; - code = null; - } - } catch (Exception e) { - this.failPicture("Error compressing image."); - } - jpeg_data = null; - } - - /** - * Send error message to JavaScript. - * - * @param err - */ - public void failPicture(String err) { - this.callbackContext.error(err); - } - - private void scanForGallery(Uri newImage) { - this.scanMe = newImage; - if (this.conn != null) { - this.conn.disconnect(); - } - this.conn = new MediaScannerConnection(this.cordova.getActivity().getApplicationContext(), this); - conn.connect(); - } - - public void onMediaScannerConnected() { - try { - this.conn.scanFile(this.scanMe.toString(), "image/*"); - } catch (java.lang.IllegalStateException e) { - LOG.e(LOG_TAG, "Can't scan file in MediaScanner after taking picture"); - } - - } - - public void onScanCompleted(String path, Uri uri) { - this.conn.disconnect(); - } - - - public void onRequestPermissionResult(int requestCode, String[] permissions, - int[] grantResults) throws JSONException { - for (int r : grantResults) { - if (r == PackageManager.PERMISSION_DENIED) { - this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR)); - return; - } - } - switch (requestCode) { - case TAKE_PIC_SEC: - takePicture(this.destType, this.encodingType); - break; - case SAVE_TO_ALBUM_SEC: - this.getImage(this.srcType, this.destType, this.encodingType); - break; - } - } - - /** - * Taking or choosing a picture launches another Activity, so we need to implement the - * save/restore APIs to handle the case where the CordovaActivity is killed by the OS - * before we get the launched Activity's result. - */ - public Bundle onSaveInstanceState() { - Bundle state = new Bundle(); - state.putInt("destType", this.destType); - state.putInt("srcType", this.srcType); - state.putInt("mQuality", this.mQuality); - state.putInt("targetWidth", this.targetWidth); - state.putInt("targetHeight", this.targetHeight); - state.putInt("encodingType", this.encodingType); - state.putInt("mediaType", this.mediaType); - state.putInt("numPics", this.numPics); - state.putBoolean("allowEdit", this.allowEdit); - state.putBoolean("correctOrientation", this.correctOrientation); - state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum); - - if (this.croppedUri != null) { - state.putString("croppedUri", this.croppedUri.toString()); - } - - if (this.imageUri != null) { - state.putString("imageUri", this.imageUri.getFileUri().toString()); - } - - return state; - } - - public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) { - this.destType = state.getInt("destType"); - this.srcType = state.getInt("srcType"); - this.mQuality = state.getInt("mQuality"); - this.targetWidth = state.getInt("targetWidth"); - this.targetHeight = state.getInt("targetHeight"); - this.encodingType = state.getInt("encodingType"); - this.mediaType = state.getInt("mediaType"); - this.numPics = state.getInt("numPics"); - this.allowEdit = state.getBoolean("allowEdit"); - this.correctOrientation = state.getBoolean("correctOrientation"); - this.saveToPhotoAlbum = state.getBoolean("saveToPhotoAlbum"); - - if (state.containsKey("croppedUri")) { - this.croppedUri = Uri.parse(state.getString("croppedUri")); - } - - if (state.containsKey("imageUri")) { - //I have no idea what type of URI is being passed in - this.imageUri = new CordovaUri(Uri.parse(state.getString("imageUri"))); - } - - this.callbackContext = callbackContext; - } - - /* - * This is dirty, but it does the job. - * - * Since the FilesProvider doesn't really provide you a way of getting a URL from the file, - * and since we actually need the Camera to create the file for us most of the time, we don't - * actually write the file, just generate the location based on a timestamp, we need to get it - * back from the Intent. - * - * However, the FilesProvider preserves the path, so we can at least write to it from here, since - * we own the context in this case. - */ - - private String getFileNameFromUri(Uri uri) { - String fullUri = uri.toString(); - String partial_path = fullUri.split("external_files")[1]; - File external_storage = Environment.getExternalStorageDirectory(); - String path = external_storage.getAbsolutePath() + partial_path; - return path; - - } - - -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java deleted file mode 100755 index 5c2224d4..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -package org.apache.cordova.camera; - -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.support.v4.content.FileProvider; - -import java.io.File; - -/* - * This class exists because Andorid FilesProvider doesn't work on Android 4.4.4 and below and throws - * weird errors. I'm not sure why writing to shared cache directories is somehow verboten, but it is - * and this error is irritating for a Compatibility library to have. - * - */ - -public class CordovaUri { - - private Uri androidUri; - private String fileName; - private Uri fileUri; - - /* - * We always expect a FileProvider string to be passed in for the file that we create - * - */ - CordovaUri (Uri inputUri) - { - //Determine whether the file is a content or file URI - if(inputUri.getScheme().equals("content")) - { - androidUri = inputUri; - fileName = getFileNameFromUri(androidUri); - fileUri = Uri.parse("file://" + fileName); - } - else - { - fileUri = inputUri; - fileName = FileHelper.stripFileProtocol(inputUri.toString()); - } - } - - public Uri getFileUri() - { - return fileUri; - } - - public String getFilePath() - { - return fileName; - } - - /* - * This only gets called by takePicture - */ - - public Uri getCorrectUri() - { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - return androidUri; - else - return fileUri; - } - - /* - * This is dirty, but it does the job. - * - * Since the FilesProvider doesn't really provide you a way of getting a URL from the file, - * and since we actually need the Camera to create the file for us most of the time, we don't - * actually write the file, just generate the location based on a timestamp, we need to get it - * back from the Intent. - * - * However, the FilesProvider preserves the path, so we can at least write to it from here, since - * we own the context in this case. - */ - - private String getFileNameFromUri(Uri uri) { - String fullUri = uri.toString(); - String partial_path = fullUri.split("external_files")[1]; - File external_storage = Environment.getExternalStorageDirectory(); - String path = external_storage.getAbsolutePath() + partial_path; - return path; - - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java deleted file mode 100755 index 5160a2f6..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.camera; - -import java.io.IOException; - -import android.media.ExifInterface; - -public class ExifHelper { - private String aperture = null; - private String datetime = null; - private String exposureTime = null; - private String flash = null; - private String focalLength = null; - private String gpsAltitude = null; - private String gpsAltitudeRef = null; - private String gpsDateStamp = null; - private String gpsLatitude = null; - private String gpsLatitudeRef = null; - private String gpsLongitude = null; - private String gpsLongitudeRef = null; - private String gpsProcessingMethod = null; - private String gpsTimestamp = null; - private String iso = null; - private String make = null; - private String model = null; - private String orientation = null; - private String whiteBalance = null; - - private ExifInterface inFile = null; - private ExifInterface outFile = null; - - /** - * The file before it is compressed - * - * @param filePath - * @throws IOException - */ - public void createInFile(String filePath) throws IOException { - this.inFile = new ExifInterface(filePath); - } - - /** - * The file after it has been compressed - * - * @param filePath - * @throws IOException - */ - public void createOutFile(String filePath) throws IOException { - this.outFile = new ExifInterface(filePath); - } - - /** - * Reads all the EXIF data from the input file. - */ - public void readExifData() { - this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE); - this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME); - this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME); - this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH); - this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH); - this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE); - this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF); - this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP); - this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE); - this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); - this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); - this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); - this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD); - this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP); - this.iso = inFile.getAttribute(ExifInterface.TAG_ISO); - this.make = inFile.getAttribute(ExifInterface.TAG_MAKE); - this.model = inFile.getAttribute(ExifInterface.TAG_MODEL); - this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION); - this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE); - } - - /** - * Writes the previously stored EXIF data to the output file. - * - * @throws IOException - */ - public void writeExifData() throws IOException { - // Don't try to write to a null file - if (this.outFile == null) { - return; - } - - if (this.aperture != null) { - this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture); - } - if (this.datetime != null) { - this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime); - } - if (this.exposureTime != null) { - this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime); - } - if (this.flash != null) { - this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash); - } - if (this.focalLength != null) { - this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength); - } - if (this.gpsAltitude != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude); - } - if (this.gpsAltitudeRef != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef); - } - if (this.gpsDateStamp != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp); - } - if (this.gpsLatitude != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude); - } - if (this.gpsLatitudeRef != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef); - } - if (this.gpsLongitude != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude); - } - if (this.gpsLongitudeRef != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef); - } - if (this.gpsProcessingMethod != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod); - } - if (this.gpsTimestamp != null) { - this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp); - } - if (this.iso != null) { - this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso); - } - if (this.make != null) { - this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make); - } - if (this.model != null) { - this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model); - } - if (this.orientation != null) { - this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation); - } - if (this.whiteBalance != null) { - this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance); - } - - this.outFile.saveAttributes(); - } - - public int getOrientation() { - int o = Integer.parseInt(this.orientation); - - if (o == ExifInterface.ORIENTATION_NORMAL) { - return 0; - } else if (o == ExifInterface.ORIENTATION_ROTATE_90) { - return 90; - } else if (o == ExifInterface.ORIENTATION_ROTATE_180) { - return 180; - } else if (o == ExifInterface.ORIENTATION_ROTATE_270) { - return 270; - } else { - return 0; - } - } - - public void resetOrientation() { - this.orientation = "" + ExifInterface.ORIENTATION_NORMAL; - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java deleted file mode 100755 index ccc5e3e7..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ -package org.apache.cordova.camera; - -import android.annotation.SuppressLint; -import android.content.ContentUris; -import android.content.Context; -import android.content.CursorLoader; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.webkit.MimeTypeMap; - -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.LOG; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -public class FileHelper { - private static final String LOG_TAG = "FileUtils"; - private static final String _DATA = "_data"; - - /** - * Returns the real path of the given URI string. - * If the given URI string represents a content:// URI, the real path is retrieved from the media store. - * - * @param uriString the URI string of the audio/image/video - * @param cordova the current application context - * @return the full path to the file - */ - @SuppressWarnings("deprecation") - public static String getRealPath(Uri uri, CordovaInterface cordova) { - String realPath = null; - - if (Build.VERSION.SDK_INT < 11) - realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri); - - // SDK >= 11 - else - realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri); - - return realPath; - } - - /** - * Returns the real path of the given URI. - * If the given URI is a content:// URI, the real path is retrieved from the media store. - * - * @param uri the URI of the audio/image/video - * @param cordova the current application context - * @return the full path to the file - */ - public static String getRealPath(String uriString, CordovaInterface cordova) { - return FileHelper.getRealPath(Uri.parse(uriString), cordova); - } - - @SuppressLint("NewApi") - public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) { - - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } - // DownloadsProvider - else if (isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - - return getDataColumn(context, contentUri, null, null); - } - // MediaProvider - else if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[] { - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - - // Return the remote address - if (isGooglePhotosUri(uri)) - return uri.getLastPathSegment(); - - return getDataColumn(context, uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - - return null; - } - - public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) { - String[] proj = { MediaStore.Images.Media.DATA }; - String result = null; - - try { - Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null); - int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - result = cursor.getString(column_index); - - } catch (Exception e) { - result = null; - } - return result; - } - - /** - * Returns an input stream based on given URI string. - * - * @param uriString the URI string from which to obtain the input stream - * @param cordova the current application context - * @return an input stream into the data at the given URI or null if given an invalid URI string - * @throws IOException - */ - public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova) - throws IOException { - InputStream returnValue = null; - if (uriString.startsWith("content")) { - Uri uri = Uri.parse(uriString); - returnValue = cordova.getActivity().getContentResolver().openInputStream(uri); - } else if (uriString.startsWith("file://")) { - int question = uriString.indexOf("?"); - if (question > -1) { - uriString = uriString.substring(0, question); - } - if (uriString.startsWith("file:///android_asset/")) { - Uri uri = Uri.parse(uriString); - String relativePath = uri.getPath().substring(15); - returnValue = cordova.getActivity().getAssets().open(relativePath); - } else { - // might still be content so try that first - try { - returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString)); - } catch (Exception e) { - returnValue = null; - } - if (returnValue == null) { - returnValue = new FileInputStream(getRealPath(uriString, cordova)); - } - } - } else { - returnValue = new FileInputStream(uriString); - } - return returnValue; - } - - /** - * Removes the "file://" prefix from the given URI string, if applicable. - * If the given URI string doesn't have a "file://" prefix, it is returned unchanged. - * - * @param uriString the URI string to operate on - * @return a path without the "file://" prefix - */ - public static String stripFileProtocol(String uriString) { - if (uriString.startsWith("file://")) { - uriString = uriString.substring(7); - } - return uriString; - } - - public static String getMimeTypeForExtension(String path) { - String extension = path; - int lastDot = extension.lastIndexOf('.'); - if (lastDot != -1) { - extension = extension.substring(lastDot + 1); - } - // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). - extension = extension.toLowerCase(Locale.getDefault()); - if (extension.equals("3ga")) { - return "audio/3gpp"; - } - return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - } - - /** - * Returns the mime type of the data specified by the given URI string. - * - * @param uriString the URI string of the data - * @return the mime type of the specified data - */ - public static String getMimeType(String uriString, CordovaInterface cordova) { - String mimeType = null; - - Uri uri = Uri.parse(uriString); - if (uriString.startsWith("content://")) { - mimeType = cordova.getActivity().getContentResolver().getType(uri); - } else { - mimeType = getMimeTypeForExtension(uri.getPath()); - } - - return mimeType; - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - * @author paulburke - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, - null); - if (cursor != null && cursor.moveToFirst()) { - - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } catch (Exception e) { - return null; - } finally { - if (cursor != null) - cursor.close(); - } - return null; - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - * @author paulburke - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - * @author paulburke - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - * @author paulburke - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is Google Photos. - */ - public static boolean isGooglePhotosUri(Uri uri) { - return "com.google.android.apps.photos.content".equals(uri.getAuthority()); - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java deleted file mode 100755 index 336f93ce..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.camera; - -public class FileProvider extends android.support.v4.content.FileProvider {} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java b/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java deleted file mode 100755 index e9efcb49..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.device; - -import java.util.TimeZone; - -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaInterface; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.provider.Settings; - -public class Device extends CordovaPlugin { - public static final String TAG = "Device"; - - public static String platform; // Device OS - public static String uuid; // Device UUID - - private static final String ANDROID_PLATFORM = "Android"; - private static final String AMAZON_PLATFORM = "amazon-fireos"; - private static final String AMAZON_DEVICE = "Amazon"; - - /** - * Constructor. - */ - public Device() { - } - - /** - * Sets the context of the Command. This can then be used to do things like - * get file paths associated with the Activity. - * - * @param cordova The context of the main Activity. - * @param webView The CordovaWebView Cordova is running in. - */ - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - Device.uuid = getUuid(); - } - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback id used when calling back into JavaScript. - * @return True if the action was valid, false if not. - */ - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - if ("getDeviceInfo".equals(action)) { - JSONObject r = new JSONObject(); - r.put("uuid", Device.uuid); - r.put("version", this.getOSVersion()); - r.put("platform", this.getPlatform()); - r.put("model", this.getModel()); - r.put("manufacturer", this.getManufacturer()); - r.put("isVirtual", this.isVirtual()); - r.put("serial", this.getSerialNumber()); - callbackContext.success(r); - } - else { - return false; - } - return true; - } - - //-------------------------------------------------------------------------- - // LOCAL METHODS - //-------------------------------------------------------------------------- - - /** - * Get the OS name. - * - * @return - */ - public String getPlatform() { - String platform; - if (isAmazonDevice()) { - platform = AMAZON_PLATFORM; - } else { - platform = ANDROID_PLATFORM; - } - return platform; - } - - /** - * Get the device's Universally Unique Identifier (UUID). - * - * @return - */ - public String getUuid() { - String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); - return uuid; - } - - public String getModel() { - String model = android.os.Build.MODEL; - return model; - } - - public String getProductName() { - String productname = android.os.Build.PRODUCT; - return productname; - } - - public String getManufacturer() { - String manufacturer = android.os.Build.MANUFACTURER; - return manufacturer; - } - - public String getSerialNumber() { - String serial = android.os.Build.SERIAL; - return serial; - } - - /** - * Get the OS version. - * - * @return - */ - public String getOSVersion() { - String osversion = android.os.Build.VERSION.RELEASE; - return osversion; - } - - public String getSDKVersion() { - @SuppressWarnings("deprecation") - String sdkversion = android.os.Build.VERSION.SDK; - return sdkversion; - } - - public String getTimeZoneID() { - TimeZone tz = TimeZone.getDefault(); - return (tz.getID()); - } - - /** - * Function to check if the device is manufactured by Amazon - * - * @return - */ - public boolean isAmazonDevice() { - if (android.os.Build.MANUFACTURER.equals(AMAZON_DEVICE)) { - return true; - } - return false; - } - - public boolean isVirtual() { - return android.os.Build.FINGERPRINT.contains("generic") || - android.os.Build.PRODUCT.contains("sdk"); - } - -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/dialogs/Notification.java b/platforms/android/app/src/main/java/org/apache/cordova/dialogs/Notification.java deleted file mode 100755 index f19bc888..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/dialogs/Notification.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.dialogs; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.LOG; -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.annotation.SuppressLint; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.ProgressDialog; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.media.Ringtone; -import android.media.RingtoneManager; -import android.net.Uri; -import android.widget.EditText; -import android.widget.TextView; - - -/** - * This class provides access to notifications on the device. - * - * Be aware that this implementation gets called on - * navigator.notification.{alert|confirm|prompt}, and that there is a separate - * implementation in org.apache.cordova.CordovaChromeClient that gets - * called on a simple window.{alert|confirm|prompt}. - */ -public class Notification extends CordovaPlugin { - - private static final String LOG_TAG = "Notification"; - - public int confirmResult = -1; - public ProgressDialog spinnerDialog = null; - public ProgressDialog progressDialog = null; - - /** - * Constructor. - */ - public Notification() { - } - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArray of arguments for the plugin. - * @param callbackContext The callback context used when calling back into JavaScript. - * @return True when the action was valid, false otherwise. - */ - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - /* - * Don't run any of these if the current activity is finishing - * in order to avoid android.view.WindowManager$BadTokenException - * crashing the app. Just return true here since false should only - * be returned in the event of an invalid action. - */ - if(this.cordova.getActivity().isFinishing()) return true; - - if (action.equals("beep")) { - this.beep(args.getLong(0)); - } - else if (action.equals("alert")) { - this.alert(args.getString(0), args.getString(1), args.getString(2), callbackContext); - return true; - } - else if (action.equals("confirm")) { - this.confirm(args.getString(0), args.getString(1), args.getJSONArray(2), callbackContext); - return true; - } - else if (action.equals("prompt")) { - this.prompt(args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), callbackContext); - return true; - } - else if (action.equals("activityStart")) { - this.activityStart(args.getString(0), args.getString(1)); - } - else if (action.equals("activityStop")) { - this.activityStop(); - } - else if (action.equals("progressStart")) { - this.progressStart(args.getString(0), args.getString(1)); - } - else if (action.equals("progressValue")) { - this.progressValue(args.getInt(0)); - } - else if (action.equals("progressStop")) { - this.progressStop(); - } - else { - return false; - } - - // Only alert and confirm are async. - callbackContext.success(); - return true; - } - - //-------------------------------------------------------------------------- - // LOCAL METHODS - //-------------------------------------------------------------------------- - - /** - * Beep plays the default notification ringtone. - * - * @param count Number of times to play notification - */ - public void beep(final long count) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - Ringtone notification = RingtoneManager.getRingtone(cordova.getActivity().getBaseContext(), ringtone); - - // If phone is not set to silent mode - if (notification != null) { - for (long i = 0; i < count; ++i) { - notification.play(); - long timeout = 5000; - while (notification.isPlaying() && (timeout > 0)) { - timeout = timeout - 100; - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - } - }); - } - - /** - * Builds and shows a native Android alert with given Strings - * @param message The message the alert should display - * @param title The title of the alert - * @param buttonLabel The label of the button - * @param callbackContext The callback context - */ - public synchronized void alert(final String message, final String title, final String buttonLabel, final CallbackContext callbackContext) { - final CordovaInterface cordova = this.cordova; - - Runnable runnable = new Runnable() { - public void run() { - - AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - dlg.setMessage(message); - dlg.setTitle(title); - dlg.setCancelable(true); - dlg.setPositiveButton(buttonLabel, - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); - } - }); - dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { - public void onCancel(DialogInterface dialog) - { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); - } - }); - - changeTextDirection(dlg); - }; - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - /** - * Builds and shows a native Android confirm dialog with given title, message, buttons. - * This dialog only shows up to 3 buttons. Any labels after that will be ignored. - * The index of the button pressed will be returned to the JavaScript callback identified by callbackId. - * - * @param message The message the dialog should display - * @param title The title of the dialog - * @param buttonLabels A comma separated list of button labels (Up to 3 buttons) - * @param callbackContext The callback context. - */ - public synchronized void confirm(final String message, final String title, final JSONArray buttonLabels, final CallbackContext callbackContext) { - final CordovaInterface cordova = this.cordova; - - Runnable runnable = new Runnable() { - public void run() { - AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - dlg.setMessage(message); - dlg.setTitle(title); - dlg.setCancelable(true); - - // First button - if (buttonLabels.length() > 0) { - try { - dlg.setNegativeButton(buttonLabels.getString(0), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on first button."); - } - } - - // Second button - if (buttonLabels.length() > 1) { - try { - dlg.setNeutralButton(buttonLabels.getString(1), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on second button."); - } - } - - // Third button - if (buttonLabels.length() > 2) { - try { - dlg.setPositiveButton(buttonLabels.getString(2), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on third button."); - } - } - dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { - public void onCancel(DialogInterface dialog) - { - dialog.dismiss(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0)); - } - }); - - changeTextDirection(dlg); - }; - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - /** - * Builds and shows a native Android prompt dialog with given title, message, buttons. - * This dialog only shows up to 3 buttons. Any labels after that will be ignored. - * The following results are returned to the JavaScript callback identified by callbackId: - * buttonIndex Index number of the button selected - * input1 The text entered in the prompt dialog box - * - * @param message The message the dialog should display - * @param title The title of the dialog - * @param buttonLabels A comma separated list of button labels (Up to 3 buttons) - * @param callbackContext The callback context. - */ - public synchronized void prompt(final String message, final String title, final JSONArray buttonLabels, final String defaultText, final CallbackContext callbackContext) { - - final CordovaInterface cordova = this.cordova; - - Runnable runnable = new Runnable() { - public void run() { - final EditText promptInput = new EditText(cordova.getActivity()); - - /* CB-11677 - By default, prompt input text color is set according current theme. - But for some android versions is not visible (for example 5.1.1). - android.R.color.primary_text_light will make text visible on all versions. */ - Resources resources = cordova.getActivity().getResources(); - int promptInputTextColor = resources.getColor(android.R.color.primary_text_light); - promptInput.setTextColor(promptInputTextColor); - promptInput.setText(defaultText); - AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - dlg.setMessage(message); - dlg.setTitle(title); - dlg.setCancelable(true); - - dlg.setView(promptInput); - - final JSONObject result = new JSONObject(); - - // First button - if (buttonLabels.length() > 0) { - try { - dlg.setNegativeButton(buttonLabels.getString(0), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - try { - result.put("buttonIndex",1); - result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on first button.", e); - } - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on first button."); - } - } - - // Second button - if (buttonLabels.length() > 1) { - try { - dlg.setNeutralButton(buttonLabels.getString(1), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - try { - result.put("buttonIndex",2); - result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on second button.", e); - } - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on second button."); - } - } - - // Third button - if (buttonLabels.length() > 2) { - try { - dlg.setPositiveButton(buttonLabels.getString(2), - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - try { - result.put("buttonIndex",3); - result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on third button.", e); - } - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); - } - }); - } catch (JSONException e) { - LOG.d(LOG_TAG,"JSONException on third button."); - } - } - dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { - public void onCancel(DialogInterface dialog){ - dialog.dismiss(); - try { - result.put("buttonIndex",0); - result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { e.printStackTrace(); } - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); - } - }); - - changeTextDirection(dlg); - }; - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - /** - * Show the spinner. - * - * @param title Title of the dialog - * @param message The message of the dialog - */ - public synchronized void activityStart(final String title, final String message) { - if (this.spinnerDialog != null) { - this.spinnerDialog.dismiss(); - this.spinnerDialog = null; - } - final Notification notification = this; - final CordovaInterface cordova = this.cordova; - Runnable runnable = new Runnable() { - public void run() { - notification.spinnerDialog = createProgressDialog(cordova); // new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - notification.spinnerDialog.setTitle(title); - notification.spinnerDialog.setMessage(message); - notification.spinnerDialog.setCancelable(true); - notification.spinnerDialog.setIndeterminate(true); - notification.spinnerDialog.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - notification.spinnerDialog = null; - } - }); - notification.spinnerDialog.show(); - } - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - /** - * Stop spinner. - */ - public synchronized void activityStop() { - if (this.spinnerDialog != null) { - this.spinnerDialog.dismiss(); - this.spinnerDialog = null; - } - } - - /** - * Show the progress dialog. - * - * @param title Title of the dialog - * @param message The message of the dialog - */ - public synchronized void progressStart(final String title, final String message) { - if (this.progressDialog != null) { - this.progressDialog.dismiss(); - this.progressDialog = null; - } - final Notification notification = this; - final CordovaInterface cordova = this.cordova; - Runnable runnable = new Runnable() { - public void run() { - notification.progressDialog = createProgressDialog(cordova); // new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - notification.progressDialog.setTitle(title); - notification.progressDialog.setMessage(message); - notification.progressDialog.setCancelable(true); - notification.progressDialog.setMax(100); - notification.progressDialog.setProgress(0); - notification.progressDialog.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - notification.progressDialog = null; - } - }); - notification.progressDialog.show(); - } - }; - this.cordova.getActivity().runOnUiThread(runnable); - } - - /** - * Set value of progress bar. - * - * @param value 0-100 - */ - public synchronized void progressValue(int value) { - if (this.progressDialog != null) { - this.progressDialog.setProgress(value); - } - } - - /** - * Stop progress dialog. - */ - public synchronized void progressStop() { - if (this.progressDialog != null) { - this.progressDialog.dismiss(); - this.progressDialog = null; - } - } - - @SuppressLint("NewApi") - private AlertDialog.Builder createDialog(CordovaInterface cordova) { - int currentapiVersion = android.os.Build.VERSION.SDK_INT; - if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { - return new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - } else { - return new AlertDialog.Builder(cordova.getActivity()); - } - } - - @SuppressLint("InlinedApi") - private ProgressDialog createProgressDialog(CordovaInterface cordova) { - int currentapiVersion = android.os.Build.VERSION.SDK_INT; - if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return new ProgressDialog(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); - } else { - return new ProgressDialog(cordova.getActivity()); - } - } - - @SuppressLint("NewApi") - private void changeTextDirection(Builder dlg){ - int currentapiVersion = android.os.Build.VERSION.SDK_INT; - dlg.create(); - AlertDialog dialog = dlg.show(); - if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - TextView messageview = (TextView)dialog.findViewById(android.R.id.message); - messageview.setTextDirection(android.view.View.TEXT_DIRECTION_LOCALE); - } - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/geolocation/Geolocation.java b/platforms/android/app/src/main/java/org/apache/cordova/geolocation/Geolocation.java deleted file mode 100755 index 6452170a..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/geolocation/Geolocation.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - - -package org.apache.cordova.geolocation; - -import android.content.pm.PackageManager; -import android.Manifest; -import android.os.Build; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaArgs; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.PermissionHelper; -import org.apache.cordova.PluginResult; -import org.apache.cordova.LOG; -import org.json.JSONArray; -import org.json.JSONException; - -import javax.security.auth.callback.Callback; - -public class Geolocation extends CordovaPlugin { - - String TAG = "GeolocationPlugin"; - CallbackContext context; - - String [] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; - - - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - LOG.d(TAG, "We are entering execute"); - context = callbackContext; - if(action.equals("getPermission")) - { - if(hasPermisssion()) - { - PluginResult r = new PluginResult(PluginResult.Status.OK); - context.sendPluginResult(r); - return true; - } - else { - PermissionHelper.requestPermissions(this, 0, permissions); - } - return true; - } - return false; - } - - - public void onRequestPermissionResult(int requestCode, String[] permissions, - int[] grantResults) throws JSONException - { - PluginResult result; - //This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed - if(context != null) { - for (int r : grantResults) { - if (r == PackageManager.PERMISSION_DENIED) { - LOG.d(TAG, "Permission Denied!"); - result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION); - context.sendPluginResult(result); - return; - } - - } - result = new PluginResult(PluginResult.Status.OK); - context.sendPluginResult(result); - } - } - - public boolean hasPermisssion() { - for(String p : permissions) - { - if(!PermissionHelper.hasPermission(this, p)) - { - return false; - } - } - return true; - } - - /* - * We override this so that we can access the permissions variable, which no longer exists in - * the parent class, since we can't initialize it reliably in the constructor! - */ - - public void requestPermissions(int requestCode) - { - PermissionHelper.requestPermissions(this, requestCode, permissions); - } - - - -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java b/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java deleted file mode 100755 index 6f56c6c6..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -package org.apache.cordova.splashscreen; - -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.Configuration; -import android.content.res.ColorStateList; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Handler; -import android.view.Display; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowManager; -import android.view.animation.Animation; -import android.view.animation.AlphaAnimation; -import android.view.animation.DecelerateInterpolator; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaWebView; -import org.json.JSONArray; -import org.json.JSONException; - -public class SplashScreen extends CordovaPlugin { - private static final String LOG_TAG = "SplashScreen"; - // Cordova 3.x.x has a copy of this plugin bundled with it (SplashScreenInternal.java). - // Enable functionality only if running on 4.x.x. - private static final boolean HAS_BUILT_IN_SPLASH_SCREEN = Integer.valueOf(CordovaWebView.CORDOVA_VERSION.split("\\.")[0]) < 4; - private static final int DEFAULT_SPLASHSCREEN_DURATION = 3000; - private static final int DEFAULT_FADE_DURATION = 500; - private static Dialog splashDialog; - private static ProgressDialog spinnerDialog; - private static boolean firstShow = true; - private static boolean lastHideAfterDelay; // https://issues.apache.org/jira/browse/CB-9094 - - /** - * Displays the splash drawable. - */ - private ImageView splashImageView; - - /** - * Remember last device orientation to detect orientation changes. - */ - private int orientation; - - // Helper to be compile-time compatible with both Cordova 3.x and 4.x. - private View getView() { - try { - return (View)webView.getClass().getMethod("getView").invoke(webView); - } catch (Exception e) { - return (View)webView; - } - } - - private int getSplashId() { - int drawableId = 0; - String splashResource = preferences.getString("SplashScreen", "screen"); - if (splashResource != null) { - drawableId = cordova.getActivity().getResources().getIdentifier(splashResource, "drawable", cordova.getActivity().getClass().getPackage().getName()); - if (drawableId == 0) { - drawableId = cordova.getActivity().getResources().getIdentifier(splashResource, "drawable", cordova.getActivity().getPackageName()); - } - } - return drawableId; - } - - @Override - protected void pluginInitialize() { - if (HAS_BUILT_IN_SPLASH_SCREEN) { - return; - } - // Make WebView invisible while loading URL - // CB-11326 Ensure we're calling this on UI thread - cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - getView().setVisibility(View.INVISIBLE); - } - }); - int drawableId = getSplashId(); - - // Save initial orientation. - orientation = cordova.getActivity().getResources().getConfiguration().orientation; - - if (firstShow) { - boolean autoHide = preferences.getBoolean("AutoHideSplashScreen", true); - showSplashScreen(autoHide); - } - - if (preferences.getBoolean("SplashShowOnlyFirstTime", true)) { - firstShow = false; - } - } - - /** - * Shorter way to check value of "SplashMaintainAspectRatio" preference. - */ - private boolean isMaintainAspectRatio () { - return preferences.getBoolean("SplashMaintainAspectRatio", false); - } - - private int getFadeDuration () { - int fadeSplashScreenDuration = preferences.getBoolean("FadeSplashScreen", true) ? - preferences.getInteger("FadeSplashScreenDuration", DEFAULT_FADE_DURATION) : 0; - - if (fadeSplashScreenDuration < 30) { - // [CB-9750] This value used to be in decimal seconds, so we will assume that if someone specifies 10 - // they mean 10 seconds, and not the meaningless 10ms - fadeSplashScreenDuration *= 1000; - } - - return fadeSplashScreenDuration; - } - - @Override - public void onPause(boolean multitasking) { - if (HAS_BUILT_IN_SPLASH_SCREEN) { - return; - } - // hide the splash screen to avoid leaking a window - this.removeSplashScreen(true); - } - - @Override - public void onDestroy() { - if (HAS_BUILT_IN_SPLASH_SCREEN) { - return; - } - // hide the splash screen to avoid leaking a window - this.removeSplashScreen(true); - // If we set this to true onDestroy, we lose track when we go from page to page! - //firstShow = true; - } - - @Override - public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - if (action.equals("hide")) { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - webView.postMessage("splashscreen", "hide"); - } - }); - } else if (action.equals("show")) { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - webView.postMessage("splashscreen", "show"); - } - }); - } else { - return false; - } - - callbackContext.success(); - return true; - } - - @Override - public Object onMessage(String id, Object data) { - if (HAS_BUILT_IN_SPLASH_SCREEN) { - return null; - } - if ("splashscreen".equals(id)) { - if ("hide".equals(data.toString())) { - this.removeSplashScreen(false); - } else { - this.showSplashScreen(false); - } - } else if ("spinner".equals(id)) { - if ("stop".equals(data.toString())) { - getView().setVisibility(View.VISIBLE); - } - } else if ("onReceivedError".equals(id)) { - this.spinnerStop(); - } - return null; - } - - // Don't add @Override so that plugin still compiles on 3.x.x for a while - public void onConfigurationChanged(Configuration newConfig) { - if (newConfig.orientation != orientation) { - orientation = newConfig.orientation; - - // Splash drawable may change with orientation, so reload it. - if (splashImageView != null) { - int drawableId = getSplashId(); - if (drawableId != 0) { - splashImageView.setImageDrawable(cordova.getActivity().getResources().getDrawable(drawableId)); - } - } - } - } - - private void removeSplashScreen(final boolean forceHideImmediately) { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - if (splashDialog != null && splashDialog.isShowing()) { - final int fadeSplashScreenDuration = getFadeDuration(); - // CB-10692 If the plugin is being paused/destroyed, skip the fading and hide it immediately - if (fadeSplashScreenDuration > 0 && forceHideImmediately == false) { - AlphaAnimation fadeOut = new AlphaAnimation(1, 0); - fadeOut.setInterpolator(new DecelerateInterpolator()); - fadeOut.setDuration(fadeSplashScreenDuration); - - splashImageView.setAnimation(fadeOut); - splashImageView.startAnimation(fadeOut); - - fadeOut.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - spinnerStop(); - } - - @Override - public void onAnimationEnd(Animation animation) { - if (splashDialog != null && splashDialog.isShowing()) { - splashDialog.dismiss(); - splashDialog = null; - splashImageView = null; - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - }); - } else { - spinnerStop(); - splashDialog.dismiss(); - splashDialog = null; - splashImageView = null; - } - } - } - }); - } - - /** - * Shows the splash screen over the full Activity - */ - @SuppressWarnings("deprecation") - private void showSplashScreen(final boolean hideAfterDelay) { - final int splashscreenTime = preferences.getInteger("SplashScreenDelay", DEFAULT_SPLASHSCREEN_DURATION); - final int drawableId = getSplashId(); - - final int fadeSplashScreenDuration = getFadeDuration(); - final int effectiveSplashDuration = Math.max(0, splashscreenTime - fadeSplashScreenDuration); - - lastHideAfterDelay = hideAfterDelay; - - // Prevent to show the splash dialog if the activity is in the process of finishing - if (cordova.getActivity().isFinishing()) { - return; - } - // If the splash dialog is showing don't try to show it again - if (splashDialog != null && splashDialog.isShowing()) { - return; - } - if (drawableId == 0 || (splashscreenTime <= 0 && hideAfterDelay)) { - return; - } - - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - // Get reference to display - Display display = cordova.getActivity().getWindowManager().getDefaultDisplay(); - Context context = webView.getContext(); - - // Use an ImageView to render the image because of its flexible scaling options. - splashImageView = new ImageView(context); - splashImageView.setImageResource(drawableId); - LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - splashImageView.setLayoutParams(layoutParams); - - splashImageView.setMinimumHeight(display.getHeight()); - splashImageView.setMinimumWidth(display.getWidth()); - - // TODO: Use the background color of the webView's parent instead of using the preference. - splashImageView.setBackgroundColor(preferences.getInteger("backgroundColor", Color.BLACK)); - - if (isMaintainAspectRatio()) { - // CENTER_CROP scale mode is equivalent to CSS "background-size:cover" - splashImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); - } - else { - // FIT_XY scales image non-uniformly to fit into image view. - splashImageView.setScaleType(ImageView.ScaleType.FIT_XY); - } - - // Create and show the dialog - splashDialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar); - // check to see if the splash screen should be full screen - if ((cordova.getActivity().getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) - == WindowManager.LayoutParams.FLAG_FULLSCREEN) { - splashDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - splashDialog.setContentView(splashImageView); - splashDialog.setCancelable(false); - splashDialog.show(); - - if (preferences.getBoolean("ShowSplashScreenSpinner", true)) { - spinnerStart(); - } - - // Set Runnable to remove splash screen just in case - if (hideAfterDelay) { - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - public void run() { - if (lastHideAfterDelay) { - removeSplashScreen(false); - } - } - }, effectiveSplashDuration); - } - } - }); - } - - // Show only spinner in the center of the screen - private void spinnerStart() { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - spinnerStop(); - - spinnerDialog = new ProgressDialog(webView.getContext()); - spinnerDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - spinnerDialog = null; - } - }); - - spinnerDialog.setCancelable(false); - spinnerDialog.setIndeterminate(true); - - RelativeLayout centeredLayout = new RelativeLayout(cordova.getActivity()); - centeredLayout.setGravity(Gravity.CENTER); - centeredLayout.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - - ProgressBar progressBar = new ProgressBar(webView.getContext()); - RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); - progressBar.setLayoutParams(layoutParams); - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - String colorName = preferences.getString("SplashScreenSpinnerColor", null); - if(colorName != null){ - int[][] states = new int[][] { - new int[] { android.R.attr.state_enabled}, // enabled - new int[] {-android.R.attr.state_enabled}, // disabled - new int[] {-android.R.attr.state_checked}, // unchecked - new int[] { android.R.attr.state_pressed} // pressed - }; - int progressBarColor = Color.parseColor(colorName); - int[] colors = new int[] { - progressBarColor, - progressBarColor, - progressBarColor, - progressBarColor - }; - ColorStateList colorStateList = new ColorStateList(states, colors); - progressBar.setIndeterminateTintList(colorStateList); - } - } - - centeredLayout.addView(progressBar); - - spinnerDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); - spinnerDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - - spinnerDialog.show(); - spinnerDialog.setContentView(centeredLayout); - } - }); - } - - private void spinnerStop() { - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - if (spinnerDialog != null && spinnerDialog.isShowing()) { - spinnerDialog.dismiss(); - spinnerDialog = null; - } - } - }); - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java b/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java deleted file mode 100755 index 714c30e8..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * -*/ -package org.apache.cordova.statusbar; - -import android.app.Activity; -import android.graphics.Color; -import android.os.Build; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaArgs; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.LOG; -import org.apache.cordova.PluginResult; -import org.json.JSONException; -import java.util.Arrays; - -public class StatusBar extends CordovaPlugin { - private static final String TAG = "StatusBar"; - - /** - * Sets the context of the Command. This can then be used to do things like - * get file paths associated with the Activity. - * - * @param cordova The context of the main Activity. - * @param webView The CordovaWebView Cordova is running in. - */ - @Override - public void initialize(final CordovaInterface cordova, CordovaWebView webView) { - LOG.v(TAG, "StatusBar: initialization"); - super.initialize(cordova, webView); - - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially - // by the Cordova. - Window window = cordova.getActivity().getWindow(); - window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - - // Read 'StatusBarBackgroundColor' from config.xml, default is #000000. - setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000")); - - // Read 'StatusBarStyle' from config.xml, default is 'lightcontent'. - setStatusBarStyle(preferences.getString("StatusBarStyle", "lightcontent")); - } - }); - } - - /** - * Executes the request and returns PluginResult. - * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. - * @param callbackContext The callback id used when calling back into JavaScript. - * @return True if the action was valid, false otherwise. - */ - @Override - public boolean execute(final String action, final CordovaArgs args, final CallbackContext callbackContext) throws JSONException { - LOG.v(TAG, "Executing action: " + action); - final Activity activity = this.cordova.getActivity(); - final Window window = activity.getWindow(); - - if ("_ready".equals(action)) { - boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0; - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible)); - return true; - } - - if ("show".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we - // use KitKat here to be aligned with "Fullscreen" preference - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - int uiOptions = window.getDecorView().getSystemUiVisibility(); - uiOptions &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - uiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; - - window.getDecorView().setSystemUiVisibility(uiOptions); - } - - // CB-11197 We still need to update LayoutParams to force status bar - // to be hidden when entering e.g. text fields - window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - }); - return true; - } - - if ("hide".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we - // use KitKat here to be aligned with "Fullscreen" preference - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - int uiOptions = window.getDecorView().getSystemUiVisibility() - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_FULLSCREEN; - - window.getDecorView().setSystemUiVisibility(uiOptions); - } - - // CB-11197 We still need to update LayoutParams to force status bar - // to be hidden when entering e.g. text fields - window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - }); - return true; - } - - if ("backgroundColorByHexString".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setStatusBarBackgroundColor(args.getString(0)); - } catch (JSONException ignore) { - LOG.e(TAG, "Invalid hexString argument, use f.i. '#777777'"); - } - } - }); - return true; - } - - if ("overlaysWebView".equals(action)) { - if (Build.VERSION.SDK_INT >= 21) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setStatusBarTransparent(args.getBoolean(0)); - } catch (JSONException ignore) { - LOG.e(TAG, "Invalid boolean argument"); - } - } - }); - return true; - } - else return args.getBoolean(0) == false; - } - - if ("styleDefault".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - setStatusBarStyle("default"); - } - }); - return true; - } - - if ("styleLightContent".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - setStatusBarStyle("lightcontent"); - } - }); - return true; - } - - if ("styleBlackTranslucent".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - setStatusBarStyle("blacktranslucent"); - } - }); - return true; - } - - if ("styleBlackOpaque".equals(action)) { - this.cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - setStatusBarStyle("blackopaque"); - } - }); - return true; - } - - return false; - } - - private void setStatusBarBackgroundColor(final String colorPref) { - if (Build.VERSION.SDK_INT >= 21) { - if (colorPref != null && !colorPref.isEmpty()) { - final Window window = cordova.getActivity().getWindow(); - // Method and constants not available on all SDKs but we want to be able to compile this code with any SDK - window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - try { - // Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21 - window.getClass().getMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref)); - } catch (IllegalArgumentException ignore) { - LOG.e(TAG, "Invalid hexString argument, use f.i. '#999999'"); - } catch (Exception ignore) { - // this should not happen, only in case Android removes this method in a version > 21 - LOG.w(TAG, "Method window.setStatusBarColor not found for SDK level " + Build.VERSION.SDK_INT); - } - } - } - } - - private void setStatusBarTransparent(final boolean transparent) { - if (Build.VERSION.SDK_INT >= 21) { - final Window window = cordova.getActivity().getWindow(); - if (transparent) { - window.getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - window.setStatusBarColor(Color.TRANSPARENT); - } - else { - window.getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_VISIBLE); - } - } - } - - private void setStatusBarStyle(final String style) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (style != null && !style.isEmpty()) { - View decorView = cordova.getActivity().getWindow().getDecorView(); - int uiOptions = decorView.getSystemUiVisibility(); - - String[] darkContentStyles = { - "default", - }; - - String[] lightContentStyles = { - "lightcontent", - "blacktranslucent", - "blackopaque", - }; - - if (Arrays.asList(darkContentStyles).contains(style.toLowerCase())) { - decorView.setSystemUiVisibility(uiOptions | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); - return; - } - - if (Arrays.asList(lightContentStyles).contains(style.toLowerCase())) { - decorView.setSystemUiVisibility(uiOptions & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); - return; - } - - LOG.e(TAG, "Invalid style, must be either 'default', 'lightcontent' or the deprecated 'blacktranslucent' and 'blackopaque'"); - } - } - } -} diff --git a/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java b/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java deleted file mode 100755 index 36567886..00000000 --- a/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -package org.apache.cordova.whitelist; - -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.ConfigXmlParser; -import org.apache.cordova.LOG; -import org.apache.cordova.Whitelist; -import org.xmlpull.v1.XmlPullParser; - -import android.content.Context; - -public class WhitelistPlugin extends CordovaPlugin { - private static final String LOG_TAG = "WhitelistPlugin"; - private Whitelist allowedNavigations; - private Whitelist allowedIntents; - private Whitelist allowedRequests; - - // Used when instantiated via reflection by PluginManager - public WhitelistPlugin() { - } - // These can be used by embedders to allow Java-configuration of whitelists. - public WhitelistPlugin(Context context) { - this(new Whitelist(), new Whitelist(), null); - new CustomConfigXmlParser().parse(context); - } - public WhitelistPlugin(XmlPullParser xmlParser) { - this(new Whitelist(), new Whitelist(), null); - new CustomConfigXmlParser().parse(xmlParser); - } - public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) { - if (allowedRequests == null) { - allowedRequests = new Whitelist(); - allowedRequests.addWhiteListEntry("file:///*", false); - allowedRequests.addWhiteListEntry("data:*", false); - } - this.allowedNavigations = allowedNavigations; - this.allowedIntents = allowedIntents; - this.allowedRequests = allowedRequests; - } - @Override - public void pluginInitialize() { - if (allowedNavigations == null) { - allowedNavigations = new Whitelist(); - allowedIntents = new Whitelist(); - allowedRequests = new Whitelist(); - new CustomConfigXmlParser().parse(webView.getContext()); - } - } - - private class CustomConfigXmlParser extends ConfigXmlParser { - @Override - public void handleStartTag(XmlPullParser xml) { - String strNode = xml.getName(); - if (strNode.equals("content")) { - String startPage = xml.getAttributeValue(null, "src"); - allowedNavigations.addWhiteListEntry(startPage, false); - } else if (strNode.equals("allow-navigation")) { - String origin = xml.getAttributeValue(null, "href"); - if ("*".equals(origin)) { - allowedNavigations.addWhiteListEntry("http://*/*", false); - allowedNavigations.addWhiteListEntry("https://*/*", false); - allowedNavigations.addWhiteListEntry("data:*", false); - } else { - allowedNavigations.addWhiteListEntry(origin, false); - } - } else if (strNode.equals("allow-intent")) { - String origin = xml.getAttributeValue(null, "href"); - allowedIntents.addWhiteListEntry(origin, false); - } else if (strNode.equals("access")) { - String origin = xml.getAttributeValue(null, "origin"); - String subdomains = xml.getAttributeValue(null, "subdomains"); - boolean external = (xml.getAttributeValue(null, "launch-external") != null); - if (origin != null) { - if (external) { - LOG.w(LOG_TAG, "Found within config.xml. Please use instead."); - allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); - } else { - if ("*".equals(origin)) { - allowedRequests.addWhiteListEntry("http://*/*", false); - allowedRequests.addWhiteListEntry("https://*/*", false); - } else { - allowedRequests.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); - } - } - } - } - } - @Override - public void handleEndTag(XmlPullParser xml) { - } - } - - @Override - public Boolean shouldAllowNavigation(String url) { - if (allowedNavigations.isUrlWhiteListed(url)) { - return true; - } - return null; // Default policy - } - - @Override - public Boolean shouldAllowRequest(String url) { - if (Boolean.TRUE == shouldAllowNavigation(url)) { - return true; - } - if (allowedRequests.isUrlWhiteListed(url)) { - return true; - } - return null; // Default policy - } - - @Override - public Boolean shouldOpenExternalUrl(String url) { - if (allowedIntents.isUrlWhiteListed(url)) { - return true; - } - return null; // Default policy - } - - public Whitelist getAllowedNavigations() { - return allowedNavigations; - } - - public void setAllowedNavigations(Whitelist allowedNavigations) { - this.allowedNavigations = allowedNavigations; - } - - public Whitelist getAllowedIntents() { - return allowedIntents; - } - - public void setAllowedIntents(Whitelist allowedIntents) { - this.allowedIntents = allowedIntents; - } - - public Whitelist getAllowedRequests() { - return allowedRequests; - } - - public void setAllowedRequests(Whitelist allowedRequests) { - this.allowedRequests = allowedRequests; - } -} diff --git a/platforms/android/app/src/main/java/uk/co/workingedge/phonegap/plugin/LaunchNavigator.java b/platforms/android/app/src/main/java/uk/co/workingedge/phonegap/plugin/LaunchNavigator.java deleted file mode 100755 index 17851475..00000000 --- a/platforms/android/app/src/main/java/uk/co/workingedge/phonegap/plugin/LaunchNavigator.java +++ /dev/null @@ -1,1758 +0,0 @@ -/* - * LaunchNavigator Plugin for Phonegap - * - * Copyright (c) 2014 Dave Alden (http://github.com/dpa99c) - * Copyright (c) 2014 Working Edge Ltd. (http://www.workingedge.co.uk) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -package uk.co.workingedge.phonegap.plugin; - -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CallbackContext; - -import org.apache.cordova.CordovaWebView; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.Uri; -import android.util.Log; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - - -public class LaunchNavigator extends CordovaPlugin { - - private static final String LOG_TAG = "LaunchNavigator"; - private static final String NO_APP_FOUND = "No Activity found to handle Intent"; - private static final String MAPS_PROTOCOL = "http://maps.google.com/maps?"; - private static final String TURN_BY_TURN_PROTOCOL = "google.navigation:"; - - // Explicitly supported apps - private static final String GEO = "geo"; // Use native app choose for geo: intent - private static final String GOOGLE_MAPS = "google_maps"; - private static final String CITYMAPPER = "citymapper"; - private static final String UBER = "uber"; - private static final String WAZE = "waze"; - private static final String YANDEX = "yandex"; - private static final String SYGIC = "sygic"; - private static final String HERE_MAPS = "here_maps"; - private static final String MOOVIT = "moovit"; - private static final String LYFT = "lyft"; - private static final String MAPS_ME = "maps_me"; - private static final String CABIFY = "cabify"; - private static final String BAIDU = "baidu"; - private static final String TAXIS_99 = "taxis_99"; - private static final String GAODE = "gaode"; - - - private static final Map supportedAppPackages; - static { - Map _supportedAppPackages = new HashMap(); - _supportedAppPackages.put(GOOGLE_MAPS, "com.google.android.apps.maps"); - _supportedAppPackages.put(CITYMAPPER, "com.citymapper.app.release"); - _supportedAppPackages.put(UBER, "com.ubercab"); - _supportedAppPackages.put(WAZE, "com.waze"); - _supportedAppPackages.put(YANDEX, "ru.yandex.yandexnavi"); - _supportedAppPackages.put(SYGIC, "com.sygic.aura"); - _supportedAppPackages.put(HERE_MAPS, "com.here.app.maps"); - _supportedAppPackages.put(MOOVIT, "com.tranzmate"); - _supportedAppPackages.put(LYFT, "me.lyft.android"); - _supportedAppPackages.put(MAPS_ME, "com.mapswithme.maps.pro"); - _supportedAppPackages.put(CABIFY, "com.cabify.rider"); - _supportedAppPackages.put(BAIDU, "com.baidu.BaiduMap"); - _supportedAppPackages.put(TAXIS_99, "com.taxis99"); - _supportedAppPackages.put(GAODE, "com.autonavi.minimap"); - supportedAppPackages = Collections.unmodifiableMap(_supportedAppPackages); - } - - private static final Map supportedAppNames; - static { - Map _supportedAppNames = new HashMap(); - _supportedAppNames.put(GOOGLE_MAPS, "Google Maps"); - _supportedAppNames.put(CITYMAPPER, "Citymapper"); - _supportedAppNames.put(UBER, "Uber"); - _supportedAppNames.put(WAZE, "Waze"); - _supportedAppNames.put(YANDEX, "Yandex Navigator"); - _supportedAppNames.put(SYGIC, "Sygic"); - _supportedAppNames.put(HERE_MAPS, "HERE Maps"); - _supportedAppNames.put(MOOVIT, "Moovit"); - _supportedAppNames.put(LYFT, "Lyft"); - _supportedAppNames.put(MAPS_ME, "MAPS.ME"); - _supportedAppNames.put(CABIFY, "Cabify"); - _supportedAppNames.put(BAIDU, "Baidu Maps"); - _supportedAppNames.put(TAXIS_99, "99 Taxi"); - _supportedAppNames.put(GAODE, "Gaode Maps (Amap)"); - supportedAppNames = Collections.unmodifiableMap(_supportedAppNames); - } - - private static final String GEO_URI = "geo:"; - - PackageManager packageManager; - Context context; - - OkHttpClient httpClient = new OkHttpClient(); - - boolean enableDebug = false; - boolean enableGeocoding = true; - - // Map of app name to package name - Map availableApps; - - - @Override - protected void pluginInitialize() { - Log.i(LOG_TAG, "pluginInitialize()"); - discoverAvailableApps(); - } - - @Override - public boolean execute(String action, JSONArray args, - CallbackContext callbackContext) throws JSONException { - try { - logDebug("Plugin action="+action); - if ("navigate".equals(action)) { - /** - * args[] - * args[0] - app - * args[1] - dType - * args[2] - dest - * args[3] - destNickname - * args[4] - sType - * args[5] - start - * args[6] - startNickname - * args[7] - transportMode - * args[8] - launchMode - * args[9] - enableDebug - * args[10] - extras - * args[11] - enableGeolocation - */ - if(args.get(11) != null){ - enableGeocoding = args.getBoolean(11); - } - enableDebug = args.getBoolean(9); - if(enableDebug){ - String navigateArgs = "Called navigate() with args" - + ": app="+ args.getString(0) - + "; dType="+ args.getString(1) - + "; dest="+ args.getString(2) - + "; destNickname="+ args.getString(3) - + "; sType="+ args.getString(4) - + "; start="+ args.getString(5) - + "; startNickname="+ args.getString(6) - + "; transportMode="+ args.getString(7) - + "; launchMode="+ args.getString(8) - + "; extras="+ args.getString(10) - + "; enableGeocoding="+ args.getString(11); - logDebug(navigateArgs); - } - this.navigate(args, callbackContext); - } else if ("discoverSupportedApps".equals(action)) { - // This is called by plugin JS on initialisation - this.discoverSupportedApps(args, callbackContext); - } else if ("availableApps".equals(action)) { - this.availableApps(args, callbackContext); - } else if ("isAppAvailable".equals(action)) { - this.isAppAvailable(args, callbackContext); - }else { - String msg = "Invalid action"; - logError(msg); - callbackContext.error(msg); - return false; - } - }catch(Exception e){ - handleException(e.getMessage(), callbackContext); - } - return true; - } - - /* - * Plugin API - */ - private void discoverSupportedApps(JSONArray args, CallbackContext callbackContext) throws JSONException{ - JSONObject apps = new JSONObject(); - - // Dynamically populate from discovered available apps that support geo: protocol - for (Map.Entry entry : availableApps.entrySet()) { - String appName = entry.getKey(); - String packageName = entry.getValue(); - // If it's not already an explicitly supported app - if(!supportedAppPackages.containsValue(packageName)){ - apps.put(appName, packageName); - } - } - - callbackContext.success(apps); - } - - private void availableApps(JSONArray args, CallbackContext callbackContext) throws Exception{ - JSONObject apps = new JSONObject(); - - // Add explicitly supported apps first - for (Map.Entry entry : supportedAppPackages.entrySet()) { - String _appName = entry.getKey(); - String _packageName = entry.getValue(); - apps.put(_appName, availableApps.containsValue(_packageName)); - } - - // Iterate over available apps and add any dynamically discovered ones - for (Map.Entry entry : availableApps.entrySet()) { - String _packageName = entry.getValue(); - // If it's not already present - if(!apps.has(_packageName) && !supportedAppPackages.containsValue(_packageName)){ - apps.put(_packageName, true); - } - } - callbackContext.success(apps); - } - - private void isAppAvailable(JSONArray args, CallbackContext callbackContext) throws Exception{ - String appName = args.getString(0); - if(supportedAppPackages.containsKey(appName)){ - appName = supportedAppPackages.get(appName); - } - - if(availableApps.containsValue(appName)){ - callbackContext.success(1); - }else{ - callbackContext.success(0); - } - } - - private void navigate(JSONArray args, CallbackContext callbackContext) throws Exception{ - String appName = args.getString(0); - String launchMode = args.getString(8); - - if(appName.equals(GOOGLE_MAPS) && !launchMode.equals("geo")){ - launchGoogleMaps(args, callbackContext); - }else if(appName.equals(CITYMAPPER)){ - launchCitymapper(args, callbackContext); - }else if(appName.equals(UBER)){ - launchUber(args, callbackContext); - }else if(appName.equals(WAZE)){ - launchWaze(args, callbackContext); - }else if(appName.equals(YANDEX)){ - launchYandex(args, callbackContext); - }else if(appName.equals(SYGIC)){ - launchSygic(args, callbackContext); - }else if(appName.equals(HERE_MAPS)){ - launchHereMaps(args, callbackContext); - }else if(appName.equals(MOOVIT)){ - launchMoovit(args, callbackContext); - }else if(appName.equals(LYFT)){ - launchLyft(args, callbackContext); - }else if(appName.equals(MAPS_ME)){ - launchMapsMe(args, callbackContext); - }else if(appName.equals(CABIFY)){ - launchCabify(args, callbackContext); - }else if(appName.equals(BAIDU)){ - launchBaidu(args, callbackContext); - }else if(appName.equals(GAODE)){ - launchGaode(args, callbackContext); - }else if(appName.equals(TAXIS_99)){ - launch99Taxis(args, callbackContext); - }else{ - launchApp(args, callbackContext); - } - } - - - /* - * Launch apps - */ - private void launchApp(JSONArray args, CallbackContext callbackContext) throws Exception{ - String appName = args.getString(0); - String dType = args.getString(1); - String dNickName = args.getString(3); - - String logMsg = "Using " + getAppDisplayName(appName)+" to navigate to "; - String destLatLon = null; - String destName = null; - String dest; - - if(dType.equals("name")){ - destName = getLocationFromName(args, 2); - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(destLatLon == null){ - return; - } - logMsg += destName; - if(!isNull(destLatLon)){ - logMsg += "["+destLatLon+"]"; - } - - }else{ - destLatLon = getLocationFromPos(args, 2); - logMsg += "["+destLatLon+"]"; - } - - if(!isNull(destLatLon)){ - dest = destLatLon; - }else{ - dest = destName; - } - - String uri = GEO_URI+destLatLon+"?q="+dest; - if(!isNull(dNickName)){ - uri += "("+dNickName+")"; - logMsg += "("+dNickName+")"; - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - uri += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + uri); - - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); - if(!appName.equals(GEO)){ - if(appName.equals(GOOGLE_MAPS)) { - appName = supportedAppPackages.get(GOOGLE_MAPS); - } - intent.setPackage(appName); - } - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - } - - private void launchGoogleMaps(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destination; - String start = null; - - String dType = args.getString(1); - if(dType.equals("pos")){ - destination = getLocationFromPos(args, 2); - }else{ - destination = getLocationFromName(args, 2); - } - - String sType = args.getString(4); - if(sType.equals("pos")){ - start = getLocationFromPos(args, 5); - }else if(sType.equals("name")){ - start = getLocationFromName(args, 5); - } - String transportMode = args.getString(7); - String launchMode = args.getString(8); - - String logMsg = "Using Google Maps to navigate to "+destination; - String url; - - if(launchMode.equals("turn-by-turn")){ - url = TURN_BY_TURN_PROTOCOL + "q=" + destination; - if(!isNull(transportMode)){ - logMsg += " by transportMode=" + transportMode; - url += "&mode=" + transportMode; - } - logMsg += " in turn-by-turn mode"; - }else{ - url = MAPS_PROTOCOL + "daddr=" + destination; - if(!isNull(start)){ - logMsg += " from " + start; - url += "&saddr=" + start; - }else{ - logMsg += " from current location"; - } - logMsg += " in maps mode"; - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - intent.setClassName(supportedAppPackages.get(GOOGLE_MAPS), "com.google.android.maps.MapsActivity"); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Google Maps app is not installed on this device"; - } - logError("Exception occurred: ".concat(msg)); - callbackContext.error(msg); - } - } - - private void launchCitymapper(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - String startAddress = null; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - }else{ - destLatLon = getLocationFromPos(args, 2); - } - - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - String url = "https://citymapper.com/directions?"; - String logMsg = "Using Citymapper to navigate to"; - if(!isNull(destAddress)){ - url += "&endaddress="+Uri.encode(destAddress); - logMsg += " '"+destAddress+"'"; - } - if(isNull(destLatLon)){ - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - } - url += "&endcoord="+destLatLon; - logMsg += " ["+destLatLon+"]"; - if(!isNull(destNickname)){ - url += "&endname="+Uri.encode(destNickname); - logMsg += " ("+destNickname+")"; - } - - if(!sType.equals("none")){ - logMsg += " from"; - if(!isNull(startAddress)){ - url += "&startaddress="+Uri.encode(startAddress); - logMsg += " '"+startAddress+"'"; - } - if(isNull(startLatLon)){ - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - } - url += "&startcoord="+startLatLon; - logMsg += " ["+startLatLon+"]"; - if(!isNull(startNickname)){ - url += "&startname="+Uri.encode(startNickname); - logMsg += " ("+startNickname+")"; - } - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Citymapper app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchUber(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - String startAddress = null; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - }else{ - destLatLon = getLocationFromPos(args, 2); - } - - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - String url = "uber://?action=setPickup"; - String logMsg = "Using Uber to navigate to"; - if(!isNull(destAddress)){ - url += "&dropoff[formatted_address]="+destAddress; - logMsg += " '"+destAddress+"'"; - } - if(!isNull(destLatLon)){ - String[] parts = splitLatLon(destLatLon); - url += "&dropoff[latitude]="+parts[0]+"&dropoff[longitude]="+parts[1]; - logMsg += " ["+destLatLon+"]"; - } - if(!isNull(destNickname)){ - url += "&dropoff[nickname]="+destNickname; - logMsg += " ("+destNickname+")"; - } - - logMsg += " from"; - if(!sType.equals("none")){ - if(!isNull(startAddress)){ - url += "&pickup[formatted_address]=="+startAddress; - logMsg += " '"+startAddress+"'"; - } - if(!isNull(startLatLon)){ - String[] parts = splitLatLon(startLatLon); - url += "&pickup[latitude]="+parts[0]+"&pickup[longitude]="+parts[1]; - logMsg += " ["+startLatLon+"]"; - } - if(!isNull(startNickname)){ - url += "&pickup[nickname]="+startNickname; - logMsg += " ("+startNickname+")"; - } - }else{ - url += "&pickup=my_location"; - logMsg += " current location"; - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Uber app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchWaze(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - - String dType = args.getString(1); - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - }else{ - destLatLon = getLocationFromPos(args, 2); - } - - String url = "waze://?"; - String logMsg = "Using Waze to navigate to"; - if(!isNull(destLatLon)){ - url += "ll="+destLatLon+"&navigate=yes"; - logMsg += " ["+destLatLon+"]"; - }else{ - url += "q="+destAddress; - logMsg += " '"+destAddress+"'"; - } - - logMsg += " from current location"; - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Waze app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchYandex(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - String startAddress = null; - String startLatLon = null; - - String dType = args.getString(1); - String sType = args.getString(4); - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - Intent intent = new Intent(supportedAppPackages.get(YANDEX)+".action.BUILD_ROUTE_ON_MAP"); - intent.setPackage(supportedAppPackages.get(YANDEX)); - String logMsg = "Using Yandex to navigate to"; - - String[] parts = splitLatLon(destLatLon); - intent.putExtra("lat_to", parts[0]); - intent.putExtra("lon_to", parts[1]); - logMsg += " ["+destLatLon+"]"; - - if(!isNull(destAddress)){ - logMsg += " ('"+destAddress+"')"; - } - - - logMsg += " from"; - if(!sType.equals("none")){ - parts = splitLatLon(startLatLon); - intent.putExtra("lat_from", parts[0]); - intent.putExtra("lon_from", parts[1]); - logMsg += " ["+startLatLon+"]"; - if(!isNull(startAddress)){ - logMsg += " ('"+startAddress+"')"; - } - }else{ - logMsg += " current location"; - } - - String jsonStringExtras = args.getString(10); - JSONObject oExtras = null; - if(!isNull(jsonStringExtras)){ - oExtras = new JSONObject(jsonStringExtras); - } - - if(oExtras != null){ - Iterator keys = oExtras.keys(); - while( keys.hasNext() ) { - String key = (String)keys.next(); - String value = oExtras.getString(key); - intent.putExtra(key, value); - } - } - logDebug(logMsg); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Yandex app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchSygic(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - - String dType = args.getString(1); - String transportMode = args.getString(7); - String url = supportedAppPackages.get(SYGIC)+"://coordinate|"; - String logMsg = "Using Sygic to navigate to"; - - if(transportMode.equals("w")){ - transportMode = "walk"; - }else{ - transportMode = "drive"; - } - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - - logMsg += " ["+destLatLon+"]"; - - String[] pos = splitLatLon(destLatLon); - url += pos[1]+"|"+pos[0]+"|"+transportMode; - - logMsg += " by " + transportMode; - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Sygic app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchHereMaps(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress; - String destLatLon = null; - String startAddress; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - String url = "https://share.here.com/r/"; - String logMsg = "Using HERE Maps to navigate"; - - logMsg += " from"; - if(sType.equals("none")){ - url += "mylocation"; - logMsg += " Current Location"; - - }else{ - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - logMsg += " '"+startAddress+"'"; - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - url += startLatLon; - logMsg += " ["+startLatLon+"]"; - - if(!isNull(startNickname)){ - url += ","+startNickname; - logMsg += " ("+startNickname+")"; - } - } - - url += "/"; - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - url += destLatLon; - - if(!isNull(destNickname)){ - url += ","+destNickname; - logMsg += " ("+destNickname+")"; - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += "?" + extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "HERE Maps app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchMoovit(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress; - String destLatLon = null; - String startAddress; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - String url = "moovit://directions"; - String logMsg = "Using Moovit to navigate"; - - - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - - String[] destPos = splitLatLon(destLatLon); - url += "?dest_lat=" + destPos[0] + "&dest_lon=" + destPos[1]; - - if(!isNull(destNickname)){ - url += "&dest_name="+destNickname; - logMsg += " ("+destNickname+")"; - } - - logMsg += " from"; - if(sType.equals("none")){ - logMsg += " Current Location"; - }else{ - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - logMsg += " '"+startAddress+"'"; - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - String[] startPos = splitLatLon(startLatLon); - url += "&orig_lat=" + startPos[0] + "&orig_lon=" + startPos[1]; - logMsg += " ["+startLatLon+"]"; - - if(!isNull(startNickname)){ - url += "&orig_name="+startNickname; - logMsg += " ("+startNickname+")"; - } - } - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Moovit app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchLyft(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress; - String destLatLon = null; - String startAddress; - String startLatLon = null; - - String dType = args.getString(1); - String sType = args.getString(4); - - String url = "lyft://ridetype?"; - String logMsg = "Using Lyft to navigate"; - - String extras = parseExtrasToUrl(args); - if(!isNull(extras)){ - url += extras; - logMsg += " - extras="+extras; - } - - if(isNull(extras) || !extras.contains("id=")){ - url += "id=lyft"; - } - - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - - String[] destPos = splitLatLon(destLatLon); - url += "&destination[latitude]=" + destPos[0] + "&destination[longitude]=" + destPos[1]; - - logMsg += " from"; - if(sType.equals("none")){ - logMsg += " Current Location"; - }else{ - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - logMsg += " '"+startAddress+"'"; - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - String[] startPos = splitLatLon(startLatLon); - url += "&pickup[latitude]=" + startPos[0] + "&pickup[longitude]=" + startPos[1]; - logMsg += " ["+startLatLon+"]"; - - } - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Lyft app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchMapsMe(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress; - String destLatLon = null; - String startAddress; - String startLatLon = null; - - String dType = args.getString(1); - String sType = args.getString(4); - String transportMode = args.getString(7); - - Intent intent = new Intent(supportedAppPackages.get(MAPS_ME).concat(".action.BUILD_ROUTE")); - intent.setPackage(supportedAppPackages.get(MAPS_ME)); - - String logMsg = "Using MAPs.ME to navigate"; - - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - - String[] destPos = splitLatLon(destLatLon); - intent.putExtra("lat_to", Double.parseDouble(destPos[0])); - intent.putExtra("lon_to", Double.parseDouble(destPos[1])); - - logMsg += " from"; - if(sType.equals("none")){ - logMsg += " Current Location"; - }else{ - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - logMsg += " '"+startAddress+"'"; - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - - String[] startPos = splitLatLon(startLatLon); - intent.putExtra("lat_from", Double.parseDouble(startPos[0])); - intent.putExtra("lon_from", Double.parseDouble(startPos[1])); - logMsg += " ["+startLatLon+"]"; - } - - - - if(transportMode.equals("d")){ - transportMode = "vehicle"; - }else if(transportMode.equals("w")){ - transportMode = "pedestrian"; - }else if(transportMode.equals("b")){ - transportMode = "bicycle"; - }else if(transportMode.equals("t")){ - transportMode = "taxi"; - } - - if(!isNull(transportMode)){ - intent.putExtra("router", transportMode); - logMsg += " by transportMode=" + transportMode; - } - - logDebug(logMsg); - - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "MAPS.ME app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchCabify(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress; - String destLatLon = null; - String startAddress; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - String url = "cabify://cabify/journey?json="; - String logMsg = "Using Cabify to navigate"; - JSONObject oJson = new JSONObject(); - - // Parse dest - JSONObject oDest = new JSONObject(); - logMsg += " to"; - - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - String[] destPos = splitLatLon(destLatLon); - - JSONObject oDestLoc = new JSONObject(); - oDestLoc.put("latitude", destPos[0]); - oDestLoc.put("longitude", destPos[1]); - oDest.put("loc", oDestLoc); - - if(!isNull(destNickname)){ - oDest.put("name", destNickname); - logMsg += " ("+destNickname+")"; - } - - // Parse start - JSONObject oStart = new JSONObject(); - logMsg += " from"; - - if(sType.equals("none")){ - logMsg += " Current Location"; - oStart.put("loc", "current"); - }else{ - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - logMsg += " '"+startAddress+"'"; - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - } - logMsg += " ["+startLatLon+"]"; - String[] startPos = splitLatLon(startLatLon); - - JSONObject oStartLoc = new JSONObject(); - oStartLoc.put("latitude", startPos[0]); - oStartLoc.put("longitude", startPos[1]); - oStart.put("loc", oStartLoc); - } - - if(!isNull(startNickname)){ - oStart.put("name", startNickname); - logMsg += " ("+startNickname+")"; - } - - String extras = args.getString(10); - if(!isNull(extras)){ - oJson = new JSONObject(extras); - logMsg += " - extras="+extras; - } - - // Assemble JSON - JSONArray aStops = new JSONArray(); - aStops.put(oStart); - if(oJson.has("stops")){ - JSONArray stops = oJson.getJSONArray("stops"); - for (int i = 0; i < stops.length(); i++) { - aStops.put(stops.getJSONObject(i)); - } - } - aStops.put(oDest); - oJson.put("stops", aStops); - - url += oJson.toString(); - - logDebug(logMsg); - logDebug("URI: " + url); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Cabify app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchBaidu(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String start; - String dest; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - String transportMode = args.getString(7); - - - String url = "baidumap://map/direction"; - String logMsg = "Using Baidu Maps to navigate"; - - String extras = parseExtrasToUrl(args); - if(isNull(extras)){ - extras = ""; - } - - if(!extras.contains("coord_type=")){ - extras += "&coord_type=wgs84"; - } - - // Destination - logMsg += " to"; - if(dType.equals("name")){ - dest = getLocationFromName(args, 2); - logMsg += dest; - }else{ - dest = getLocationFromPos(args, 2); - logMsg += " ["+dest+"]"; - if(!isNull(destNickname)){ - dest = "latlng:" + dest + "|name:" + destNickname; - logMsg += " ("+destNickname+")"; - } - } - url += "?destination=" + dest; - - // Start - logMsg += " from"; - if(sType.equals("none")){ - logMsg += " Current Location"; - }else{ - if(sType.equals("name")){ - start = getLocationFromName(args, 5); - logMsg += start; - }else{ - start = getLocationFromPos(args, 5); - logMsg += " ["+start+"]"; - if(!isNull(startNickname)){ - start = "latlng:" + start + "|name:" + startNickname; - logMsg += " ("+startNickname+")"; - } - } - url += "&origin=" + start; - } - - // Transport mode - if(transportMode.equals("d")){ - transportMode = "driving"; - }else if(transportMode.equals("w")){ - transportMode = "walking"; - }else if(transportMode.equals("b")){ - transportMode = "riding"; - }else if(transportMode.equals("t")){ - transportMode = "transit"; - }else{ - transportMode = "driving"; - } - - url += "&mode="+transportMode; - logMsg += " by transportMode=" + transportMode; - - // Extras - url += extras; - logMsg += " - extras="+extras; - - - logDebug(logMsg); - logDebug("URI: " + url); - - Intent intent = new Intent(); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Baidu Maps app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launchGaode(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - String startAddress = null; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - String transportMode = args.getString(7); - - - String url = "amapuri://route/plan/?"; - String logMsg = "Using Gaode Maps to navigate"; - - String extras = parseExtrasToUrl(args); - if(isNull(extras)){ - extras = ""; - } - - if(!extras.contains("sourceApplication=")){ - extras += "&sourceApplication="+Uri.encode(getThisAppName()); - } - - // Destination - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - String[] pos = splitLatLon(destLatLon); - url += "dlat="+pos[0]+"&dlon="+pos[1]; - - // Dest name - if(!isNull(destNickname)){ - logMsg += " ("+destNickname+")"; - url += "&dname="+destNickname; - } - - // Start - logMsg += " from"; - if(sType.equals("none")){ - logMsg += " Current Location"; - }else { - if (sType.equals("name")) { - startAddress = getLocationFromName(args, 5); - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - logMsg += " '" + startAddress + "'"; - } else{ - startLatLon = getLocationFromPos(args, 5); - } - if (!isNull(startLatLon)) { - logMsg += " [" + startLatLon + "]"; - pos = splitLatLon(startLatLon); - url += "&slat=" + pos[0] + "&slon=" + pos[1]; - - // Start name - if(!isNull(startNickname)){ - logMsg += " ("+startNickname+")"; - url += "&sname="+startNickname; - } - } - } - - - // Transport mode - String transportModeName; - if(transportMode.equals("d")){ - transportModeName = "driving"; - transportMode = "0"; - }else if(transportMode.equals("w")){ - transportModeName = "walking"; - transportMode = "2"; - }else if(transportMode.equals("b")){ - transportModeName = "bicycle"; - transportMode = "3"; - }else if(transportMode.equals("t")){ - transportModeName = "transit"; - transportMode = "1"; - }else{ - transportModeName = "driving"; - transportMode = "0"; - } - url += "&t="+transportMode; - logMsg += " by transportMode=" + transportModeName; - - // Extras - url += extras; - logMsg += " - extras="+extras; - - - logDebug(logMsg); - logDebug("URI: " + url); - - Intent intent = new Intent(); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "Gaode Maps app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - private void launch99Taxis(JSONArray args, CallbackContext callbackContext) throws Exception{ - try { - String destAddress = null; - String destLatLon = null; - String startAddress = null; - String startLatLon = null; - String destNickname = args.getString(3); - String startNickname = args.getString(6); - - String dType = args.getString(1); - String sType = args.getString(4); - - - String url = "taxis99://call?"; - String logMsg = "Using 99 Taxi to navigate"; - - String extras = parseExtrasToUrl(args); - if(isNull(extras)){ - extras = ""; - } - - if(!extras.contains("deep_link_product_id")){ - extras += "&deep_link_product_id=316"; - } - - if(!extras.contains("client_id")){ - extras += "&client_id=MAP_123"; - } - - // Destination - logMsg += " to"; - if(dType.equals("name")){ - destAddress = getLocationFromName(args, 2); - logMsg += " '"+destAddress+"'"; - destLatLon = geocodeAddressToLatLon(args.getString(2), callbackContext); - if(isNull(destLatLon)){ - return; - } - }else{ - destLatLon = getLocationFromPos(args, 2); - } - logMsg += " ["+destLatLon+"]"; - String[] pos = splitLatLon(destLatLon); - url += "dropoff_latitude="+pos[0]+"&dropoff_longitude="+pos[1]; - - // Dest name - if(isNull(destNickname)){ - if(!isNull(destAddress)){ - destNickname = destAddress; - }else{ - destNickname = "Dropoff"; - } - } - logMsg += " ("+destNickname+")"; - url += "&dropoff_title="+destNickname; - - // Start - logMsg += " from"; - if(sType.equals("name")){ - startAddress = getLocationFromName(args, 5); - startLatLon = geocodeAddressToLatLon(args.getString(5), callbackContext); - logMsg += " '"+startAddress+"'"; - if(isNull(startLatLon)){ - return; - } - }else if(sType.equals("pos")){ - startLatLon = getLocationFromPos(args, 5); - }else{ - handleError("start location is a required parameter for 99 Taxi and must be specified", callbackContext); - return; - } - logMsg += " ["+startLatLon+"]"; - pos = splitLatLon(startLatLon); - url += "&pickup_latitude="+pos[0]+"&pickup_longitude="+pos[1]; - - // Start name - if(isNull(startNickname)){ - if(!isNull(startAddress)){ - startNickname = startAddress; - }else{ - startNickname = "Pickup"; - } - } - logMsg += " ("+startNickname+")"; - url += "&pickup_title="+startNickname; - - - // Extras - url += extras; - logMsg += " - extras="+extras; - - logDebug(logMsg); - logDebug("URI: " + url); - - Intent intent = new Intent(); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - callbackContext.success(); - }catch( JSONException e ) { - String msg = e.getMessage(); - if(msg.contains(NO_APP_FOUND)){ - msg = "99 Taxis app is not installed on this device"; - } - handleException(msg, callbackContext); - } - } - - /* - * Utilities - */ - - private String parseExtrasToUrl(JSONArray args) throws JSONException{ - String extras = null; - String jsonStringExtras = args.getString(10); - JSONObject oExtras = null; - if(!isNull(jsonStringExtras)){ - oExtras = new JSONObject(jsonStringExtras); - } - - if(oExtras != null){ - Iterator keys = oExtras.keys(); - extras = ""; - while( keys.hasNext() ) { - String key = (String)keys.next(); - String value = oExtras.getString(key); - extras += "&"+key+"="+value; - } - } - return extras; - } - - private String getLocationFromPos(JSONArray args, int index) throws Exception{ - String location; - JSONArray pos = args.getJSONArray(index); - String lat = pos.getString(0); - String lon = pos.getString(1); - if (isNull(lat) || lat.length() == 0 || isNull(lon) || lon.length() == 0) { - throw new Exception("Expected two non-empty string arguments for lat/lon."); - } - location = lat + "," + lon; - return location; - } - - private String getLocationFromName(JSONArray args, int index) throws Exception{ - String name = args.getString(index); - if (isNull(name) || name.length() == 0) { - throw new Exception("Expected non-empty string argument for place name."); - } - return name; - } - - private String[] splitLatLon(String latlon){ - return latlon.split(","); - } - - private String getAppName(String packageName){ - ApplicationInfo ai; - try { - ai = packageManager.getApplicationInfo(packageName, 0); - } catch (final PackageManager.NameNotFoundException e) { - ai = null; - } - final String applicationName = (String) (ai != null ? packageManager.getApplicationLabel(ai) : null); - return applicationName; - } - - private void discoverAvailableApps(){ - context = this.cordova.getActivity().getApplicationContext(); - packageManager = context.getPackageManager(); - - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(GEO_URI)); - List resolveInfoList = packageManager.queryIntentActivities(intent, 0); - availableApps = new HashMap(); - for (ResolveInfo resolveInfo : resolveInfoList) { - String packageName = resolveInfo.activityInfo.packageName; - String appName = getAppName(packageName); - if(!supportedAppPackages.containsValue(packageName)) { // if it's not already an explicitly supported app - logDebug("Found available app supporting geo protocol: " + appName + " (" + packageName + ")"); - availableApps.put(appName, packageName); - } - } - - // Check if explicitly supported apps are installed - for (Map.Entry entry : supportedAppPackages.entrySet()) { - String _appName = entry.getKey(); - String _packageName = entry.getValue(); - if(isPackageInstalled(_packageName, packageManager)){ - availableApps.put(supportedAppNames.get(_appName), _packageName); - logDebug(_appName+" is available"); - }else{ - logDebug(_appName + " is not available"); - } - } - } - - private boolean isPackageInstalled(String packagename, PackageManager packageManager) { - try { - packageManager.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES); - ApplicationInfo ai = packageManager.getApplicationInfo(packagename, 0); - return ai.enabled; - } catch (PackageManager.NameNotFoundException e) { - return false; - } - } - - private String geocodeAddressToLatLon(String address, CallbackContext callbackContext) throws Exception { - String result = null; - String errMsg = "Unable to geocode coords from address '"+address; - try { - - if(!enableGeocoding){ - handleError("Geocoding disabled: "+errMsg, callbackContext); - return result; - } - - if(!isNetworkAvailable()){ - handleError("No internet connection: "+errMsg, callbackContext); - return result; - } - - address = address.replaceAll(" ", "%20"); - - JSONObject oResponse = doGeocode("address=" + address); - - double longitude = oResponse - .getJSONObject("geometry").getJSONObject("location") - .getDouble("lng"); - - double latitude = oResponse - .getJSONObject("geometry").getJSONObject("location") - .getDouble("lat"); - - result = latitude+","+longitude; - logDebug("Geocoded '"+address+"' to '"+result+"'"); - return result; - }catch(Exception e){ - handleException(errMsg+": "+e.getMessage(), callbackContext); - return result; - } - } - - private String reverseGeocodeLatLonToAddress(String latLon, CallbackContext callbackContext) throws Exception { - String result = null; - String errMsg = "Unable to reverse geocode address from coords '"+latLon; - try { - if(!enableGeocoding){ - handleError("Geocoding disabled: "+errMsg, callbackContext); - return result; - } - - if(!isNetworkAvailable()){ - handleError("No internet connection: "+errMsg, callbackContext); - return result; - } - - JSONObject oResponse = doGeocode("latlng=" + latLon); - result = oResponse.getString("formatted_address"); - logDebug("Reverse geocoded '"+latLon+"' to '"+result+"'"); - return result; - }catch(Exception e){ - handleException(errMsg+": "+e.getMessage(), callbackContext); - return result; - } - } - - private JSONObject doGeocode(String query) throws Exception{ - String url = "http://maps.google.com/maps/api/geocode/json?" + query + "&sensor=false"; - Request request = new Request.Builder() - .url(url) - .build(); - - Response response = httpClient.newCall(request).execute(); - String responseBody = response.body().string(); - JSONObject oResponse = new JSONObject(responseBody); - return ((JSONArray)oResponse.get("results")).getJSONObject(0); - } - - private boolean isNull(String arg){ - return arg == null || arg.equals("null"); - } - - private void logDebug(String msg) { - if(enableDebug){ - Log.d(LOG_TAG, msg); - executeGlobalJavascript("console.log(\""+LOG_TAG+"[native]: "+escapeDoubleQuotes(msg)+"\")"); - } - } - - private void logError(String msg){ - Log.e(LOG_TAG, msg); - if(enableDebug){ - executeGlobalJavascript("console.error(\""+LOG_TAG+"[native]: "+escapeDoubleQuotes(msg)+"\")"); - } - } - - private void handleError(String msg, CallbackContext callbackContext){ - logError(msg); - callbackContext.error(msg); - } - - private void handleException(String msg, CallbackContext callbackContext){ - msg = "Exception occurred: ".concat(msg); - handleError(msg, callbackContext); - } - - private String escapeDoubleQuotes(String string){ - String escapedString = string.replace("\"", "\\\""); - escapedString = escapedString.replace("%22", "\\%22"); - return escapedString; - } - - private void executeGlobalJavascript(final String jsString){ - cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - webView.loadUrl("javascript:" + jsString); - } - }); - } - - private String getAppDisplayName(String packageName){ - String name = "[Not found]"; - if(packageName.equals(GEO)){ - return "[Native chooser]"; - } - for (Map.Entry entry : availableApps.entrySet()) { - String _appName = entry.getKey(); - String _packageName = entry.getValue(); - if(packageName.equals(_packageName)){ - name = _appName; - break; - } - } - return name; - } - - private String getThisAppName(){ - return this.context.getApplicationInfo().loadLabel(this.context.getPackageManager()).toString(); - } - - private boolean isNetworkAvailable() { - ConnectivityManager connectivityManager - = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); - return activeNetworkInfo != null && activeNetworkInfo.isConnected(); - } - -} \ No newline at end of file diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png deleted file mode 100755 index 48ebd8ad..00000000 Binary files a/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png deleted file mode 100755 index 737b6fa4..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png deleted file mode 100755 index f8cbd082..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png deleted file mode 100755 index 006b1b17..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png deleted file mode 100755 index f1346e81..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png deleted file mode 100755 index bd80be84..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png deleted file mode 100755 index c7430245..00000000 Binary files a/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png deleted file mode 100755 index 122f4425..00000000 Binary files a/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png b/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png deleted file mode 100755 index 40bf934b..00000000 Binary files a/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png deleted file mode 100755 index ef7e4f44..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png deleted file mode 100755 index 9b72b588..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png deleted file mode 100755 index 4ae723c2..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png deleted file mode 100755 index e5a0d137..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png deleted file mode 100755 index e1dd562c..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png deleted file mode 100755 index 17fbe4ee..00000000 Binary files a/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png deleted file mode 100755 index e1c9590b..00000000 Binary files a/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png deleted file mode 100755 index f7e87240..00000000 Binary files a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png deleted file mode 100755 index 0fb85452..00000000 Binary files a/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png and /dev/null differ diff --git a/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml b/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml deleted file mode 100755 index be46116d..00000000 --- a/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml b/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml deleted file mode 100755 index 261f3e7f..00000000 --- a/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml b/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml deleted file mode 100755 index 0c6face9..00000000 --- a/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - -