Jen Looper
Developer Advocate at ProgressSW
NativeScript、Firebase、Angular 2 ã¨ããå¼·åãªçµã¿åãããæ´»ç¨ããã°、ã¢ããªã®æ§ç¯ãä¸æ°ã«å éããããã¨ãã§ãã¾ã。ã¯ãªã¹ãã¹ä¼æã®æéä¸ã¯、ã¢ããªã®éçºãã¹ãã¼ãã¢ããããã¦、ãã¬ã¼ã³ããè´ãããã¨ãã家æã®ãã¼ãºã«å¿ããªããã°ãªããªããã、ç¹ã«ãã®ç¹ãéè¦ã«ãªãã¾ã。ã¡ããã©ãããã¨ã«、Angular 2 ãã¼ã¹ã® NativeScript ã¢ããªã§ Firebase ã使ãæ¹æ³ã®ãã¢ãçããã«
ãã¬ã¼ã³ã ãããã¨ãã§ãã¾ã(以ä¸ãã覧ãã ãã ð)。ããã¯、Eddy Verbruggen æ°ã«ããæåãª
NativeScript-Firebase ãã©ã°ã¤ã³ ã®ããã¤ãã®ã³ã³ãã¼ãã³ãã使ã£ããã®ã§ã。
ãã®ãã¥ã¼ããªã¢ã«ã§ã¯、ãã使ããã¦ãã次㮠4 ã¤ã® Firebase æ©è½ã NativeScript ã¢ããªã§ä½¿ç¨ããæ¹æ³ã説æãã¾ã。4 ã¤ã®æ©è½ã«ã¯、ãã°ã¤ã³ã¨ã¦ã¼ã¶ã¼ç»é²ã®æ©è½ãæä¾ãã
Authentication 、ãªã¢ã«ã¿ã¤ã ã«ã¢ãããã¼ãããããã¼ã¿ ã¹ãã¬ã¼ã¸ã®
Realtime Database 、ãªã¢ã¼ãã§ã¢ããªãå¤æ´ã§ãã
Remote Config 、åçãä¿åãã
Storage ãããã¾ã。説æããã«ããã£ã¦、以åã« Ionic ã§æ¸ãã
Giftler ã¢ã㪠ãæ¸ãç´ããã¨ã«ãã¾ãã。
å®éã®ããã¸ã§ã¯ãã§ä½æ¥ã«çæããåã«、
ããã¥ã¡ã³ã ã«ç®ãéã、以ä¸ã®åæäºé
ã«ã¤ãã¦ç¢ºèªãããã¨ããå§ããã¾ã。
ãã¼ã«ã«ãã·ã³ã« NativeScript ãã¤ã³ã¹ãã¼ã«ããã¦ãã、CLI ãåé¡ãªãåä½ãã¦ãããã¨ã確èªãã¾ã。
ã好ã¿ã® IDE ã§、NativeScript 㨠Angular ã®éçºç°å¢ãè¨å®ãã¾ã。TypeScript ãå¿
è¦ã«ãªãã®ã§、ãã©ã³ã¹ãã¤ã« ããã»ã¹ãåä½ãããã¨ã確èªãã¦ããã¾ã。Visual Studio 、Visual Studio Code 、Jetbrains 対å¿ã® IDE ãªã©ã§å©ç¨ã§ããåªãã NativeScript ãã©ã°ã¤ã³ãããã¾ãã、ä¸ã§ã Visual Studio Code ã«ã¯、éçºãå éããã便å©ãªã¹ãããã ãããã¾ã。
Firebase ã¢ã«ã¦ã³ãã«ãã°ã¤ã³ã、ã³ã³ã½ã¼ã« ãéãã¾ã。
Firebase ã³ã³ã½ã¼ã«ã§æ°ããããã¸ã§ã¯ããä½æãã¾ã。ããã§ã¯、「Giftler」ã¨ããååã«ãã¾ãã。ããã«、Firebase ã³ã³ã½ã¼ã«ã§ iOS 㨠Android ã®ã¢ããªãä½æãã¾ã。ãã®éã«、GoogleServices-Info.plist ãã¡ã¤ã«ã¨ google-services.json ãã¡ã¤ã«ããã¦ã³ãã¼ããã¾ã。å¾ã»ã©å¿
è¦ã«ãªãã®ã§、ãã¡ã¤ã«ãé
ç½®ããå ´æã¯è¦ãã¦ããã¦ãã ãã。
ä¾åã¢ã¸ã¥ã¼ã«ã®ã¤ã³ã¹ãã¼ã«
Giftler ã¯、èªè¨¼ãå¿
è¦ãª NativeScript ã¢ããªã®ãµã³ãã«ã¨ãã¦ä½æãã¾ãã。ãã®ã¢ããªã§ã¯、ã¦ã¼ã¶ã¼ãã¯ãªã¹ãã¹ä¼æã«åãåãããã®ããã、åçã説æã¨ã¨ãã«ä¸è¦§è¡¨ç¤ºã§ãã¾ã。ç¾æç¹ã§、ãã®ã¢ããªã«ã¯ iOS ç㨠Android çããã、以ä¸ã®æ©è½ãããã¾ã。
ãã°ã¤ã³、ãã°ã¢ã¦ã、ã¦ã¼ã¶ã¼ç»é²、ããã³「ãã¹ã¯ã¼ããå¿ãã」å ´åã®å¦çã®å®è¡
ã¦ã¼ã¶ã¼ã«ãããªã¹ãã¸ã®ã®ããé
ç®ã®ç»é²
ã¦ã¼ã¶ã¼ã«ãããªã¹ãããã®ã®ããé
ç®ã®åé¤
ã¦ã¼ã¶ã¼ã«ãããªã¹ãã®åã®ããé
ç®ã®ç·¨é(説æãåçã®è¿½å )
ããã¯ã¨ã³ãã§ããã«å¤æ´ã§ãã Firebase ã® Remote Config ãµã¼ãã¹ã«ããã¡ãã»ã¼ã¸ã³ã°
ããã§ã¯、
Giftler ã®ã½ã¼ã¹ã³ã¼ã ããã©ã¼ã¯ãã¾ããã。ããã¯、åé¡ãªãåä½ãã¦ããå®å
¨çã®ã¢ããªã§ã。ã¢ããªãã¯ãã¼ã³ã§ããã、ã¢ããªãä½æããéã«ãã¦ã³ãã¼ããã、ç¾å¨ã® Firebase é¢é£ã®ã¢ããªã®ãã¡ã¤ã«ãç½®ãæãã¾ã。
Firebase ãããã¦ã³ãã¼ããã google.services.json ãã¡ã¤ã«ã /app/App_Resources/Android folder
ã«é
ç½®ãã¾ã。
åæ§ã«、Firebase ãããã¦ã³ãã¼ããã GoogleService-Info.plist ãã¡ã¤ã«ã /app/App_Resources/iOS folder
ã«é
ç½®ãã¾ã。
ãããã®ãã¡ã¤ã«ã¯、ã¢ããªã§ Firebase ãåæåã、é¢é£ããå¤é¨ãµã¼ãã¹ã«æ¥ç¶ããããã«å¿
è¦ã§ã。
次ã«、ã¢ããªã®ã«ã¼ãã«ãã
package.json
ã確èªãã¾ã。ãã®ãã¡ã¤ã«ã«ã¯、ã¢ããªã§ä½¿ç¨ãããã©ã°ã¤ã³ãå«ã¾ãã¦ãã¾ã。ããã§ã¯、NativeScript ã«é¢é£ãããã©ã°ã¤ã³ã«æ³¨ç®ãã¦ãã ãã。
"nativescript-angular":"1.2.0",
"nativescript-camera": "^0.0.8",
"nativescript-iqkeyboardmanager": "^1.0.1",
"nativescript-plugin-firebase": "^3.8.4",
"nativescript-theme-core": "^1.0.2",
NativeScript-Angular ãã©ã°ã¤ã³ã¯、Angular 㨠NativeScript ãçµ±åãããã©ã°ã¤ã³ã§ã。Camera ãã©ã°ã¤ã³ã使ãã¨、å°ãã«ã¡ã©ã管çãããããªãã¾ã。IQKeyboardManager 㯠iOS å°ç¨ã®ãã©ã°ã¤ã³ã§、åä»ãª iOS ã®ãã¼ãã¼ãã管çãã¦ããã¾ã。Theme ãã©ã°ã¤ã³ã¯、ã¹ãã³ãå®å
¨ã«èªä½ããªãã¦ãããã©ã«ãã®ã¹ã¿ã¤ã«ãã¢ããªã«è¿½å ã§ãããã°ããããã©ã°ã¤ã³ã§ã。æå¾ã«、ãã®ã¢ããªã§ãã£ã¨ãéè¦ãªã®ã Firebase ãã©ã°ã¤ã³ã§ã。
以ä¸ã®ä¾åã¢ã¸ã¥ã¼ã«ãé
ç½®ãã¦、ãã©ã°ã¤ã³ãã¤ã³ã¹ãã¼ã«ããæºåãã§ããã、iOS 㨠Android ã®ããããã®ã³ã¼ããæ ¼ç´ããã
platforms
ãã©ã«ããä½æã、Firebase ãã©ã°ã¤ã³ããã®ä»ã® npm ãã¼ã¹ã®ãã©ã°ã¤ã³ãåæåãã¦、ã¢ããªãæ§ç¯ã§ããããã«ãã¾ã。NativeScript CLI ã使ã£ã¦ã¯ãã¼ã³ããã¢ããªã®ã«ã¼ãã«ç§»åã、
tns
run ios
ã¾ãã¯
tns run android
ãå®è¡ãã¾ã。ããã«ãã£ã¦ãã©ã°ã¤ã³ããã«ãããã«ã¼ãã³ãéå§ããã¾ã。ä¸ã§ã、Firebase ãã©ã°ã¤ã³ã®ãã¾ãã¾ãªãã¼ãã®ã¤ã³ã¹ãã¼ã«ãå§ã¾ããã¨ã確èªã§ããã¯ãã§ã。ã¤ã³ã¹ãã¼ã« ã¹ã¯ãªãããå®è¡ãããã¨、ãã¾ãã¾ãª Firebase ãµã¼ãã¹ãçµ±åããããã®ã³ã³ãã¼ãã³ããã¤ã³ã¹ãã¼ã«ãããã©ããã®ç¢ºèªã表示ããã¾ã。ããã§ã¯、Messaging ã¨ã½ã¼ã·ã£ã«èªè¨¼ãé¤ããã¹ã¦ãé¸æãã¾ã。ããã§ã®å¤§ããªç¹å¾´ã¯、firebase.nativescript.json ãã¡ã¤ã«ãã¢ããªã®ã«ã¼ãã«ã¤ã³ã¹ãã¼ã«ããããã¨ã§ã。ãã®ãã、ä»å¾ãã©ã°ã¤ã³ã®æ°ãããã¼ããã¤ã³ã¹ãã¼ã«ãããå ´å、ãã®ãã¡ã¤ã«ãç·¨éããã ãã§ãã©ã°ã¤ã³ãåã¤ã³ã¹ãã¼ã«ã§ãã¾ã。
ããã§、
tns livesync ios --watch
ã¾ãã¯
tns livesync android
--watch
ãå®è¡ã、ã¨ãã¥ã¬ã¼ã¿ã§ã¢ããªãèµ·åãã¦å¤æ´ãç£è¦ããããã¨ã確èªããã¨、ã¢ããªãå®è¡ããã¦æ°ãããã°ã¤ã³ããæºåãã§ãã¦ãããã¨ããããã¾ã。ãã ã、ãã°ã¤ã³ãè¡ãåã«、Firebase ã³ã³ã½ã¼ã«ã® [Authentication] ã¿ãããã¡ã¼ã« / ãã¹ã¯ã¼ãã«ãããã°ã¤ã³ãæå¹ã«ãã¦、Firebase ããã®ã¿ã¤ãã®ãã°ã¤ã³ãå¦çã§ããããã«ããå¿
è¦ãããã¾ã。
ãã®è£ã§ä½ãèµ·ãã£ã¦ãããã確èªããããã«、å°ãã°ããå
é¨ã®ä»çµã¿ãè¦ã¦ã¿ã¾ããã。Firebase ã«ãã°ã¤ã³ããã«ã¯、ã¤ã³ã¹ãã¼ã«ãã Firebase ãµã¼ãã¹ãåæåãã¦ããå¿
è¦ãããã¾ã。
app/main.ts
ã«ã¯、ããã¤ãèå³æ·±ãç¹ãããã¾ã。
// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app.module";
import { BackendService } from "./services/backend.service";
import firebase = require("nativescript-plugin-firebase");
firebase.init({
//persist should be set to false as otherwise numbers aren't returned during
livesync
persist: false,
storageBucket: 'gs://giftler-f48c4.appspot.com',
onAuthStateChanged: (data: any) => {
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}
}).then(
function (instance) {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
platformNativeScriptDynamic().bootstrapModule(AppModule);
æåã«、ãã©ã°ã¤ã³ãã firebase ãã¤ã³ãã¼ãã、.init() ãå¼ã³åºãã¾ã。次㫠storageBucket ããããã£ãç·¨éã、Firebase ã³ã³ã½ã¼ã«ã® [Storage] ã¿ãã«è¡¨ç¤ºããã¦ããå¤ãè²¼ãä»ãã¾ã。
ããã§、ã使ãã® Firebase ã¢ã«ã¦ã³ãã«åããã¦ã¢ããªãã«ã¹ã¿ãã¤ãºãã、ã¢ããªã§æ°ããã¦ã¼ã¶ã¼ã®ç»é²ã¨ãã°ã¤ã³ãå¯è½ã«ãªãã¯ãã§ã。å¿
è¦ã«å¿ãã¦、
app/login/login.component.ts
ãã¡ã¤ã«ã® user.email 㨠password å¤æ°ãç·¨éãã¦、ããã©ã«ãã®ãã°ã¤ã³èªè¨¼æ
å ±ã
[email protected]
ãããèªèº«ã®ãã°ã¤ã³ã¨ãã¹ã¯ã¼ãã«å¤æ´ãããã¨ãã§ãã¾ã。
iOS 㨠Android ã®ãã°ã¤ã³ç»é¢
注: iOS ã§ã¯、Xcode ã·ãã¥ã¬ã¼ã¿ã使ãã¨ããã«ã¢ããªãã¨ãã¥ã¬ã¼ãã§ãã¾ã。ãã ã Android ã§ã¯、ã¢ããªãã¨ãã¥ã¬ã¼ã¿ã«ã¤ã³ã¹ãã¼ã«ããããã«、Google Services ã®æå¹åãªã©、追å ã§ããã¤ãã®æé ãå¿
è¦ã«ãªãå ´åãããã¾ã。
ã³ã¼ãã®æ§é ã¨èªè¨¼
Angular 2 ã®ãã¶ã¤ã³ ãã¿ã¼ã³ã§ã¯、ã³ã¼ããã¢ã¸ã¥ã¼ã«åããå¿
è¦ãããã¾ã。ãã®ãã、以ä¸ã®ã³ã¼ãæ§é ã«å¾ããã®ã¨ãã¾ã。
—login
login.component.ts
login.html
login.module.ts
login.routes.ts
—list …
—list-detail …
—models
gift.model.ts
user.model.ts
index.ts
—services
backend.service.ts
firebase.service.ts
utils.service.ts
index.ts
app.component.ts
app.css
app.module.ts
app.routes.ts
auth-guard.service.ts
main.ts
Firebase ã®èªè¨¼ã Angular 2 ã® auth-guard.service ã¨é£æºããæ¹æ³ã«æ³¨ç®ãã¦ãã ãã。åè¿°ã®ããã«、ã¢ããªã®
app/main.ts
㧠Firebase ãåæåããã¾ã。ãã®éã«、
onAuthStateChanged
é¢æ°ãå¼ã³åºããã¾ã。
onAuthStateChanged: (data: any) => {
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}
ã¢ããªãèµ·åããéã«、Firebase ããè¿ããããã¼ã¿ãæåååãããã®ãã³ã³ã½ã¼ã«ã§ç¢ºèªãã¦ãã ãã。ãã®ã¦ã¼ã¶ã¼ã«
loggedIn
ãã©ã°ãç«ã£ã¦ããå ´å、Firebase ããéãè¿ããã userId ã
token
ã¨ãã¦è¨å®ãã¾ã。NativeScript ã¢ããªã±ã¼ã·ã§ã³è¨å®ã¢ã¸ã¥ã¼ã«ã使ã£ã¦、ãã® userId ãä¿åãããã¤、ããããä½æãããã¼ã¿ã¨é¢é£ä»ãã¾ã。ãã®ã¢ã¸ã¥ã¼ã«ã¯、localStorage ã®ãããªæ©è½ãæã¤ã¢ã¸ã¥ã¼ã«ã§ã。ãã®ãã¼ã¯ã³ã¨ãã¼ã¯ã³ã使ãèªè¨¼ãã¹ãã¯
app/services/backend.service.ts
ãã¡ã¤ã«ã§ç®¡çããã¦ãã、
app/auth-guard.service.ts
ãã¡ã¤ã«ã§å©ç¨ã§ãã¾ã。auth-guard ãã¡ã¤ã«ã¯、ã¢ããªã®ãã°ã¤ã³ããã³ãã°ã¢ã¦ãç¶æ
ãé©åã«ç®¡çããæ¹æ³ãæä¾ãã¦ãã¾ã。
AuthGuard ã¯ã©ã¹ã¯、Angular Router ã¢ã¸ã¥ã¼ã«ã® CanActivate ã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£
ãã¦ãã¾ã。
export class AuthGuard implements CanActivate {
constructor(private router:Router) { }
canActivate() {
if (BackendService.isLoggedIn()) {
return true;
}
else {
this.router.navigate(["/login"]);
return false;
}
}
åºæ¬çã«ã¯、åè¿°ã®ãã°ã¤ã³ ã«ã¼ãã³ã§ãã¼ã¯ã³ãè¨å®ãã、ã㤠BackendService.isLoggedIn é¢æ°ã true ãè¿ãå ´å、ã¢ããªã§ããã©ã«ãã®ã«ã¼ãã§ããã¦ã£ãã·ã¥ãªã¹ãã¸ã®ããã²ã¼ã·ã§ã³ã許å¯ããã¾ã。ããã、ãã以å¤ã®å ´å、ã¦ã¼ã¶ã¼ã¯ãã°ã¤ã³ç»é¢ã«æ»ããã¾ã。
const listRoutes:Routes = [
{ path: "", component:ListComponent, canActivate: [AuthGuard] },
];
ããã§、Firebase ã使ã NativeScript ã¢ããªãåæåã§ãã¾ãã。次ã¯、ã¢ããªã«ãã¼ã¿ãèªã¿è¾¼ã¿、Firebase ã®ãã°ããããªã¢ã«ã¿ã¤ã æ§ãæ´»ç¨ãã¦、ã¢ãããã¼ãããããã¼ã¿ãã¼ã¹ã®å
容ãç£è¦ããæ¹æ³ã«ã¤ãã¦å¦ãã§ããã¾ããã。
ãªã¹ãã®ä½æã¨ããã«ãã§ãã¯
ã¦ã£ãã·ã¥ãªã¹ãã®ãã¼ã¹ã¨ãªã£ã¦ãã
app/list/list.html
ãã説æãã¾ã。ããã«ã¯、ããã¹ãé
ç®ã¨ç©ºã®ãªã¹ãã表示ããã¦ããã¯ãã§ã。ã§ã¯、ãµã³ã¿ããã«æ¬²ãããã®ãä¼ãã¦ã¿ã¾ããã。é
ç®ããã¼ã¿ãã¼ã¹ã«éä¿¡ãã、ãªã¢ã«ã¿ã¤ã ã«ãªã¹ãã«è¿½å ããã¾ã。ãããã©ããã£ã¦å®ç¾ãã¦ããããè¦ã¦ã¿ã¾ããã。
app/list/list.component.ts
ã§ã¯、æåã«ã®ããã®ãªã¹ããä¿æããããã®ç£è¦å¯è½ãªãã¸ã§ã¯ããè¨å®ãã¦ãã¾ã。
public gifts$: Observable;
次ã«、ã³ã³ãã¼ãã³ãã®åæåã®éã«、ãã¼ã¿ãã¼ã¹ãããªã¹ããèªã¿è¾¼ã¿ã¾ã。
ngOnInit(){
this.gifts$ = this.firebaseService.getMyWishList();
}
ãããããã®ã¯ firebaseService ãã¡ã¤ã«ã§ã。ãã®é¢æ°ã§ã¯、ãªã¹ãã¼ã追å ã㦠Firebase Database ã® Gifts ã³ã¬ã¯ã·ã§ã³ã®å¤æ´ãç£è¦ããç£è¦å¯è½ãªãã¸ã§ã¯ã rxjs ãè¿ãã¦ãã¾ã。ãã®æ¹æ³ã«æ³¨ç®ãã¦ãã ãã。
getMyWishList():Observable {
return new Observable((observer: any) => {
let path = 'Gifts';
let onValueEvent = (snapshot: any) => {
this.ngZone.run(() => {
let results = this.handleSnapshot(snapshot.value);
console.log(JSON.stringify(results))
observer.next(results);
});
};
firebase.addValueEventListener(onValueEvent, `/${path}`);
}).share();
}
ãã®ã¯ã¨ãªã®çµæã¯、次ã«ç¤ºã
handleSnapshot
é¢æ°ã§å¦çããã¾ã。ãã®é¢æ°ã¯、ã¦ã¼ã¶ã¼ããã£ã«ã¿ãªã³ã°ãããã¼ã¿ã _allItems é
åã«è¨å®ãã¦ãã¾ã。
handleSnapshot(data: any) {
//empty array, then refill and filter
this._allItems = [];
if (data) {
for (let id in data) {
let result = (Object).assign({id: id}, data[id]);
if(BackendService.token === result.UID){
this._allItems.push(result);
}
}
this.publishUpdates();
}
return this._allItems;
}
æå¾ã«、publishUpdates ãå¼ã³åºããã¾ã。ãã®é¢æ°ã¯、æ°ããé
ç®ãå
é ã«è¡¨ç¤ºãããããã«、æ¥ä»ã§ãã¼ã¿ã並ã³æ¿ãã¦ãã¾ã。
publishUpdates() {
// here, we sort must emit a *new* value (immutability!)
this._allItems.sort(function(a, b){
if(a.date < b.date) return -1;
if(a.date > b.date) return 1;
return 0;
})
this.items.next([...this._allItems]);
}
ç£è¦å¯è½ãªãã¸ã§ã¯ã $gifts ã«ãã¼ã¿ãè¨å®ãããã¨、è¦ç´ ã®ç·¨éãåé¤ãè¡ããã³ã«ãªã¹ãã¼ãå¼ã°ã、ããã³ãã¨ã³ããé©åã«ã¢ãããã¼ãããã¾ã。getMyWishList ã¡ã½ããå
ã® onValueEvent é¢æ°ã§
ngZone ã使ããã¦ãããã¨ã«æ³¨æãã¦ãã ãã。ããã«ãã£ã¦、éåæã«è¡ããããã¼ã¿ã®ã¢ãããã¼ãã«å¿ã㦠UI ãé©åã«ã¢ãããã¼ãããã¾ã。NativeScript ã¢ããªã® ngZone ã®æ¦è¦ã«ã¤ãã¦ã¯、
ãã¡ã ãã覧ãã ãã。
ã¡ãã»ã¼ã¸ã®ãªã¢ã¼ãè¨å®
ãã 1 ã¤ã®åªãã Firebase ãµã¼ãã¹ã«「Remote Config」ãããã¾ã。ããã¯、Firebase ã®ããã¯ã¨ã³ãããã¢ããªãã¢ãããã¼ãã§ããæ©è½ã§ã。Remote Config ã使ãã¨、ã¢ããªã®æ©è½ã®ãªã³、ãªããåãæ¿ããã、UI ãå¤æ´ãããã§ãã¾ã。ããã§ã¯、ãµã³ã¿ããããã¡ãã»ã¼ã¸ãéãæ©è½ã追å ãã¦ã¿ã¾ããã。
app/list/list.html
ã«ã¯、次ã®ã¡ãã»ã¼ã¸ ããã¯ã¹ãããã¾ã。
<Label class="gold card" textWrap="true" [text]="message$ | async"></Label>
ç£è¦å¯è½ãªãã¸ã§ã¯ã
message$
ã¯、ãã¼ã¿ãªã¹ãã¨ã»ã¼åãæ¹æ³ã§çµã¿è¾¼ã¾ãã¦ãã¾ãã、ããã§ã¯ã¢ããªãæ°ããåæåããããã³ã«å¤æ´ãé©ç¨ããã¾ã。
ngOnInit(){
this.message$ = this.firebaseService.getMyMessage();
}
ç§å¯ã¯、次ã«ç¤ºããµã¼ãã¹ã¬ã¤ã¤(
app/services/firebase.service.ts
)ã«ããã¾ã。
getMyMessage():Observable{
return new Observable((observer:any) => {
firebase.getRemoteConfig({
developerMode: false,
cacheExpirationSeconds: 300,
properties: [{
key: "message",
default:"Happy Holidays!"
}]
}).then(
function (result) {
console.log("Fetched at " + result.lastFetch + (result.throttled ? " (throttled)" : ""));
for (let entry in result.properties)
{
observer.next(result.properties[entry]);
}
}
);
}).share();
}
好ããªã ãæ°ããã¡ãã»ã¼ã¸ãçºè¡å¯è½
注: ã¢ããªããå¿
è¦ã®ãªãé«é »åº¦ã§ Remote Config ã®å¤ãåå¾ããã¨、Remote Config ã®å©ç¨ãå¶éããã¦ãã¾ãå ´åãããã¾ãã®ã§、æ
éã«éçºãã¦ãã ãã。
åçãæ®ã
ãã®ããã¸ã§ã¯ãã®ãããããã¨ããã¯、é¸ãã ãã¬ã¼ã³ãã®åçãæ®ã£ã¦ Firebase Storage ã«æ ¼ç´ã§ããç¹ã§ããã。åè¿°ã®ããã«、ãã®é¨åã«ã¯ Camera ãã©ã°ã¤ã³ã使ãã¾ãã。ããã§ãã¼ãã¦ã§ã¢ã®ç®¡çãå°ã楽ã«ãªãã¾ã。æåã«、
app/list-detail/list-detail.component.ts
ã® ngOnInit() ã¡ã½ããã§ãã¼ããã·ã§ã³ ã»ãããåå¾ã、ã¢ããªãã«ã¡ã©ããã¤ã¹ã«ã¢ã¯ã»ã¹ã§ããããã«ãã¾ã。
ngOnInit() {
camera.requestPermissions();
...
}
ã¦ã¼ã¶ã¼ã詳細ç»é¢ã® [Photo] ãã¿ã³ãã¯ãªãã¯ããã¨、ã¤ãã³ã ãã§ã¼ã³ãå§ã¾ãã¾ã。æåã«å¼ã°ããã®ã¯æ¬¡ã®ã³ã¼ãã§ã。
takePhoto() {
let options = {
width:300,
height:300,
keepAspectRatio: true,
saveToGallery: true
};
camera.takePicture(options)
.then(imageAsset => {
imageSource.fromAsset(imageAsset).then(res => {
this.image = res;
//save the source image to a file, then send that file path to firebase
this.saveToFile(this.image);
})
}).catch(function (err) {
console.log("Error -> " + err.message);
});
}
ã«ã¡ã©ã§åçãæ®å½±ãã、ãã®åçã imageAsset ã¨ãã¦ä¿åããã¦ç»é¢ã«è¡¨ç¤ºããã¾ã。ãã®ã¤ã¡ã¼ã¸ã¯ãã¡ã¤ã«ã¨ãã¦ãã¼ã«ã«ã«ä¿åããã¾ã。ãã®éã«、æ¥ä»ã®ã¿ã¤ã ã¹ã¿ã³ãã«å¾ã£ãååãä»ãããã¾ã。ã¾ã、ä»å¾ã®å©ç¨ã«åãã¦、ãã¹ãä¿åããã¾ã。
saveToFile(res){
let imgsrc = res;
this.imagePath =
this.utilsService.documentsPath(`photo-${Date.now()}.png`);
imgsrc.saveToFile(this.imagePath, enums.ImageFormat.png);
}
[Save] ãã¿ã³ãæ¼ãããã¨、ã¤ã¡ã¼ã¸ã¯ãã¼ã«ã«ãã¹çµç±ã§ Firebase ã«éä¿¡ãã、ã¹ãã¬ã¼ã¸ ã¢ã¸ã¥ã¼ã«å
ã«ä¿åããã¾ã。ã¢ããªã«è¿ããã Firebase ã®ãã«ãã¹ã¯、
/Gifts
ãã¼ã¿ãã¼ã¹ ã³ã¬ã¯ã·ã§ã³ã«ä¿åããã¾ã。
editGift(id: string){
if(this.image){
//upload the file, then save all
this.firebaseService.uploadFile(this.imagePath).then((uploadedFile: any) =>
{
this.uploadedImageName = uploadedFile.name;
//get downloadURL and store it as a full path;
this.firebaseService.getDownloadUrl(this.uploadedImageName).then((downloadUrl: string) => {
this.firebaseService.editGift(id,this.description,downloadUrl).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
})
}, (error: any) => {
alert('File upload error: ' + error);
});
}
else {
//just edit the description
this.firebaseService.editDescription(id,this.description).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
}
}
ãã®ã¤ãã³ã ãã§ã¼ã³ã¯ä¸è¦è¤éããã§ãã、æçµçã«å®è¡ãããã®ã¯、Firebase ãµã¼ãã¹ ãã¡ã¤ã«ã®ä¸ã®æ°è¡ã§ã。
uploadFile(localPath: string, file?: any): Promise {
let filename = this.utils.getFilename(localPath);
let remotePath = `${filename}`;
return firebase.uploadFile({
remoteFullPath: remotePath,
localFullPath: localPath,
onProgress: function(status) {
console.log("Uploaded fraction: " + status.fractionCompleted);
console.log("Percentage complete: " + status.percentageCompleted);
}
});
}
getDownloadUrl(remoteFilePath: string): Promise {
return firebase.getDownloadUrl({
remoteFullPath: remoteFilePath})
.then(
function (url:string) {
return url;
},
function (errorMessage:any) {
console.log(errorMessage);
});
}
editGift(id:string, description: string, imagepath: string){
this.publishUpdates();
return firebase.update("/Gifts/"+id+"",{
description: description,
imagepath: imagepath})
.then(
function (result:any) {
return 'You have successfully edited this gift!';
},
function (errorMessage:any) {
console.log(errorMessage);
});
}
æçµçãªçµæã§ã¯、ã¦ã£ãã·ã¥ãªã¹ãã«è¡¨ç¤ºããã®ããã®åçã¨èª¬æã®ä¸¡æ¹ããã¾ãåå¾ã§ãã¦ãã¾ã。ããã§ãããµã³ã¿ããã¯、ã«ã¤ãªã¼ã®ã©ã®ã¢ã¤ã©ã¤ãã¼ãè²·ãã°ããã®ãããããªãã¨ããè¨ã訳ã¯ã§ãã¾ãã。å¼·å㪠NativeScript 㨠Angular ãçµã¿åãããã°、æ°å㧠iOS 㨠Android ã®ãã¤ãã£ã ã¢ããªãä½ããã¨ãã§ãã¾ã。ããã« Firebase ã追å ããã°、ã¢ããªã®ã¦ã¼ã¶ã¼、ã¤ã¡ã¼ã¸、ãã¼ã¿ãä¿åããå¼·åãªæ©è½ãå©ç¨ã§ã、ããã«ç«¯æ«éã§ãªã¢ã«ã¿ã¤ã ã«ãã¼ã¿ãã¢ãããã¼ããããã¨ãå¯è½ã«ãªãã¾ã。ãã°ãããã¨æãã¾ããã。ãã®ã¢ããªã¯、次ã®ããã«ãªãã¾ã。
ããã¾ã§、å
å®ããã¦ã£ãã·ã¥ãªã¹ã管çã¢ããªã®ä½æã«åãã¦é 調ã«é²ãã§ãã¾ãã。ããã、ãµã³ã¿ããã«é¡ããã¨ãä¼ããæé«ã®æ¹æ³ã¯ã¾ã 模索ä¸ã¨è¨ããã§ããã。次ã®ã¹ãããã¨ãã¦ã¯、Mailgun ã®ã¡ã¼ã«ã¨ã®çµ±åãããã·ã¥éç¥ã®å©ç¨ãèãããã¾ã。ããã¾ã§ã®é、ãã°ãããã¯ãªã¹ãã¹ä¼æããéãããã ãã。çããã Firebase ãå©ç¨ãã¦ãã¦ã㪠NativeScript ã¢ããªãä½ããããã«ãç¥ããã¾ã。
NativeScript ã«ã¤ãã¦ããã«è©³ããå¦ã³ããæ¹ã¯、
http://www.nativescript.org ãã覧ãã ãã。質åãããæ¹ã¯、
ãã¡ã ãã NativeScript ã® Slack ãã£ã³ãã«ã«åå ãã¦ãã ãã。
Posted by
Khanh LeViet - Developer Relations Team
ãã®è¨äºã¯ã²ã¹ã ããã¬ã¼ Jen Looper ã«ãã The Firebase Blog ã®è¨äº "The Firebase Blog: Building a NativeScript + Angular 2 Mobile App using Firebase " ãå
ã«ç¿»è¨³・å çãããã®ã§ã。詳ããã¯å
è¨äºãã覧ãã ãã。
Jen Looper
Developer Advocate at ProgressSW
NativeScript、Firebase、Angular 2 ã¨ããå¼·åãªçµã¿åãããæ´»ç¨ããã°、ã¢ããªã®æ§ç¯ãä¸æ°ã«å éããããã¨ãã§ãã¾ã。ã¯ãªã¹ãã¹ä¼æã®æéä¸ã¯、ã¢ããªã®éçºãã¹ãã¼ãã¢ããããã¦、ãã¬ã¼ã³ããè´ãããã¨ãã家æã®ãã¼ãºã«å¿ããªããã°ãªããªããã、ç¹ã«ãã®ç¹ãéè¦ã«ãªãã¾ã。ã¡ããã©ãããã¨ã«、Angular 2 ãã¼ã¹ã® NativeScript ã¢ããªã§ Firebase ã使ãæ¹æ³ã®ãã¢ãçããã«ãã¬ã¼ã³ã ãããã¨ãã§ãã¾ã(以ä¸ãã覧ãã ãã ð)。ããã¯、Eddy Verbruggen æ°ã«ããæå㪠NativeScript-Firebase ãã©ã°ã¤ã³ ã®ããã¤ãã®ã³ã³ãã¼ãã³ãã使ã£ããã®ã§ã。
ãã®ãã¥ã¼ããªã¢ã«ã§ã¯、ãã使ããã¦ãã次㮠4 ã¤ã® Firebase æ©è½ã NativeScript ã¢ããªã§ä½¿ç¨ããæ¹æ³ã説æãã¾ã。4 ã¤ã®æ©è½ã«ã¯、ãã°ã¤ã³ã¨ã¦ã¼ã¶ã¼ç»é²ã®æ©è½ãæä¾ãã Authentication 、ãªã¢ã«ã¿ã¤ã ã«ã¢ãããã¼ãããããã¼ã¿ ã¹ãã¬ã¼ã¸ã® Realtime Database 、ãªã¢ã¼ãã§ã¢ããªãå¤æ´ã§ãã Remote Config 、åçãä¿åãã Storage ãããã¾ã。説æããã«ããã£ã¦、以åã« Ionic ã§æ¸ãã Giftler ã¢ã㪠ãæ¸ãç´ããã¨ã«ãã¾ãã。
å®éã®ããã¸ã§ã¯ãã§ä½æ¥ã«çæããåã«、ããã¥ã¡ã³ã ã«ç®ãéã、以ä¸ã®åæäºé
ã«ã¤ãã¦ç¢ºèªãããã¨ããå§ããã¾ã。
ãã¼ã«ã«ãã·ã³ã« NativeScript ãã¤ã³ã¹ãã¼ã«ããã¦ãã、CLI ãåé¡ãªãåä½ãã¦ãããã¨ã確èªãã¾ã。
ã好ã¿ã® IDE ã§、NativeScript 㨠Angular ã®éçºç°å¢ãè¨å®ãã¾ã。TypeScript ãå¿
è¦ã«ãªãã®ã§、ãã©ã³ã¹ãã¤ã« ããã»ã¹ãåä½ãããã¨ã確èªãã¦ããã¾ã。Visual Studio 、Visual Studio Code 、Jetbrains 対å¿ã® IDE ãªã©ã§å©ç¨ã§ããåªãã NativeScript ãã©ã°ã¤ã³ãããã¾ãã、ä¸ã§ã Visual Studio Code ã«ã¯、éçºãå éããã便å©ãªã¹ãããã ãããã¾ã。
Firebase ã¢ã«ã¦ã³ãã«ãã°ã¤ã³ã、ã³ã³ã½ã¼ã« ãéãã¾ã。
Firebase ã³ã³ã½ã¼ã«ã§æ°ããããã¸ã§ã¯ããä½æãã¾ã。ããã§ã¯、「Giftler」ã¨ããååã«ãã¾ãã。ããã«、Firebase ã³ã³ã½ã¼ã«ã§ iOS 㨠Android ã®ã¢ããªãä½æãã¾ã。ãã®éã«、GoogleServices-Info.plist ãã¡ã¤ã«ã¨ google-services.json ãã¡ã¤ã«ããã¦ã³ãã¼ããã¾ã。å¾ã»ã©å¿
è¦ã«ãªãã®ã§、ãã¡ã¤ã«ãé
ç½®ããå ´æã¯è¦ãã¦ããã¦ãã ãã。
ä¾åã¢ã¸ã¥ã¼ã«ã®ã¤ã³ã¹ãã¼ã«
Giftler ã¯、èªè¨¼ãå¿
è¦ãª NativeScript ã¢ããªã®ãµã³ãã«ã¨ãã¦ä½æãã¾ãã。ãã®ã¢ããªã§ã¯、ã¦ã¼ã¶ã¼ãã¯ãªã¹ãã¹ä¼æã«åãåãããã®ããã、åçã説æã¨ã¨ãã«ä¸è¦§è¡¨ç¤ºã§ãã¾ã。ç¾æç¹ã§、ãã®ã¢ããªã«ã¯ iOS ç㨠Android çããã、以ä¸ã®æ©è½ãããã¾ã。
ãã°ã¤ã³、ãã°ã¢ã¦ã、ã¦ã¼ã¶ã¼ç»é²、ããã³「ãã¹ã¯ã¼ããå¿ãã」å ´åã®å¦çã®å®è¡
ã¦ã¼ã¶ã¼ã«ãããªã¹ãã¸ã®ã®ããé
ç®ã®ç»é²
ã¦ã¼ã¶ã¼ã«ãããªã¹ãããã®ã®ããé
ç®ã®åé¤
ã¦ã¼ã¶ã¼ã«ãããªã¹ãã®åã®ããé
ç®ã®ç·¨é(説æãåçã®è¿½å )
ããã¯ã¨ã³ãã§ããã«å¤æ´ã§ãã Firebase ã® Remote Config ãµã¼ãã¹ã«ããã¡ãã»ã¼ã¸ã³ã°
ããã§ã¯、Giftler ã®ã½ã¼ã¹ã³ã¼ã ããã©ã¼ã¯ãã¾ããã。ããã¯、åé¡ãªãåä½ãã¦ããå®å
¨çã®ã¢ããªã§ã。ã¢ããªãã¯ãã¼ã³ã§ããã、ã¢ããªãä½æããéã«ãã¦ã³ãã¼ããã、ç¾å¨ã® Firebase é¢é£ã®ã¢ããªã®ãã¡ã¤ã«ãç½®ãæãã¾ã。
Firebase ãããã¦ã³ãã¼ããã google.services.json ãã¡ã¤ã«ã /app/App_Resources/Android folder
ã«é
ç½®ãã¾ã。
åæ§ã«、Firebase ãããã¦ã³ãã¼ããã GoogleService-Info.plist ãã¡ã¤ã«ã /app/App_Resources/iOS folder
ã«é
ç½®ãã¾ã。
ãããã®ãã¡ã¤ã«ã¯、ã¢ããªã§ Firebase ãåæåã、é¢é£ããå¤é¨ãµã¼ãã¹ã«æ¥ç¶ããããã«å¿
è¦ã§ã。
次ã«、ã¢ããªã®ã«ã¼ãã«ãã package.json
ã確èªãã¾ã。ãã®ãã¡ã¤ã«ã«ã¯、ã¢ããªã§ä½¿ç¨ãããã©ã°ã¤ã³ãå«ã¾ãã¦ãã¾ã。ããã§ã¯、NativeScript ã«é¢é£ãããã©ã°ã¤ã³ã«æ³¨ç®ãã¦ãã ãã。
"nativescript-angular":"1.2.0",
"nativescript-camera": "^0.0.8",
"nativescript-iqkeyboardmanager": "^1.0.1",
"nativescript-plugin-firebase": "^3.8.4",
"nativescript-theme-core": "^1.0.2",
NativeScript-Angular ãã©ã°ã¤ã³ã¯、Angular 㨠NativeScript ãçµ±åãããã©ã°ã¤ã³ã§ã。Camera ãã©ã°ã¤ã³ã使ãã¨、å°ãã«ã¡ã©ã管çãããããªãã¾ã。IQKeyboardManager 㯠iOS å°ç¨ã®ãã©ã°ã¤ã³ã§、åä»ãª iOS ã®ãã¼ãã¼ãã管çãã¦ããã¾ã。Theme ãã©ã°ã¤ã³ã¯、ã¹ãã³ãå®å
¨ã«èªä½ããªãã¦ãããã©ã«ãã®ã¹ã¿ã¤ã«ãã¢ããªã«è¿½å ã§ãããã°ããããã©ã°ã¤ã³ã§ã。æå¾ã«、ãã®ã¢ããªã§ãã£ã¨ãéè¦ãªã®ã Firebase ãã©ã°ã¤ã³ã§ã。
以ä¸ã®ä¾åã¢ã¸ã¥ã¼ã«ãé
ç½®ãã¦、ãã©ã°ã¤ã³ãã¤ã³ã¹ãã¼ã«ããæºåãã§ããã、iOS 㨠Android ã®ããããã®ã³ã¼ããæ ¼ç´ããã platforms
ãã©ã«ããä½æã、Firebase ãã©ã°ã¤ã³ããã®ä»ã® npm ãã¼ã¹ã®ãã©ã°ã¤ã³ãåæåãã¦、ã¢ããªãæ§ç¯ã§ããããã«ãã¾ã。NativeScript CLI ã使ã£ã¦ã¯ãã¼ã³ããã¢ããªã®ã«ã¼ãã«ç§»åã、tns
run ios
ã¾ã㯠tns run android
ãå®è¡ãã¾ã。ããã«ãã£ã¦ãã©ã°ã¤ã³ããã«ãããã«ã¼ãã³ãéå§ããã¾ã。ä¸ã§ã、Firebase ãã©ã°ã¤ã³ã®ãã¾ãã¾ãªãã¼ãã®ã¤ã³ã¹ãã¼ã«ãå§ã¾ããã¨ã確èªã§ããã¯ãã§ã。ã¤ã³ã¹ãã¼ã« ã¹ã¯ãªãããå®è¡ãããã¨、ãã¾ãã¾ãª Firebase ãµã¼ãã¹ãçµ±åããããã®ã³ã³ãã¼ãã³ããã¤ã³ã¹ãã¼ã«ãããã©ããã®ç¢ºèªã表示ããã¾ã。ããã§ã¯、Messaging ã¨ã½ã¼ã·ã£ã«èªè¨¼ãé¤ããã¹ã¦ãé¸æãã¾ã。ããã§ã®å¤§ããªç¹å¾´ã¯、firebase.nativescript.json ãã¡ã¤ã«ãã¢ããªã®ã«ã¼ãã«ã¤ã³ã¹ãã¼ã«ããããã¨ã§ã。ãã®ãã、ä»å¾ãã©ã°ã¤ã³ã®æ°ãããã¼ããã¤ã³ã¹ãã¼ã«ãããå ´å、ãã®ãã¡ã¤ã«ãç·¨éããã ãã§ãã©ã°ã¤ã³ãåã¤ã³ã¹ãã¼ã«ã§ãã¾ã。
ããã§、tns livesync ios --watch
ã¾ã㯠tns livesync android
--watch
ãå®è¡ã、ã¨ãã¥ã¬ã¼ã¿ã§ã¢ããªãèµ·åãã¦å¤æ´ãç£è¦ããããã¨ã確èªããã¨、ã¢ããªãå®è¡ããã¦æ°ãããã°ã¤ã³ããæºåãã§ãã¦ãããã¨ããããã¾ã。ãã ã、ãã°ã¤ã³ãè¡ãåã«、Firebase ã³ã³ã½ã¼ã«ã® [Authentication] ã¿ãããã¡ã¼ã« / ãã¹ã¯ã¼ãã«ãããã°ã¤ã³ãæå¹ã«ãã¦、Firebase ããã®ã¿ã¤ãã®ãã°ã¤ã³ãå¦çã§ããããã«ããå¿
è¦ãããã¾ã。
ãã®è£ã§ä½ãèµ·ãã£ã¦ãããã確èªããããã«、å°ãã°ããå
é¨ã®ä»çµã¿ãè¦ã¦ã¿ã¾ããã。Firebase ã«ãã°ã¤ã³ããã«ã¯、ã¤ã³ã¹ãã¼ã«ãã Firebase ãµã¼ãã¹ãåæåãã¦ããå¿
è¦ãããã¾ã。app/main.ts
ã«ã¯、ããã¤ãèå³æ·±ãç¹ãããã¾ã。
// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app.module";
import { BackendService } from "./services/backend.service";
import firebase = require("nativescript-plugin-firebase");
firebase.init({
//persist should be set to false as otherwise numbers aren't returned during
livesync
persist: false,
storageBucket: 'gs://giftler-f48c4.appspot.com',
onAuthStateChanged: (data: any) => {
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}
}).then(
function (instance) {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
platformNativeScriptDynamic().bootstrapModule(AppModule);
æåã«、ãã©ã°ã¤ã³ãã firebase ãã¤ã³ãã¼ãã、.init() ãå¼ã³åºãã¾ã。次㫠storageBucket ããããã£ãç·¨éã、Firebase ã³ã³ã½ã¼ã«ã® [Storage] ã¿ãã«è¡¨ç¤ºããã¦ããå¤ãè²¼ãä»ãã¾ã。
ããã§、ã使ãã® Firebase ã¢ã«ã¦ã³ãã«åããã¦ã¢ããªãã«ã¹ã¿ãã¤ãºãã、ã¢ããªã§æ°ããã¦ã¼ã¶ã¼ã®ç»é²ã¨ãã°ã¤ã³ãå¯è½ã«ãªãã¯ãã§ã。å¿
è¦ã«å¿ãã¦、app/login/login.component.ts
ãã¡ã¤ã«ã® user.email 㨠password å¤æ°ãç·¨éãã¦、ããã©ã«ãã®ãã°ã¤ã³èªè¨¼æ
å ±ã user@nativescript.org
ãããèªèº«ã®ãã°ã¤ã³ã¨ãã¹ã¯ã¼ãã«å¤æ´ãããã¨ãã§ãã¾ã。
iOS 㨠Android ã®ãã°ã¤ã³ç»é¢
注: iOS ã§ã¯、Xcode ã·ãã¥ã¬ã¼ã¿ã使ãã¨ããã«ã¢ããªãã¨ãã¥ã¬ã¼ãã§ãã¾ã。ãã ã Android ã§ã¯、ã¢ããªãã¨ãã¥ã¬ã¼ã¿ã«ã¤ã³ã¹ãã¼ã«ããããã«、Google Services ã®æå¹åãªã©、追å ã§ããã¤ãã®æé ãå¿
è¦ã«ãªãå ´åãããã¾ã。
ã³ã¼ãã®æ§é ã¨èªè¨¼
Angular 2 ã®ãã¶ã¤ã³ ãã¿ã¼ã³ã§ã¯、ã³ã¼ããã¢ã¸ã¥ã¼ã«åããå¿
è¦ãããã¾ã。ãã®ãã、以ä¸ã®ã³ã¼ãæ§é ã«å¾ããã®ã¨ãã¾ã。
—login
login.component.ts
login.html
login.module.ts
login.routes.ts
—list …
—list-detail …
—models
gift.model.ts
user.model.ts
index.ts
—services
backend.service.ts
firebase.service.ts
utils.service.ts
index.ts
app.component.ts
app.css
app.module.ts
app.routes.ts
auth-guard.service.ts
main.ts
Firebase ã®èªè¨¼ã Angular 2 ã® auth-guard.service ã¨é£æºããæ¹æ³ã«æ³¨ç®ãã¦ãã ãã。åè¿°ã®ããã«、ã¢ããªã® app/main.ts
㧠Firebase ãåæåããã¾ã。ãã®éã«、onAuthStateChanged
é¢æ°ãå¼ã³åºããã¾ã。
onAuthStateChanged: (data: any) => {
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}
ã¢ããªãèµ·åããéã«、Firebase ããè¿ããããã¼ã¿ãæåååãããã®ãã³ã³ã½ã¼ã«ã§ç¢ºèªãã¦ãã ãã。ãã®ã¦ã¼ã¶ã¼ã« loggedIn
ãã©ã°ãç«ã£ã¦ããå ´å、Firebase ããéãè¿ããã userId ã token
ã¨ãã¦è¨å®ãã¾ã。NativeScript ã¢ããªã±ã¼ã·ã§ã³è¨å®ã¢ã¸ã¥ã¼ã«ã使ã£ã¦、ãã® userId ãä¿åãããã¤、ããããä½æãããã¼ã¿ã¨é¢é£ä»ãã¾ã。ãã®ã¢ã¸ã¥ã¼ã«ã¯、localStorage ã®ãããªæ©è½ãæã¤ã¢ã¸ã¥ã¼ã«ã§ã。ãã®ãã¼ã¯ã³ã¨ãã¼ã¯ã³ã使ãèªè¨¼ãã¹ã㯠app/services/backend.service.ts
ãã¡ã¤ã«ã§ç®¡çããã¦ãã、app/auth-guard.service.ts
ãã¡ã¤ã«ã§å©ç¨ã§ãã¾ã。auth-guard ãã¡ã¤ã«ã¯、ã¢ããªã®ãã°ã¤ã³ããã³ãã°ã¢ã¦ãç¶æ
ãé©åã«ç®¡çããæ¹æ³ãæä¾ãã¦ãã¾ã。
AuthGuard ã¯ã©ã¹ã¯、Angular Router ã¢ã¸ã¥ã¼ã«ã® CanActivate ã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£
ãã¦ãã¾ã。
export class AuthGuard implements CanActivate {
constructor(private router:Router) { }
canActivate() {
if (BackendService.isLoggedIn()) {
return true;
}
else {
this.router.navigate(["/login"]);
return false;
}
}
åºæ¬çã«ã¯、åè¿°ã®ãã°ã¤ã³ ã«ã¼ãã³ã§ãã¼ã¯ã³ãè¨å®ãã、ã㤠BackendService.isLoggedIn é¢æ°ã true ãè¿ãå ´å、ã¢ããªã§ããã©ã«ãã®ã«ã¼ãã§ããã¦ã£ãã·ã¥ãªã¹ãã¸ã®ããã²ã¼ã·ã§ã³ã許å¯ããã¾ã。ããã、ãã以å¤ã®å ´å、ã¦ã¼ã¶ã¼ã¯ãã°ã¤ã³ç»é¢ã«æ»ããã¾ã。
const listRoutes:Routes = [
{ path: "", component:ListComponent, canActivate: [AuthGuard] },
];
ããã§、Firebase ã使ã NativeScript ã¢ããªãåæåã§ãã¾ãã。次ã¯、ã¢ããªã«ãã¼ã¿ãèªã¿è¾¼ã¿、Firebase ã®ãã°ããããªã¢ã«ã¿ã¤ã æ§ãæ´»ç¨ãã¦、ã¢ãããã¼ãããããã¼ã¿ãã¼ã¹ã®å
容ãç£è¦ããæ¹æ³ã«ã¤ãã¦å¦ãã§ããã¾ããã。
ãªã¹ãã®ä½æã¨ããã«ãã§ãã¯
ã¦ã£ãã·ã¥ãªã¹ãã®ãã¼ã¹ã¨ãªã£ã¦ãã app/list/list.html
ãã説æãã¾ã。ããã«ã¯、ããã¹ãé
ç®ã¨ç©ºã®ãªã¹ãã表示ããã¦ããã¯ãã§ã。ã§ã¯、ãµã³ã¿ããã«æ¬²ãããã®ãä¼ãã¦ã¿ã¾ããã。é
ç®ããã¼ã¿ãã¼ã¹ã«éä¿¡ãã、ãªã¢ã«ã¿ã¤ã ã«ãªã¹ãã«è¿½å ããã¾ã。ãããã©ããã£ã¦å®ç¾ãã¦ããããè¦ã¦ã¿ã¾ããã。
app/list/list.component.ts
ã§ã¯、æåã«ã®ããã®ãªã¹ããä¿æããããã®ç£è¦å¯è½ãªãã¸ã§ã¯ããè¨å®ãã¦ãã¾ã。
public gifts$: Observable;
次ã«、ã³ã³ãã¼ãã³ãã®åæåã®éã«、ãã¼ã¿ãã¼ã¹ãããªã¹ããèªã¿è¾¼ã¿ã¾ã。
ngOnInit(){
this.gifts$ = this.firebaseService.getMyWishList();
}
ãããããã®ã¯ firebaseService ãã¡ã¤ã«ã§ã。ãã®é¢æ°ã§ã¯、ãªã¹ãã¼ã追å ã㦠Firebase Database ã® Gifts ã³ã¬ã¯ã·ã§ã³ã®å¤æ´ãç£è¦ããç£è¦å¯è½ãªãã¸ã§ã¯ã rxjs ãè¿ãã¦ãã¾ã。ãã®æ¹æ³ã«æ³¨ç®ãã¦ãã ãã。
getMyWishList():Observable {
return new Observable((observer: any) => {
let path = 'Gifts';
let onValueEvent = (snapshot: any) => {
this.ngZone.run(() => {
let results = this.handleSnapshot(snapshot.value);
console.log(JSON.stringify(results))
observer.next(results);
});
};
firebase.addValueEventListener(onValueEvent, `/${path}`);
}).share();
}
ãã®ã¯ã¨ãªã®çµæã¯、次ã«ç¤ºã handleSnapshot
é¢æ°ã§å¦çããã¾ã。ãã®é¢æ°ã¯、ã¦ã¼ã¶ã¼ããã£ã«ã¿ãªã³ã°ãããã¼ã¿ã _allItems é
åã«è¨å®ãã¦ãã¾ã。
handleSnapshot(data: any) {
//empty array, then refill and filter
this._allItems = [];
if (data) {
for (let id in data) {
let result = (Object).assign({id: id}, data[id]);
if(BackendService.token === result.UID){
this._allItems.push(result);
}
}
this.publishUpdates();
}
return this._allItems;
}
æå¾ã«、publishUpdates ãå¼ã³åºããã¾ã。ãã®é¢æ°ã¯、æ°ããé
ç®ãå
é ã«è¡¨ç¤ºãããããã«、æ¥ä»ã§ãã¼ã¿ã並ã³æ¿ãã¦ãã¾ã。
publishUpdates() {
// here, we sort must emit a *new* value (immutability!)
this._allItems.sort(function(a, b){
if(a.date < b.date) return -1;
if(a.date > b.date) return 1;
return 0;
})
this.items.next([...this._allItems]);
}
ç£è¦å¯è½ãªãã¸ã§ã¯ã $gifts ã«ãã¼ã¿ãè¨å®ãããã¨、è¦ç´ ã®ç·¨éãåé¤ãè¡ããã³ã«ãªã¹ãã¼ãå¼ã°ã、ããã³ãã¨ã³ããé©åã«ã¢ãããã¼ãããã¾ã。getMyWishList ã¡ã½ããå
ã® onValueEvent é¢æ°ã§ ngZone ã使ããã¦ãããã¨ã«æ³¨æãã¦ãã ãã。ããã«ãã£ã¦、éåæã«è¡ããããã¼ã¿ã®ã¢ãããã¼ãã«å¿ã㦠UI ãé©åã«ã¢ãããã¼ãããã¾ã。NativeScript ã¢ããªã® ngZone ã®æ¦è¦ã«ã¤ãã¦ã¯、ãã¡ã ãã覧ãã ãã。
ã¡ãã»ã¼ã¸ã®ãªã¢ã¼ãè¨å®
ãã 1 ã¤ã®åªãã Firebase ãµã¼ãã¹ã«「Remote Config」ãããã¾ã。ããã¯、Firebase ã®ããã¯ã¨ã³ãããã¢ããªãã¢ãããã¼ãã§ããæ©è½ã§ã。Remote Config ã使ãã¨、ã¢ããªã®æ©è½ã®ãªã³、ãªããåãæ¿ããã、UI ãå¤æ´ãããã§ãã¾ã。ããã§ã¯、ãµã³ã¿ããããã¡ãã»ã¼ã¸ãéãæ©è½ã追å ãã¦ã¿ã¾ããã。
app/list/list.html
ã«ã¯、次ã®ã¡ãã»ã¼ã¸ ããã¯ã¹ãããã¾ã。
<Label class="gold card" textWrap="true" [text]="message$ | async"></Label>
ç£è¦å¯è½ãªãã¸ã§ã¯ã message$
ã¯、ãã¼ã¿ãªã¹ãã¨ã»ã¼åãæ¹æ³ã§çµã¿è¾¼ã¾ãã¦ãã¾ãã、ããã§ã¯ã¢ããªãæ°ããåæåããããã³ã«å¤æ´ãé©ç¨ããã¾ã。
ngOnInit(){
this.message$ = this.firebaseService.getMyMessage();
}
ç§å¯ã¯、次ã«ç¤ºããµã¼ãã¹ã¬ã¤ã¤(app/services/firebase.service.ts
)ã«ããã¾ã。
getMyMessage():Observable{
return new Observable((observer:any) => {
firebase.getRemoteConfig({
developerMode: false,
cacheExpirationSeconds: 300,
properties: [{
key: "message",
default:"Happy Holidays!"
}]
}).then(
function (result) {
console.log("Fetched at " + result.lastFetch + (result.throttled ? " (throttled)" : ""));
for (let entry in result.properties)
{
observer.next(result.properties[entry]);
}
}
);
}).share();
}
好ããªã ãæ°ããã¡ãã»ã¼ã¸ãçºè¡å¯è½
注: ã¢ããªããå¿
è¦ã®ãªãé«é »åº¦ã§ Remote Config ã®å¤ãåå¾ããã¨、Remote Config ã®å©ç¨ãå¶éããã¦ãã¾ãå ´åãããã¾ãã®ã§、æ
éã«éçºãã¦ãã ãã。
åçãæ®ã
ãã®ããã¸ã§ã¯ãã®ãããããã¨ããã¯、é¸ãã ãã¬ã¼ã³ãã®åçãæ®ã£ã¦ Firebase Storage ã«æ ¼ç´ã§ããç¹ã§ããã。åè¿°ã®ããã«、ãã®é¨åã«ã¯ Camera ãã©ã°ã¤ã³ã使ãã¾ãã。ããã§ãã¼ãã¦ã§ã¢ã®ç®¡çãå°ã楽ã«ãªãã¾ã。æåã«、app/list-detail/list-detail.component.ts
ã® ngOnInit() ã¡ã½ããã§ãã¼ããã·ã§ã³ ã»ãããåå¾ã、ã¢ããªãã«ã¡ã©ããã¤ã¹ã«ã¢ã¯ã»ã¹ã§ããããã«ãã¾ã。
ngOnInit() {
camera.requestPermissions();
...
}
ã¦ã¼ã¶ã¼ã詳細ç»é¢ã® [Photo] ãã¿ã³ãã¯ãªãã¯ããã¨、ã¤ãã³ã ãã§ã¼ã³ãå§ã¾ãã¾ã。æåã«å¼ã°ããã®ã¯æ¬¡ã®ã³ã¼ãã§ã。
takePhoto() {
let options = {
width:300,
height:300,
keepAspectRatio: true,
saveToGallery: true
};
camera.takePicture(options)
.then(imageAsset => {
imageSource.fromAsset(imageAsset).then(res => {
this.image = res;
//save the source image to a file, then send that file path to firebase
this.saveToFile(this.image);
})
}).catch(function (err) {
console.log("Error -> " + err.message);
});
}
ã«ã¡ã©ã§åçãæ®å½±ãã、ãã®åçã imageAsset ã¨ãã¦ä¿åããã¦ç»é¢ã«è¡¨ç¤ºããã¾ã。ãã®ã¤ã¡ã¼ã¸ã¯ãã¡ã¤ã«ã¨ãã¦ãã¼ã«ã«ã«ä¿åããã¾ã。ãã®éã«、æ¥ä»ã®ã¿ã¤ã ã¹ã¿ã³ãã«å¾ã£ãååãä»ãããã¾ã。ã¾ã、ä»å¾ã®å©ç¨ã«åãã¦、ãã¹ãä¿åããã¾ã。
saveToFile(res){
let imgsrc = res;
this.imagePath =
this.utilsService.documentsPath(`photo-${Date.now()}.png`);
imgsrc.saveToFile(this.imagePath, enums.ImageFormat.png);
}
[Save] ãã¿ã³ãæ¼ãããã¨、ã¤ã¡ã¼ã¸ã¯ãã¼ã«ã«ãã¹çµç±ã§ Firebase ã«éä¿¡ãã、ã¹ãã¬ã¼ã¸ ã¢ã¸ã¥ã¼ã«å
ã«ä¿åããã¾ã。ã¢ããªã«è¿ããã Firebase ã®ãã«ãã¹ã¯、/Gifts
ãã¼ã¿ãã¼ã¹ ã³ã¬ã¯ã·ã§ã³ã«ä¿åããã¾ã。
editGift(id: string){
if(this.image){
//upload the file, then save all
this.firebaseService.uploadFile(this.imagePath).then((uploadedFile: any) =>
{
this.uploadedImageName = uploadedFile.name;
//get downloadURL and store it as a full path;
this.firebaseService.getDownloadUrl(this.uploadedImageName).then((downloadUrl: string) => {
this.firebaseService.editGift(id,this.description,downloadUrl).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
})
}, (error: any) => {
alert('File upload error: ' + error);
});
}
else {
//just edit the description
this.firebaseService.editDescription(id,this.description).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
}
}
ãã®ã¤ãã³ã ãã§ã¼ã³ã¯ä¸è¦è¤éããã§ãã、æçµçã«å®è¡ãããã®ã¯、Firebase ãµã¼ãã¹ ãã¡ã¤ã«ã®ä¸ã®æ°è¡ã§ã。
uploadFile(localPath: string, file?: any): Promise {
let filename = this.utils.getFilename(localPath);
let remotePath = `${filename}`;
return firebase.uploadFile({
remoteFullPath: remotePath,
localFullPath: localPath,
onProgress: function(status) {
console.log("Uploaded fraction: " + status.fractionCompleted);
console.log("Percentage complete: " + status.percentageCompleted);
}
});
}
getDownloadUrl(remoteFilePath: string): Promise {
return firebase.getDownloadUrl({
remoteFullPath: remoteFilePath})
.then(
function (url:string) {
return url;
},
function (errorMessage:any) {
console.log(errorMessage);
});
}
editGift(id:string, description: string, imagepath: string){
this.publishUpdates();
return firebase.update("/Gifts/"+id+"",{
description: description,
imagepath: imagepath})
.then(
function (result:any) {
return 'You have successfully edited this gift!';
},
function (errorMessage:any) {
console.log(errorMessage);
});
}
æçµçãªçµæã§ã¯、ã¦ã£ãã·ã¥ãªã¹ãã«è¡¨ç¤ºããã®ããã®åçã¨èª¬æã®ä¸¡æ¹ããã¾ãåå¾ã§ãã¦ãã¾ã。ããã§ãããµã³ã¿ããã¯、ã«ã¤ãªã¼ã®ã©ã®ã¢ã¤ã©ã¤ãã¼ãè²·ãã°ããã®ãããããªãã¨ããè¨ã訳ã¯ã§ãã¾ãã。å¼·å㪠NativeScript 㨠Angular ãçµã¿åãããã°、æ°å㧠iOS 㨠Android ã®ãã¤ãã£ã ã¢ããªãä½ããã¨ãã§ãã¾ã。ããã« Firebase ã追å ããã°、ã¢ããªã®ã¦ã¼ã¶ã¼、ã¤ã¡ã¼ã¸、ãã¼ã¿ãä¿åããå¼·åãªæ©è½ãå©ç¨ã§ã、ããã«ç«¯æ«éã§ãªã¢ã«ã¿ã¤ã ã«ãã¼ã¿ãã¢ãããã¼ããããã¨ãå¯è½ã«ãªãã¾ã。ãã°ãããã¨æãã¾ããã。ãã®ã¢ããªã¯、次ã®ããã«ãªãã¾ã。
ããã¾ã§、å
å®ããã¦ã£ãã·ã¥ãªã¹ã管çã¢ããªã®ä½æã«åãã¦é 調ã«é²ãã§ãã¾ãã。ããã、ãµã³ã¿ããã«é¡ããã¨ãä¼ããæé«ã®æ¹æ³ã¯ã¾ã 模索ä¸ã¨è¨ããã§ããã。次ã®ã¹ãããã¨ãã¦ã¯、Mailgun ã®ã¡ã¼ã«ã¨ã®çµ±åãããã·ã¥éç¥ã®å©ç¨ãèãããã¾ã。ããã¾ã§ã®é、ãã°ãããã¯ãªã¹ãã¹ä¼æããéãããã ãã。çããã Firebase ãå©ç¨ãã¦ãã¦ã㪠NativeScript ã¢ããªãä½ããããã«ãç¥ããã¾ã。
NativeScript ã«ã¤ãã¦ããã«è©³ããå¦ã³ããæ¹ã¯、http://www.nativescript.org ãã覧ãã ãã。質åãããæ¹ã¯、ãã¡ã ãã NativeScript ã® Slack ãã£ã³ãã«ã«åå ãã¦ãã ãã。
Posted by Khanh LeViet - Developer Relations Team