这是为Facebook SDK支持WP8和Unity 5的请求。 我是一名想要在许多平台上制作游戏的开发者,能够发布到Windows Phone 8商店是我议程的重要组成部分。
此平台的支持是否计划在短期内发布?如果是这样,你什么时候发布它呢?
此外,是否有即将发布的Unity SDK可用于Unity 5?我已经设法让当前的版本工作,但由于它还没有完全支持,我不知道什么会起作用,什么不起作用。
非常感谢有关这些问题的任何信息!
答案 0 :(得分:4)
更新:我遇到了这个视频,解释了" AndContinue"方法在Windows 10中消失,所以我们可以使用一种方法; Windows 8 / 8.1 api上已存在的异步方法。请查看https://youtu.be/aFVAP3fNJVo?t=23m34s
我和你在同一个地方但设法让它运转起来。如果我有时间,可能会写一篇关于我的经历的博客。
以下是直接调用WebAuthenticationBroker的一些主要代码: -
static bool isTryingToRegister { get; set; }
private static string _FbToken;
public static string response;
static bool isLoggedIn { get; set; }
static private string AppID { get { return "000000000000000000"; } }
static private Uri callback { get; set; }
static private string permissions { get { return "public_profile, user_friends, email, publish_actions, user_photos"; } }
public static System.Action<object> AuthSuccessCallback;
public static System.Action<object> AuthFailedCallback;
public static string fbToken
{
get
{
return _FbToken;
}
}
static Uri loginUrl
{
get
{
return new Uri(String.Format("https://www.facebook.com/v2.0/dialog/oauth/?client_id={0}&display=popup&response_type=token&redirect_uri={1}&scope={2}",
AppID,
callback,
permissions));
}
}
public static IEnumerator _Run_ConnectWithFacebook()
{
yield return new WaitForEndOfFrame();
#if UNITY_EDITOR
UnityDebugAuthentication();
#endif
#if NETFX_CORE
WindowsStoreAuthenticate();
#endif
}
#if NETFX_CORE
static void WindowsStoreAuthenticate()
{
#if UNITY_WP_8_1 && !UNITY_EDITOR
AuthSuccessCallback = _Run_ConnectWithFacebook_SuccessResponse;
AuthFailedCallback = _Run_ConnectWithFacebook_FailedResponse;
UnityEngine.WSA.Application.InvokeOnUIThread(
() =>
{
callback = WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
WebAuthenticationBroker.AuthenticateAndContinue(loginUrl, callback, null, WebAuthenticationOptions.None);
}, true);
#endif
#if UNITY_METRO_8_1 && !UNITY_EDITOR
AuthSuccessCallback = _Run_ConnectWithFacebook_SuccessResponse;
AuthFailedCallback = _Run_ConnectWithFacebook_FailedResponse;
UnityEngine.WSA.Application.InvokeOnUIThread(
async () =>
{
callback = WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
WebAuthenticationResult authResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, loginUrl);
}, true);
#endif
}
#endif
请注意我如何使用Windows Phone的WebAuthenticationBroker.AuthenticateAndContinue和Windows 8的WebAuthenticationBroker.AuthenticateAsync。这对于各自的平台来说是必需的。您可能想要了解一下WebAuthenticationBroker,这是一个适用于WP8和WSA的Microsoft类(我猜你的目标是WSA,我也是): -
您还需要在Unity中构建一个c#项目,这样您就可以实现它的第2部分,其中包括将令牌详细信息返回给应用程序时的处理。这是我的App.xaml.cs代码示例,其灵感来自https://msdn.microsoft.com/en-us/library/dn631755.aspx:-
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using UnityPlayer;
using Template.Common;
using Windows.Security.Authentication.Web;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
namespace Template
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
private WinRTBridge.WinRTBridge _bridge;
private AppCallbacks appCallbacks;
#if UNITY_WP_8_1
public ContinuationManager continuationManager { get; private set; }
#endif
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
appCallbacks = new AppCallbacks();
appCallbacks.RenderingStarted += RemoveSplashScreen;
#if UNITY_WP_8_1
this.Suspending += OnSuspending;
continuationManager = new ContinuationManager();
#endif
}
/// <summary>
/// Invoked when application is launched through protocol.
/// Read more - http://msdn.microsoft.com/library/windows/apps/br224742
/// </summary>
/// <param name="args"></param>
protected override void OnActivated(IActivatedEventArgs args)
{
#if UNITY_WP_8_1
var continuationEventArgs = args as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
ContinueWebAuthentication(args as WebAuthenticationBrokerContinuationEventArgs);
return;
//}
}
#endif
string appArgs = "";
Windows.ApplicationModel.Activation.SplashScreen splashScreen = null;
switch (args.Kind)
{
case ActivationKind.Protocol:
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
splashScreen = eventArgs.SplashScreen;
appArgs += string.Format("Uri={0}", eventArgs.Uri.AbsoluteUri);
break;
}
InitializeUnity(appArgs, splashScreen);
}
#if UNITY_WP_8_1
public void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
{
WebAuthenticationResult result = args.WebAuthenticationResult;
if (result.ResponseStatus == WebAuthenticationStatus.Success)
{
string responseData = result.ResponseData.Substring(result.ResponseData.IndexOf("access_token"));
String[] keyValPairs = responseData.Split('&');
string access_token = null;
string expires_in = null;
for (int i = 0; i < keyValPairs.Length; i++)
{
String[] splits = keyValPairs[i].Split('=');
switch (splits[0])
{
case "access_token":
access_token = splits[1]; //you may want to store access_token for further use. Look at Scenario5 (Account Management).
break;
case "expires_in":
expires_in = splits[1];
break;
}
}
AppCallbacks.Instance.UnityActivate(Window.Current.CoreWindow, CoreWindowActivationState.CodeActivated);
AppCallbacks.Instance.InvokeOnAppThread(() =>
{
// back to Unity
//function to call or variable that accepts the access token
}, false);
//OutputToken(result.ResponseData.ToString());
//await GetFacebookUserNameAsync(result.ResponseData.ToString());
}
else if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
{
//OutputToken("HTTP Error returned by AuthenticateAsync() : " + result.ResponseErrorDetail.ToString());
AppCallbacks.Instance.InvokeOnAppThread(() =>
{
// back to Unity
//function to call indicating something went wrong
}, false);
}
else if(result.ResponseStatus == WebAuthenticationStatus.UserCancel)
{
//OutputToken("Error returned by AuthenticateAsync() : " + result.ResponseStatus.ToString());
AppCallbacks.Instance.InvokeOnAppThread(() =>
{
// back to Unity
//function to call indicating something went wrong
}, false);
}
}
#endif
/// <summary>
/// Invoked when application is launched via file
/// Read more - http://msdn.microsoft.com/library/windows/apps/br224742
/// </summary>
/// <param name="args"></param>
protected override void OnFileActivated(FileActivatedEventArgs args)
{
string appArgs = "";
Windows.ApplicationModel.Activation.SplashScreen splashScreen = null;
splashScreen = args.SplashScreen;
appArgs += "File=";
bool firstFileAdded = false;
foreach (var file in args.Files)
{
if (firstFileAdded) appArgs += ";";
appArgs += file.Path;
firstFileAdded = true;
}
InitializeUnity(appArgs, splashScreen);
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used when the application is launched to open a specific file, to display
/// search results, and so forth.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
InitializeUnity(args.Arguments, args.SplashScreen);
}
private void InitializeUnity(string args, Windows.ApplicationModel.Activation.SplashScreen splashScreen)
{
#if UNITY_WP_8_1
ApplicationView.GetForCurrentView().SuppressSystemOverlays = true;
#pragma warning disable 4014
StatusBar.GetForCurrentView().HideAsync();
#pragma warning restore 4014
#endif
appCallbacks.SetAppArguments(args);
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null && !appCallbacks.IsInitialized())
{
var mainPage = new MainPage(splashScreen);
Window.Current.Content = mainPage;
Window.Current.Activate();
// Setup scripting bridge
_bridge = new WinRTBridge.WinRTBridge();
appCallbacks.SetBridge(_bridge);
#if !UNITY_WP_8_1
appCallbacks.SetKeyboardTriggerControl(mainPage);
#endif
appCallbacks.SetSwapChainPanel(mainPage.GetSwapChainPanel());
appCallbacks.SetCoreWindowEvents(Window.Current.CoreWindow);
appCallbacks.InitializeD3DXAML();
}
Window.Current.Activate();
#if UNITY_WP_8_1
SetupLocationService();
#endif
}
private void RemoveSplashScreen()
{
// This will fail if you change main window class
// Make sure to adjust accordingly if you do something like this
MainPage page = (MainPage)Window.Current.Content;
page.RemoveSplashScreen();
}
#if UNITY_WP_8_1
// This is the default setup to show location consent message box to the user
// You can customize it to your needs, but do not remove it completely if your application
// uses location services, as it is a requirement in Windows Store certification process
private async void SetupLocationService()
{
if (!appCallbacks.IsLocationCapabilitySet())
{
return;
}
const string settingName = "LocationContent";
bool userGaveConsent = false;
object consent;
var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
var userWasAskedBefore = settings.Values.TryGetValue(settingName, out consent);
if (!userWasAskedBefore)
{
var messageDialog = new Windows.UI.Popups.MessageDialog("Can this application use your location?", "Location services");
var acceptCommand = new Windows.UI.Popups.UICommand("Yes");
var declineCommand = new Windows.UI.Popups.UICommand("No");
messageDialog.Commands.Add(acceptCommand);
messageDialog.Commands.Add(declineCommand);
userGaveConsent = (await messageDialog.ShowAsync()) == acceptCommand;
settings.Values.Add(settingName, userGaveConsent);
}
else
{
userGaveConsent = (bool)consent;
}
if (userGaveConsent)
{ // Must be called from UI thread
appCallbacks.SetupGeolocator();
}
}
#endif
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await SuspensionManager.SaveAsync();
deferral.Complete();
}
}
}
您还需要ContinuationManager.cs类和SuspensionManager.cs类,但主要用于WP8.1 Universal。这不是W8.1所必需的,所以你应该确保使用#defines将它们保存在自己的上下文中
如果您愿意,可以直接在Facebook应用程序上调用,而不是调用WebAuthenticationBroker,但我不知道所有细节。您可以在Facebook的网站developers.facebook.com/docs/facebook-login/login-for-windows-phone上阅读。如果用户没有安装该方法,则不建议使用该方法。
Long(匆忙)故事简短,调用WebAuthenticationBroker,处理OnActivated事件中的continuation事件以捕获WebAuthenticationBrokerContinuationEventArgs对象,并使用您认为合适的数据。如果要调用统一端的任何代码,请务必使用以下内容。请注意,您可以直接从App.xaml.cs访问c#代码: -
AppCallbacks.Instance.InvokeOnAppThread(() =>
{
// back to Unity
//your code here
}, false);
另请注意,这主要是为了获取访问令牌。一旦我们有了这个,我们可以直接向facebook发送基本的WWW调用并从中获取数据。数据将以JSON格式返回(ps这是一种非常棒的干净格式!)您可以使用.NET json库将其序列化为类。我使用json2csharp.com将任何示例输出转换为我刚刚解析到json库中的类。