NativeScript : Facebook SDK
NativeScript plugin, wrapper of native Facebook SDK for Android and iOS.
- Features
- Installation
- Configuration
- NativeScript Core
- NativeScript Angular
- Login Response
- Get Current Access Token
- Basic Analytics
- Deep Linking
- Deferred Deep Linking
- Graph API Example
- Release notes
- FAQ
- Contribute
- Get Help
Features
- [x] Login & Logout
- [x] Share
- [ ] Graph API
- [x] Basic Analytics
- [x] Deep Linking
- [x] Deferred Deep Linking
Installation
tns plugin add nativescript-facebook
Configuration
Android
Update AndroidManifest.xml (app/App_Resources/Android/AndroidManifest.xml) to put provider
under <application>
{facebook_app_id}
is your app id
<provider android:authorities="com.facebook.app.FacebookContentProvider{facebook_app_id}"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
iOS
Update Info.plist file (app/App_Resources/iOS/Info.plist) to contains CFBundleURLTypes
and LSApplicationQueriesSchemes
like below:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
...
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb{facebook_app_id}</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-share-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
</array>
</dict>
</plist>
Make sure you replaced {facebook_app_id} with your Facebook App Id. More info regarding how to obtain a Facebook App Id can be found here.
Usage
NativeScript Core
Initialization
Call init of nativescript-facebook module on application launch.
import * as application from 'application';
import { init } from "nativescript-facebook";
application.on(application.launchEvent, function (args) {
init("{facebook_app_id}");
});
application.start({ moduleName: "login-page" });
Login
Facebook Login Button
Add Facebook login button as simple as adding a Facebook:LoginButton tag in your view. Then you can define login
event handler name. In the example below - onLogin
.
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:Facebook="nativescript-facebook"
loaded="pageLoaded" class="page">
...
<Facebook:LoginButton login="{{ onLogin }}"></Facebook:LoginButton>
...
</Page>
Implement onLogin
event handler in your view-model. It receives an argument from type LoginEventData
. Currently LoginEventData
object has 2 properties: error and loginResponse. loginResponse is an object that consists of 1 property - token that keeps the facebook access token which will be used for further authentications. Ideally we can add some other properties here in the future such as Facebook user id.
import { Observable } from 'data/observable';
import { Facebook:LoginButton } from "nativescript-facebook";
export class LoginViewModel extends Observable {
onLogin(eventData: LoginEventData) {
if (eventData.error) {
alert("Error during login: " + eventData.error.message);
} else {
console.log(eventData.loginResponse.token);
}
}
}
Custom Login Button
Add a button and define a tap
event handler in your login view.
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:Facebook="nativescript-facebook"
loaded="pageLoaded" class="page">
...
<Button tap="{{ login }}" text="Log in (custom)"></Button>
...
</Page>
In the view model implement the tap event handler in this case login
method. It just has to call the login method that comes from the plugin. In the example below the login method from the plugin is imported as fbLogin.
BEST PRACTICE: Import only the methods that you need instead of the entire file. It is crucial when you bundle your app with webpack.
import { Observable } from 'data/observable';
import { login as fbLogin } from "nativescript-facebook";
export class LoginViewModel extends Observable {
login() {
fbLogin((err, fbData) => {
if (err) {
alert("Error during login: " + err.message);
} else {
console.log(fbData.token);
}
});
}
}
Log out
Facebook Logout Button
Add Facebook logout button as simple as adding a Facebook:LoginButton tag in your view. Then you can define logout
event handler name. In the example below - onLogout
.
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:Facebook="nativescript-facebook"
loaded="pageLoaded" class="page">
...
<Facebook:LoginButton logout="{{ onLogout }}"></Facebook:LoginButton>
...
</Page>
Implement onLogout
event handler in your view-model.
import { Observable } from 'data/observable';
export class HomeViewModel extends Observable {
onLogout() {
console.log("logged out");
}
}
Custom Logout Button
Add a button and define a tap
event handler in your view. In this case - logout
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:Facebook="nativescript-facebook"
loaded="pageLoaded" class="page">
...
<Button tap="{{ logout }}" text="Log out (custom)"></Button>
...
</Page>
In the view model implement the tap event handler in this case logout
method. It just has to call the logout method that comes from the plugin. In the example below the logout method from the plugin is imported as fbLogout.
import { Observable } from 'data/observable';
import { logout as fbLogout } from "nativescript-facebook";
export class LoginViewModel extends Observable {
logout() {
fbLogout(() => {
console.log("logged out");
});
}
}
Share
Create Sharing Content
For sharing, you have to create sharing content first. Currently the available content types are:
- createShareLinksContent(link: string, quote?: string, addition?: ShareAdditionContent) available for every condition
-
createSharePhotosContent(images: ImageSource[] | string[], userGenerated: boolean, addition?: ShareAdditionContent) available for ShareButton and
showShareDialog
( only when user have native Facebook installed, version 7.0 or higher ) -
createShareMessageGenericTemplateContent(contentConfig: MessageGenericTemplateContent) available for SendButton and
showMessageDialog
-
createShareMessageMediaTemplateContent(contentConfig: MessageMediaTemplateContent) available for SendButton and
showMessageDialog
You can see more information from https://developers.facebook.com/docs/sharing/overview#content and https://developers.facebook.com/docs/sharing/messenger#share-types
import {
LoginEventData,
getCurrentAccessToken,
createShareLinksContent,
createSharePhotosContent,
createShareMessageGenericTemplateContent,
MessageGenericTemplateImageAspectRatio,
showShareDialog,
showMessageDialog,
canShareDialogShow,
canMessageDialogShow
} from 'nativescript-facebook';
const linkContent = createShareLinksContent('https://www.nativescript.org',
'Create Native iOS and Android Apps With JavaScript',
{
hashtag: '#Nativescript'
});
// you can also pass in imageUrls as string[] in here
const logoImage = fromResource('logo');
const photosContent = createSharePhotosContent([logoImage], false, {
hashtag: '#Nativescript'
});
const GenericTemplate = createShareMessageGenericTemplateContent({
element: {
title: 'Nativescript',
subtitle: 'Create Native iOS and Android Apps With JavaScript',
imageUrl: 'https://d2odgkulk9w7if.cloudfront.net/images/default-source/home/how-it-works-min.png',
button: {
title: 'Check Doc',
url: 'https://docs.nativescript.org'
},
defaultAction: {
title: 'Go HomePage',
url: 'https://www.nativescript.org'
}
},
// it seems android have to provide a pageId, otherwise the MessageDialog just wont show
pageID: 'testestsett',
imageAspectRatio: MessageGenericTemplateImageAspectRatio.Horizontal
});
Facebook Share Button
<Facebook:ShareButton content="{{ linkContent }}"></Facebook:ShareButton>
Facebook Send Button
If the Messenger app is not installed, the Send button will be hidden. Be sure that your app layout is appropriate when this button is hidden.
<Facebook:SendButton content="{{ genericContent }}"></Facebook:SendButton>
Show Share Dialog Programmatically
Note The share dialog will try fallback to browse page sharing if user doesn't have Facebook installed (only for linkContent)
showShareDialog(this.linkContent);
showMessageDialog(this.linkContent);
showShareDialog(this.linkContent, (error:Error, result:ShareCallbackResult) => {
if(!error){
console.log(result.android); // com.facebook.share.Sharer.Result
console.log(result.ios); // (NSDictionary * ) The results from the sharer. This may be nil or empty.
}
});
Hide Custom Button If Can't share
You can use this method to check if the content can be shared and hide the custom button if can't
public canShowPhotosShareDialog = canShareDialogShow(this.photosContent);
public canShowGenericMessageDialog = canMessageDialogShow(this.genericContent);
<Button tap="{{ onShareDialogPhotos }}" text="Open Share dialog (photos)" visibility="{{ canShowPhotosShareDialog ? 'visible' : 'collapsed' }}"></Button>
<Button tap="{{ onSendGenericDialog }}" text="Share Message Generic Template" visibility="{{ canShowGenericMessageDialog ? 'visible' : 'collapsed' }}"></Button>
NativeScript Angular
Initialization
Call init of nativescript-facebook module on application launch.
...
import * as application from 'application';
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptFacebookModule } from "nativescript-facebook/angular";
let nsFacebook = require('nativescript-facebook');
application.on(application.launchEvent, function (args) {
nsFacebook.init("{facebook_app_id}");
});
...
@NgModule({
...
imports: [
AppRoutingModule,
NativeScriptModule,
NativeScriptFacebookModule,
...
],
...
})
...
Login
Facebook Login Button
Add Facebook login button as simple as adding a Facebook:LoginButton tag in your component html file. Then you can define login
event handler name. In the example below - onLogin
. Bare in mind the $event argument.
pages/login/login.component.html
<StackLayout>
<FacebookLoginButton (login)="onLogin($event)"></FacebookLoginButton>
</StackLayout>
Implement onLogin
event handler in your component. It receives an argument from type LoginEventData
. Currently LoginEventData
object has 2 properties: error and loginResponse. loginResponse is an object that consists of 1 property - token that keeps the facebook access token which will be used for further authentications. Ideally we can add some other properties here in the future such as Facebook user id.
pages/login/login.component.ts
import { Component } from "@angular/core";
import * as Facebook from "nativescript-facebook";
@Component({
selector: "login",
templateUrl: "login.component.html",
})
export class LoginComponent {
onLogin(eventData: Facebook.LoginEventData) {
if (eventData.error) {
alert("Error during login: " + eventData.error);
} else {
console.log(eventData.loginResponse.token);
}
}
}
Custom Login Button
Add a button and define a tap
event handler in your login component html.
pages/login/login.component.html
<StackLayout>
<Button text="Login Button (custom)" (tap)="login()"></Button>
</StackLayout>
In the component implement the tap event handler in this case login
method. It just has to call the login method that comes from the plugin.
pages/login/login.component.ts
import { Component } from "@angular/core";
import * as Facebook from "nativescript-facebook";
@Component({
selector: "login",
templateUrl: "login.component.html",
})
export class LoginComponent {
login() {
Facebook.login((error, fbData) => {
if (error) {
alert("Error during login: " + error.message);
} else {
console.log(fbData.token);
}
});
}
}
Logout
Facebook Logout Button
Add Facebook logout button as simple as adding a Facebook:LoginButton tag in your component html file. Then you can define logout
event handler name. In the example below - onLogout
. Bare in mind the $event argument.
pages/home/home.component.html
<StackLayout>
<FacebookLoginButton (logout)="onLogout($event)"></FacebookLoginButton>
</StackLayout>
Implement onLogout
event handler.
import { Component } from "@angular/core";
import * as Facebook from "nativescript-facebook";
@Component({
selector: "home",
templateUrl: "home.component.html",
})
export class HomeComponent {
onLogout(eventData: Facebook.LoginEventData) {
if (eventData.error) {
alert("Error during login: " + eventData.error);
} else {
console.log("logged out");
}
}
}
Custom Logout Button
Add a button and define a tap
event handler in your view. In this case - logout
pages/home/home.component.html
<StackLayout>
<Button text="Log out (custom)" (tap)="logout()"></Button>
</StackLayout>
In the component implement the tap event handler in this case logout
method. It just has to call the logout method that comes from the plugin. In the example below the logout method from the plugin is imported as fbLogout.
import { Component } from "@angular/core";
import { logout as fbLogout } from "nativescript-facebook";
@Component({
selector: "home",
templateUrl: "home.component.html",
})
export class AppComponent {
logout() {
fbLogout(() => {
console.log("logged out");
});
}
}
Share
Create Sharing Content
Read Nativescript chapter for this
Facebook Share Button
<FacebookShareButton [content] = "linkContent"></FacebookShareButton>
Facebook Send Button
If the Messenger app is not installed, the Send button will be hidden. Be sure that your app layout is appropriate when this button is hidden.
<FacebookSendButton [content] = "genericContent"></FacebookSendButton>
Show Share Dialog Programmatically
Note The share dialog will try fallback to browse page sharing if user doesn't have Facebook installed (only for linkContent)
showShareDialog(this.linkContent);
showMessageDialog(this.linkContent);
showShareDialog(this.linkContent, (error:Error, result:ShareCallbackResult) => {
if(!error){
console.log(result.android); // com.facebook.share.Sharer.Result
console.log(result.ios); // (NSDictionary * ) The results from the sharer. This may be nil or empty.
}
});
Hide Custom Button If Can't share
You can use this method to check if the content can be shared and hide the custom button if can't
public canShowPhotosShareDialog = canShareDialogShow(this.photosContent);
public canShowGenericMessageDialog = canMessageDialogShow(this.genericContent);
<Button (tap) = "onShareDialogPhotos()" text = "Open Share dialog (photos)" *ngIf = "canShowPhotosShareDialog"></Button>
<Button (tap) = "onSendGenericDialog()" text = "Share Message Generic Template" *ngIf = "canShowGenericMessageDialog"></Button>
Login Response
The callback that have to be provided to Facebook.login method receives 2 arguments: error and login response object. Login response object has the following structure:
Property | Description |
---|---|
token | access token which will be used for further authentications |
Get Current Access Token
The plugin allows to get the current access token, if any, via getCurrentAccessToken() method.
Basic Analytics
The plugin allows to log analytics events. At the initialization of the application you need to init analytics:
application.on(application.launchEvent, function (args) {
nsFacebook.init("{facebook_app_id}");
nsFacebook.initAnalytics();
});
Events logging:
nsFacebook.logEvent('Lead');
Logging event with parameters:
const value = 5;
const parameters = [{
key: 'value',
value: value.toString(),
}];
nsFacebook.logEvent(FundsAdded, parameters);
Events logging:
nsFacebook.logEvent('Lead');
Logging event with parameters:
const value = 5;
const parameters = [{
key: 'value',
value: value.toString(),
}];
nsFacebook.logEvent(FundsAdded, parameters);
Deep Linking
The plugin supports Deep Linking. You must register the callback before the application is started:
In your main.ts file call this before the app is initialized. Note: This must be done outside of the application.on(), and only done once;
nsFacebook.registerDeepLinkCallback((application, url, options) => {
//Use the url;
});
Deferred Deep Linking
The plugin has basic support for Deferred Deep Linking. At the initialization of the application you need to init deep linking:
Note: The initDeepLinking() is only required if you aren't using init().
application.on(application.launchEvent, function (args) {
nsFacebook.initDeepLinking("{facebook_app_id}");
nsFacebook.fetchDeferredAppLink().then(deepLink => {
}).catch(error => {
})
});
The fetchDeferredAppLink() returns a promise with a value of DeepLink defined below.
{
target: string;
ref: string;
promoCode: string;
}
Graph API Example
Once the Facebook access token is retrieved you can execute Graph API requests. In the example below after successful login, the access token is stored in application settings. And then on the home view it is retrieved and 2 Graph API calls are executed.
- Get Facebook id of the logged in user
- Get the logged in user avatar (this is kind of workaround of this NativeScript issue. #2176)
export class HomeComponent {
accessToken: string = appSettings.getString("access_token");
userId: string;
username: string;
avatarUrl: string;
constructor(private ref: ChangeDetectorRef, private navigationService: NavigationService) {
// Get logged in user's info
http.getJSON(config.FACEBOOK_GRAPH_API_URL + "/me?access_token=" + this.accessToken).then((res) => {
this.username = res.name;
this.userId = res.id;
// Get logged in user's avatar
// ref: https://github.com/NativeScript/NativeScript/issues/2176
http.getJSON(config.FACEBOOK_GRAPH_API_URL + "/" + this.userId + "/picture?type=large&redirect=false&access_token=" + this.accessToken).then((res) => {
this.avatarUrl = res.data.url;
this.ref.detectChanges();
}, function (err) {
alert("Error getting user info: " + err);
});
}, function (err) {
alert("Error getting user info: " + err);
});
}
This sample is part of the demo apps and can be observed here for Nativescript Code and here for NativeScript + Angular.
Release notes
Check out release notes here
FAQ
Check out our FAQ section here.
Contribute
We love PRs! Check out the contributing guidelines. If you want to contribute, but you are not sure where to start - look for issues labeled help wanted
.
Get Help
Please, use github issues strictly for reporting bugs or requesting features. For general questions and support, check out Stack Overflow or ask our experts in NativeScript community Slack channel.