coton_chen1
coton_chen1
  • 发布:2018-10-08 08:28
  • 更新:2018-10-08 09:18
  • 阅读:4358

facebook登录插件(ios版)

分类:5+ SDK

贴出源码回报社区!

下面贴出关键代码,稍后完善更多细节步骤。个人ios开发经验不多,如果有更好的集成方式,请大家分享!

前提:

  1. 能在Xcode中成功运行官方给出的离线打包演示应用 HBuilder-Hello (iOS平台5+SDK集成)
  2. 注册了facebook开发者平台,并完成了官方ios集成步骤,参考:https://developers.facebook.com/docs/facebook-login/ios?sdk=fbsdk&locale=zh_CN

源代码目录结构

1. js层代码调用插件login.js

    loginWithFacebook: function()  
    {  
        Common.showLoading();  

        setTimeout(function(){  
            if(App.timeout)  
            {  
                Common.hideLoading();  
                mui.toast(Common.messages.LOGIN_TIMEOUT,{ duration:'short', type:'div' });  
            }  
        }, 30000);  

        if(Common.debug)  
        {  
            setTimeout(function(){  
                App.facebookAuthSuccessCallBack('{"picture":{"data":{"height":50,"is_silhouette":false,"url":"https:\/\/platform-lookaside.fbsbx.com\/platform\/profilepic\/?asid=1799672767573170&height=50&width=50&ext=1529946538&hash=AeT-c8Gg8kljhvAC","width":50}},"name":"Nick Name","id":"1791872767573170","email":"last.first@gmail.com","permissions":{"data":[{"permission":"user_birthday","status":"granted"},{"permission":"user_hometown","status":"granted"},{"permission":"user_location","status":"granted"},{"permission":"user_posts","status":"granted"},{"permission":"user_gender","status":"granted"},{"permission":"user_link","status":"granted"},{"permission":"user_age_range","status":"granted"},{"permission":"email","status":"granted"},{"permission":"public_profile","status":"granted"}]},"age_range":{"min":21},"link":"https:\/\/www.facebook.com\/app_scoped_user_id\/YXNpZADpBWEZAmSmJjc01BLXJNTGt4UDd0RlZAicXpYVG5HbTV3YUl2T29uNNNNMWpGWndhVEVieTI4S18zcDVuUjczUHRmUHgwYm8xUkwtU1lHWENuRW9vUnE2clFtalVLaWs4SldxT05iWUxZAUlZA2bjRHemhE\/","gender":"male","birthday":"01\/01\/1990","location":{"id":"106324044973002","name":"Shanghai, China"}}');  
                //App.facebookAuthCancelCallBack();  
                //App.facebookAuthErrorCallBack("auth fail!");  
            }, 2000);  

        }else  
        {  
            //plus.facebookplug.logOut();  
            plus.facebookplug.logIn(App.facebookAuthSuccessCallBack, App.facebookAuthErrorCallBack);  
        }  

    },  

    // 这个回调函数会在 cn.shaketowin.app.SDK_WebApp.java 原生类中调用, 参考类中的excuteJSCode()方法  
    facebookAuthSuccessCallBack: function(data)  
    {  
        App.timeout = false;  

        if(data != null)  
        {  
            //alert("===facebookAuthSuccessCallBack(), data: " + JSON.stringify(data));  
            // data example: {"picture":{"data":{"height":50,"is_silhouette":false,"url":"https:\/\/platform-lookaside.fbsbx.com\/platform\/profilepic\/?asid=1791872767573170&height=50&width=50&ext=1529946538&hash=AeT-c8Gg8kljhvAC","width":50}},"name":"Nick Name","id":"1987872767573170","email":"last.first@gmail.com","permissions":{"data":[{"permission":"user_birthday","status":"granted"},{"permission":"user_hometown","status":"granted"},{"permission":"user_location","status":"granted"},{"permission":"user_posts","status":"granted"},{"permission":"user_gender","status":"granted"},{"permission":"user_link","status":"granted"},{"permission":"user_age_range","status":"granted"},{"permission":"email","status":"granted"},{"permission":"public_profile","status":"granted"}]},"age_range":{"min":21},"link":"https:\/\/www.facebook.com\/app_scoped_user_id\/YXNpZADpBWEZAmSmJjc01BLXJNTGt4UD09RlZAicXpYVG5HbTV3YUl2T29uVTNNMWpGWndhVEVieTI4S18zcDVuUjczUHRmUHgwYm8xUkwtU1lHWENuRW9vUnE2clFtalVLaWs4SldxT05iWUxZAUlZA2bjRHemhE\/","gender":"male","birthday":"01\/01\/1990","location":{"id":"116324086073002","name":"Shanghai, China"}}  
            try{  
                var facebookUser = JSON.parse(data);  
                facebookUser.unionid = facebookUser.id;  
                mui.toast(Common.messages.LOGIN_SUCCESS,{ duration:'short', type:'div' });  
                App.checkUserIsExist(facebookUser, "facebook");  
            }catch(err)  
            {  
                Common.hideLoading();  
                mui.toast(Common.messages.LOGIN_FAIL,{ duration:'long', type:'div' });  
                Common.log("====login.js, facebookAuthSuccessCallBack(), decode facebook user JSON string fail!");  
            }  
        }else  
        {  
            Common.hideLoading();  
            App.facebookAuthErrorCallBack();  
        }  
    },  

    // 这个回调函数会在 cn.shaketowin.app.SDK_WebApp.java 原生类中调用, 参考类中的excuteJSCode()方法  
    facebookAuthCancelCallBack: function()  
    {  
        App.timeout = false;  
        Common.hideLoading();  

        mui.toast(Common.messages.LOGIN_CANCEL,{ duration:'long', type:'div' });  
    },  

    // 这个回调函数会在 cn.shaketowin.app.SDK_WebApp.java 原生类中调用, 参考类中的excuteJSCode()方法  
    facebookAuthErrorCallBack: function(error)  
    {  
        App.timeout = false;  
        Common.hideLoading();  

        mui.toast(Common.messages.LOGIN_FAIL,{ duration:'long', type:'div' });  
    },

2. js层代码插件facebookplug.js

document.addEventListener( "plusready",  function()  
{  
    var facebookplug =  
    {  
        logIn : function (successCallback, errorCallback )  
        {  
            var success = typeof successCallback !== 'function' ? null : function(args)  
            {  
                successCallback(args);  
            },  
            fail = typeof errorCallback !== 'function' ? null : function(code)  
            {  
                errorCallback(code);  
            };  
            callbackID = window.plus.bridge.callbackId(success, fail);  

            return window.plus.bridge.exec('facebookloginplugin', "LogIn",  [callbackID]);  
        },  
        logOut : function ()  
        {  
            window.plus.bridge.exec('facebookloginplugin', "LogOut", []);  
        },  
    };  

    window.plus.facebookplug = facebookplug;  
}, true );

3. 原生层FacebookLoginPlugin.h

//  
//  FacebookLoginPlugin.h  
//  
//  

#include "PGPlugin.h"  
#include "PGMethod.h"  
#import <Foundation/Foundation.h>  

@interface FacebookLoginPlugin : PGPlugin  

- (void)LogIn:(PGMethod*)command;  
- (void)LogOut:(PGMethod*)command;  
@end

4. 原生层FacebookLoginPlugin.m

//  
//  FacebookLoginPlugin.m  
//  

#import "FacebookLoginPlugin.h"  
#import "PDRCoreAppFrame.h"  
#import "H5WEEngineExport.h"  
#import "PDRToolSystemEx.h"  
// 扩展插件中需要引入需要的系统库  
#import <LocalAuthentication/LocalAuthentication.h>  
#import <FBSDKCoreKit/FBSDKCoreKit.h>  
#import <FBSDKLoginKit/FBSDKLoginKit.h>  

@implementation FacebookLoginPlugin  

#pragma mark 这个方法在使用WebApp方式集成时触发,WebView集成方式不触发  

/*  
 * WebApp启动时触发  
 * 需要在PandoraApi.bundle/feature.plist/注册插件里添加autostart值为true,global项的值设置为true  
 */  
- (void) onAppStarted:(NSDictionary*)options{  

    NSLog(@"5+ WebApp启动时触发");  
    // 可以在这个方法里向Core注册扩展插件的JS  

}  

// 监听基座事件事件  
// 应用退出时触发  
- (void) onAppTerminate{  
    //  
    NSLog(@"APPDelegate applicationWillTerminate 事件触发时触发");  
}  

// 应用进入后台时触发  
- (void) onAppEnterBackground{  
    //  
    NSLog(@"APPDelegate applicationDidEnterBackground 事件触发时触发");  
}  

// 应用进入前天时触发  
- (void) onAppEnterForeground{  
    //  
    NSLog(@"APPDelegate applicationWillEnterForeground 事件触发时触发");  
}  

#pragma mark 以下为插件方法,由JS触发, WebView集成和WebApp集成都可以触发  

// 登录  
- (void)LogIn:(PGMethod*)commands  
{  
    if ( commands ) {  
        // CallBackid 异步方法的回调id,H5+ 会根据回调ID通知JS层运行结果成功或者失败  
        NSString* cbId = [commands.arguments objectAtIndex:0];  

        if ([FBSDKAccessToken currentAccessToken]) {  
            //NSLog(@"==========LogIn(), already have token");  

            [self GetUserInfo:cbId];  

        }else{  

            /*  
             * Facebook会对i应用访问的字段进行控制(https://developers.facebook.com/apps/193845774573048/review-status/)  
             * 应用审核说明:https://developers.facebook.com/docs/apps/review/#app-review  
             * 默认不需要审核的有:@"public_profile", @"email"  
             * 如下权限系统提交应用审核才可以访问: @"public_profile", @"email", @"user_age_range", @"user_birthday", @"user_gender", @"user_hometown", @"user_link", @"user_location"  
             * 如果需要访问相对应的字段,将字段放入的代码 [login logInWithReadPermissions:@[@"public_profile", @"email"] 参数即可  
             */  

            FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];  
            login.loginBehavior = FBSDKLoginBehaviorWeb;  
            [login logInWithReadPermissions:@[@"public_profile", @"email"]  
                                    handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)  
            {  
                if (error) {  
                    [self CallWebAppJSFun: cbId status: @"ERROR" message: error.localizedDescription];  
                } else if (result.isCancelled) {  
                    [self CallWebAppJSFun: cbId status: @"ERROR" message: @"cancel"];  
                } else {  
                    // If you ask for multiple permissions at once, you  
                    // should check if specific permissions missing  
                    //NSLog(@"========Permission  2: %@",result.grantedPermissions);  

                    [self GetUserInfo:cbId];  
                }  

            }];  
        }  
    }  
}  

// 退出登录  
- (void)LogOut:(PGMethod *)command  
{  
    FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];  
    [loginManager logOut];  
    // or  
    //[FBSDKAccessToken setCurrentAccessToken:nil];  
}  

// 获取用户信息  
- (void)GetUserInfo:(NSString *) cbId  
{  
    /*  
     * Facebook会对i应用访问的字段进行控制(https://developers.facebook.com/apps/193845774573048/review-status/)  
     * 应用审核说明:https://developers.facebook.com/docs/apps/review/#app-review  
     * 对应默认不需要审核的字段@"public_profile", @"email"的是@"id,name,first_name,last_name,email,picture.type(large)“  
     * 对应提交应用审核才可以访问字段有 @"cover,picture.type(large),id,name,first_name,last_name,gender,birthday,email,location,hometown,about,photos,age_range,link"  
     * 如果需要访问相对应的字段,将字段放入的代码 parameters:[NSDictionary dictionaryWithObject:@"cover,..." forKey:@"fields"] 参数即可  
     */  

    [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:[NSDictionary dictionaryWithObject:@"id,name,first_name,last_name,email,picture" forKey:@"fields"]]  
     startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {  

         if (!error) {  

             //NSLog(@"==========GetUserInfo(), username: %@", [result valueForKey:@"name"]);  
//             NSString *userID = [[FBSDKAccessToken currentAccessToken] userID];  
//             NSString *userName = [result valueForKey:@"name"];  
//             NSString *email =  [result valueForKey:@"email"];  
//             NSString *userImageURL = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large", [[FBSDKAccessToken currentAccessToken] userID]];  

             NSData *jsonData = [NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingPrettyPrinted error:nil];  

             NSString *userInfo =  [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];  

             //NSLog(@"==========GetUserInfo(), userInfo: %@", userInfo);  

             [self CallWebAppJSFun: cbId status: @"OK" message: userInfo];  
         }  
         else{  
             [self CallWebAppJSFun: cbId status: @"ERROR" message: error.localizedDescription];  
         }  
     }];  

}  

// 回调通知JS层  
- (void)CallWebAppJSFun:(NSString *) cbId  
                status:(NSString *) st  
                message:(NSString *) msg  
{  
    // 运行Native代码结果和预期相同,调用回调通知JS层运行成功并返回结果  
    // PDRCommandStatusOK 表示触发JS层成功回调方法  
    // PDRCommandStatusError 表示触发JS层错误回调方法  

    // 如果方法需要持续触发页面回调,可以通过修改 PDRPluginResult 对象的keepCallback 属性值来表示当前是否可重复回调, true 表示可以重复回调   false 表示不可重复回调  默认值为false  

    PDRPluginResult * pResult = nil;  

    if([st isEqualToString: @"OK"])  
    {  
        pResult = [PDRPluginResult resultWithStatus:PDRCommandStatusOK messageAsString: msg];  
    }else  
    {  
        // 如果Native代码运行结果和预期不同,需要通过回调通知JS层出现错误,并返回错误提示  
        pResult = [PDRPluginResult resultWithStatus:PDRCommandStatusError messageAsString:msg];  

    }  

    // 通知JS层Native层运行结果  
    [self toCallback:cbId withReslut:[pResult toJSONString]];  

}  

// 调用指纹解锁  
- (void)AuthenticateUser:(PGMethod*)command  
{  
    if (nil == command) {  
        return;  
    }  
    BOOL isSupport = false;  
    NSString* pcbid = [command.arguments objectAtIndex:0];  
    NSError* error = nil;  
    NSString* LocalReason = @"HBuilder指纹验证";  

    // Touch ID 是IOS 8 以后支持的功能  
    if ([PTDeviceOSInfo systemVersion] >= PTSystemVersion8Series) {  
        LAContext* context = [[LAContext alloc] init];  
        if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {  
            isSupport = true;  
            [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:LocalReason reply:^(BOOL success, NSError * _Nullable error) {  
                PDRPluginResult * pResult = nil;  

                if (success) {  

                    pResult = [PDRPluginResult resultWithStatus: PDRCommandStatusOK messageAsDictionary:@{@"state":@(0), @"message":@"成功"}];  
                }  
                else{  
                    NSDictionary* pStringError = nil;  
                    switch (error.code) {  
                        case LAErrorSystemCancel:  
                        {  
                            pStringError = @{@"state":@(-1), @"message":@"系统取消授权(例如其他APP切入)"};  
                            break;  
                        }  
                        case LAErrorUserCancel:  
                        {  
                            pStringError = @{@"state":@(-2), @"message":@"用户取消Touch ID授权"};  
                            break;  
                        }  
                        case LAErrorUserFallback:  
                        {  
                            pStringError  = @{@"state":@(-3), @"message":@"用户选择输入密码"};  
                            break;  
                        }  
                        case LAErrorTouchIDNotAvailable:{  
                            pStringError  = @{@"state":@(-4), @"message":@"设备Touch ID不可用"};  
                            break;  
                        }  
                        case LAErrorTouchIDLockout:{  
                            pStringError  = @{@"state":@(-5), @"message":@"Touch ID被锁"};  
                            break;  
                        }  
                        case LAErrorAppCancel:{  
                            pStringError  = @{@"state":@(-6), @"message":@"软件被挂起取消授权"};  
                            break;  
                        }  
                        default:  
                        {  
                            pStringError  = @{@"state":@(-7), @"message":@"其他错误"};  
                            break;  
                        }  
                    }  
                    pResult = [PDRPluginResult resultWithStatus:PDRCommandStatusError messageAsDictionary:pStringError];  

                }  

                [self toCallback:pcbid withReslut:[pResult toJSONString]];  
            }];  
        }  
        else{  
            NSDictionary* pStringError = nil;  
            switch (error.code) {  
                case LAErrorTouchIDNotEnrolled:  
                {  
                    pStringError  = @{@"state":@(-11), @"message":@"设备Touch ID不可用"};  
                    break;  
                }  
                case LAErrorPasscodeNotSet:  
                {  
                    pStringError  = @{@"state":@(-12), @"message":@"用户未录入Touch ID"};  
                    break;  
                }  

                default:  
                    break;  
            }  
        }  
    }  

    if (!isSupport) {  
        PDRPluginResult* pResult = [PDRPluginResult resultWithStatus:PDRCommandStatusError messageAsString:@"Device Not Support"];  
        [self toCallback:pcbid withReslut:[pResult toJSONString]];  
    }  
}  

@end

5. 原生层AppDelegate.m(在原有函数上新增一行FB的代码,这里仅贴出需要修改的函数的代码)

//  
//  AppDelegate.m  
//  

#import "AppDelegate.h"  
#import "PDRCore.h"  
#import "PDRCommonString.h"  
#import "ViewController.h"  
#import "PDRCoreApp.h"  
#import "DCADManager.h"  
#import "PDRCoreAppManager.h"  
#import <FBSDKCoreKit/FBSDKCoreKit.h>  

// 示例默认带开屏广告,如果不需要广告,可注释下面一行  
#define dcSplashAd  

@interface AppDelegate () <DCADManagerDelgate, PDRCoreDelegate>  
@property (strong, nonatomic) ViewController *h5ViewContoller;  
@end  

@implementation AppDelegate  

@synthesize window = _window;  
#pragma mark -  
#pragma mark app lifecycle  
/*  
 * @Summary:程序启动时收到push消息  
 */  
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
{  

    BOOL ret = [PDRCore initEngineWihtOptions:launchOptions  
                                  withRunMode:PDRCoreRunModeNormal withDelegate:self];  

    DCADManager *adManager = [DCADManager adManager];  
    UIViewController* adViewController = [adManager getADViewController];  
    adManager.delegate = self;  
    UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];  
    self.window = window;  

    ViewController *viewController = [[ViewController alloc] init];  
    self.h5ViewContoller = viewController;  

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];  
    self.rootViewController = navigationController;  
    navigationController.navigationBarHidden = YES;  
    if ( adViewController ) {  
        [navigationController pushViewController:adViewController animated:NO];  
    } else {  
        [self startMainApp];  
        self.h5ViewContoller.showLoadingView = YES;  
    }  
    self.window.rootViewController = navigationController;  
    [self.window makeKeyAndVisible];  

    [[FBSDKApplicationDelegate sharedInstance] application:application  
                             didFinishLaunchingWithOptions:launchOptions];  

    return ret;  
}  

#pragma mark -  
#pragma mark URL  

- (BOOL)application:(UIApplication *)application  
            openURL:(NSURL *)url  
  sourceApplication:(NSString *)sourceApplication  
         annotation:(id)annotation  
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{  
    //NSLog(@"==========here(), url: %@", url);  
    [self application:application handleOpenURL:url];  

    [[FBSDKApplicationDelegate sharedInstance] application:application  
                                                                  openURL:url  
                                            sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]  
                                           annotation:options[UIApplicationOpenURLOptionsAnnotationKey]  
                    ];  

    return YES;  
}

6. Supporting Files/Info.plist文件

3 关注 分享
DCloud_UNI_GSQ 9***@qq.com 蒋馨莹

要回复文章请先登录注册

coton_chen1

coton_chen1 (作者)

facebook登录插件(android版): http://ask.dcloud.net.cn/article/13428
2018-10-08 09:18