UNITY - FB SDK : screenshot not getting posted on profile - c#

I am trying to integrate FB SDK in my UNITY GAME for ios and ANDROID.
FB SHARE AND INVITE are working fine which are in "FBSCENE" scene.
But in "GAME" scene i want to take a SCREENSHOT after game is finished and post it on users FB WALL.
I read "Take and publish a screenshot" under EXAMPLE at https://developers.facebook.com/docs/unity/reference/current/FB.API
and my code is this
public void screenShareFB()
{
callFB ();
}
void callFB () {
if (!FB.IsLoggedIn) {
FB.Login("email,publish_actions", LoginCallback);
}
else {
StartCoroutine(TakeScreenshot());
}
}
void LoginCallback(FBResult result) {
FbDebug.Log("LoginCallback");
if (FB.IsLoggedIn) {
StartCoroutine(TakeScreenshot());
}
}
/*
void OnLoggedIn() {
FbDebug.Log("Logged in. ID: " + FB.UserId);
}*/
private IEnumerator TakeScreenshot() {
yield return new WaitForEndOfFrame();
var width = Screen.width;
var height = Screen.height;
var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
// Read screen contents into the texture
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
tex.Apply();
byte[] screenshot = tex.EncodeToPNG();
var wwwForm = new WWWForm();
wwwForm.AddBinaryData("image", screenshot, "InteractiveConsole.png");
wwwForm.AddField("message", "herp derp. I did a thing! Did I do this right?");
FB.API("me/photos", Facebook.HttpMethod.POST, Callback, wwwForm);
Debug.Log("done");
}
private Texture2D lastResponseTexture;
private string lastResponse = "";
public string ApiQuery = "";
void Callback(FBResult result)
{
lastResponseTexture = null;
if (result.Error != null)
lastResponse = "Error Response: " + result.Error;
else if (!ApiQuery.Contains("/picture"))
lastResponse = "Success Response: " + result.Text;
else
{
lastResponseTexture = result.Texture;
lastResponse = "Success Response: ";
}
}
screenShareFB() being called when user tap on SHARE SCREENSHOT button.
NOTE:
I have called FB.Init(with a call back method); in Start() of the script.
I am using C# script.
Is this because my app is not live on facebook ?
I have configured it on facebook already.
I was testing on PC.
Please tell me if anything is wrong with the code or any thing i am missing.

The problem was permissions.
the "publish_actions" permission was not review by facebook.
thus the screenshot was not getting published.
but 1 thing when try to fill details for fb to review my app and allow me to access publish_actions for my user.
They require us to add a "platform" under "SETTINGS" in "BASIC".
Now i am using UNITY.
which is not mentioned as a platform there.
What should i do.?

Related

(unity) I want to download image from URL for each button of my app but it shows just last button one

All buttons and text can show well but the image just shows only last button. when I try to click to check user.value.imageUrl, it's correct. I don't know what is wrong, please help me. I think IEnumerator has something I am missing.
my code is:
void CreateButton()
{
FirebaseRestClent.GetUsers(users =>
{
foreach (var user in users)
{
StartCoroutine(downloadImage(user.Value.imageUrl));
var clone = Instantiate(button,m_transform) as GameObject;
var modelBtn = clone.GetComponent<Button>();
imageToUpdate = modelBtn.GetComponent<Image>();
title = modelBtn.GetComponentInChildren<Text>();
title.text = user.Value.saveFile;
//Debug.Log($"{user.Value.modelUrl} {user.Value.saveFile} {user.Value.imageUrl}");
modelBtn.onClick.AddListener(delegate {
Debug.Log(user.Value.modelUrl + user.Value.saveFile + user.Value.imageUrl);
dlManager.PlayModel(user.Value.modelUrl, user.Value.saveFile,user.Value.musicUrl,false);
//dlManager.PlayModel(user.Value.modelUrl, user.Value.saveFile, false);
});
}
});
}
IEnumerator downloadImage(string url)
{
UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
DownloadHandler handle = www.downloadHandler;
//Send Request and wait
yield return www.SendWebRequest();
if (www.isHttpError || www.isNetworkError)
{
UnityEngine.Debug.Log("Error while Receiving: " + www.error);
}
else
{
UnityEngine.Debug.Log("Success");
//Load Image
Texture2D texture2d = DownloadHandlerTexture.GetContent(www);
Sprite sprite = null;
sprite = Sprite.Create(texture2d, new Rect(0, 0, 326, texture2d.height), Vector2.zero);
imageToUpdate.sprite = sprite;
}
}
you always overwrite the same imageToUpdate field reference in your loop so most probably all results get written into the Image component of the very last user.
You should rather simply pass the image reference on to the routine
void CreateButton()
{
FirebaseRestClent.GetUsers(users =>
{
foreach (var user in users)
{
var clone = Instantiate(button, m_transform) as GameObject;
var modelBtn = clone.GetComponent<Button>();
var image = modelBtn.GetComponent<Image>();
// instead of storing it in a class field rather
// pass the image reference into the Coroutine
StartCoroutine(downloadImage(user.Value.imageUrl, image));
title = modelBtn.GetComponentInChildren<Text>(true);
title.text = user.Value.saveFile;
modelBtn.onClick.AddListener(()=>
{
Debug.Log(user.Value.modelUrl + user.Value.saveFile + user.Value.imageUrl);
dlManager.PlayModel(user.Value.modelUrl, user.Value.saveFile, user.Value.musicUrl, false);
});
}
});
}
IEnumerator downloadImage(string url, Image targetImage)
{
using(www = UnityWebRequestTexture.GetTexture(url))
{
//Send Request and wait
yield return www.SendWebRequest();
if (www.isHttpError || www.isNetworkError)
{
Debug.Log("Error while Receiving: " + www.error);
}
else
{
Debug.Log("Success");
//Load Image
var texture2d = DownloadHandlerTexture.GetContent(www);
var sprite = Sprite.Create(texture2d, new Rect(0, 0, 326, texture2d.height), Vector2.zero);
targetImage.sprite = sprite;
}
}
}

C# InstaSharper: Unable to upload photo: Unexpected character encountered while parsing value: S. Path '', line 0, position 0

I'm using this library as a NuGet package(InstaSharper) for instagram bot program: https://github.com/a-legotin/InstaSharper
And in the InsertImage(); function, which is meant for uploading a photo to instagram page, while parsing, the program runs into a problem and console reuturns:
Loged in! Unable to upload photo: Unexpected character encountered
while parsing value: S. Path '', line 0, position 0.
I tried using different paths and image types, but the same thing happens.
What could be the problem and how to fix it?
These are main functions:
static void Main(string[] args)
{
user = new UserSessionData();
user.UserName = username;
user.Password = password;
Login();
Console.Read();
}
public static async void Login()
{
api = InstaApiBuilder.CreateBuilder().SetUser(user).UseLogger(new DebugLogger(LogLevel.Exceptions)).SetRequestDelay(RequestDelay.FromSeconds(1, 3)).Build();
var loginRequest = await api.LoginAsync();
if (loginRequest.Succeeded)
{
Console.WriteLine("Loged in!");
InsertImage(#"C:\test.jpg", "Testing");
}
else Console.WriteLine("Unable to log in: " + loginRequest.Info.Message);
}
public static async void InsertImage(string _path, string _caption)
{
var mediaImage = new InstaImage
{
Height = 1080,
Width = 1080,
URI = new Uri(Path.GetFullPath(_path), UriKind.Absolute).LocalPath
};
var result = await api.UploadPhotoAsync(mediaImage, _caption);
if (result.Succeeded == true) Console.WriteLine($"Media created: {result.Value.Pk}, {result.Value.Caption}");
else Console.WriteLine($"Unable to upload photo: {result.Info.Message}");
}
It seems InstaSharper Nuget Package is not updated, I've downloaded it from Github and use it in my project, it worked for me
Hope this helps

Unity VR-Application - Can't import files

Right now I am developing a VR-application for my Oculus Go. In this Application i need to import files like images, video, audio during runtime. My Problem right now is that the import of these files do work in unity, but doesn't work on my oculus go.
In my project i use a file browser prefab from the asset store. this file browser can be opened during the runtime of my application, but when i want to open a file for example an image, it only turns grey. the image should be loaded to a RawImage-Object.
Filebrowser during runtime
RawImage-Object turns grey
Unity-does work
I dont' understand why this is happening. I have to say I'm new to unity and would appreciate any kind of help! Here is the code of the image-load-script.
public class FileManager : MonoBehaviour {
public RawImage image;
public void OpenExplorer()
{
SimpleFileBrowser.FileBrowser.SetFilters(true, ".txt", ".jpg", ".png", ".mp4");
SimpleFileBrowser.FileBrowser.ShowLoadDialog( (path) => { UpdateImage(path); }, null, false, null, "Select File", "Select");
}
void UpdateImage(string pfad)
{
if (pfad != null)
{
WWW www = new WWW(pfad);
image.texture = www.texture;
var texWidth = www.texture.width;
var texHeight = www.texture.height;
if (texWidth > texHeight)
{
GetComponent<RectTransform>().sizeDelta = new Vector2(1920/2, 1080/2);
}
if (texWidth < texHeight)
{
GetComponent<RectTransform>().sizeDelta = new Vector2(1080/2, 1920/2);
}
}
}
My Problem right now is that the import of these files do work in
unity, but doesn't work on my oculus go.
Most buggy code work on the Editor but you will discover the issue with a code when you deploy or build the project.
Your problem is in the UpdateImage function:
WWW www = new WWW(pfad);
image.texture = www.texture;
...
You are supposed to yield or wait for the WWW request to finish before loading the image. The request asynchronous. Without yielding it, you would be trying to accessing incomplete image leading to a corrupted image or gray image depending on the platform.
Make the following changes:
1.Change the UpdateImage to a coroutine function (void to IEnumerator) then yield the WWW request with yield return www; before accessing the texture from it:
2.Call the UpdateImage function as a coroutine function with StartCoroutine:
Replace:
SimpleFileBrowser.FileBrowser.ShowLoadDialog( (path) => { UpdateImage(path); }, null, false, null, "Select File", "Select");
with
SimpleFileBrowser.FileBrowser.ShowLoadDialog( (path) => { StartCoroutine(UpdateImage(path)); }, null, false, null, "Select File", "Select");
3.Check for error before accessing the Texture. When the WWW request has finished, there could be an error. Check that before using the returned texture or item.
The final code should look like this:
public RawImage image;
public void OpenExplorer()
{
SimpleFileBrowser.FileBrowser.SetFilters(true, ".txt", ".jpg", ".png", ".mp4");
SimpleFileBrowser.FileBrowser.ShowLoadDialog((path) => { StartCoroutine(UpdateImage(path)); }, null, false, null, "Select File", "Select");
}
IEnumerator UpdateImage(string pfad)
{
if (pfad != null)
{
WWW www = new WWW(pfad);
//WAIT UNTIL REQUEST IS DONE!
yield return www;
//Check for error
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
}
else
{
image.texture = www.texture;
var texWidth = www.texture.width;
var texHeight = www.texture.height;
if (texWidth > texHeight)
{
GetComponent<RectTransform>().sizeDelta = new Vector2(1920 / 2, 1080 / 2);
}
if (texWidth < texHeight)
{
GetComponent<RectTransform>().sizeDelta = new Vector2(1080 / 2, 1920 / 2);
}
}
}
}

error uploading file to parse from unity3D

I am using Parse for a game that I'm developing.
Everything is ok until I try to uplad a file, no matters his extension I always get this Error : "get_version can only be called from main thread"
URL=http://www.hostingpics.net/viewer.php?id=764075parseError.png
and this is my script :
byte[] data = System.Text.Encoding.UTF8.GetBytes("Working at Parse is great!");
ParseFile file = new ParseFile("resume.txt", data);
Task saveTask = file.SaveAsync();
var player = new ParseObject ("FilesLibrary");
player ["Number"] = 155;
player ["Files"] = file;
saveTask = player.SaveAsync();
I have tried to place this script in different places but I always get the same problem.
You need to make sure the file is uploaded to Parse first, before you try to save it to the db object.
The Parse Unity documentation is not very good as it doesn't fit Unity's threading model. I would suggest using co-routines to do all your Parse calls.
I posted this on Unity Answers as well, but you get the idea..
// The file first needs to be uploaded to Parse before it can be saved to the object in the database
ParseFile _playerFile;
public void CreatePlayer()
{
StartCoroutine (UploadPlayerFile ((response) => {
if(response == 1)
StartCoroutine(CreateProjectAsync());
else
Debug.LogError("The file could not be uploaded");
}));
}
IEnumerator UploadPlayerFile(Action <int> callback)
{
var fileBytes = System.IO.File.ReadAllBytes (#"C:\myfile.jpg");
_playerFile = new ParseFile ("file.jpg", fileBytes, "image/jpeg");
var saveTask = _playerFile.SaveAsync ();
while (!saveTask.IsCompleted)
yield return null;
if (saveTask.IsFaulted) {
Debug.LogError ("An error occurred while uploading the player file : " + saveTask.Exception.Message);
callback (-1);
} else {
callback (1);
}
}
IEnumerator CreateProjectAsync()
{
ParseObject player = new ParseObject ("Player");
player ["Number"] = 111;
player ["Files"] = _playerFile;
var saveTask = player.SaveAsync ();
while (!saveTask.IsCompleted)
yield return null;
if (saveTask.IsFaulted) {
Debug.LogError ("An error occurred while creating the player object : " + saveTask.Exception.Message);
} else {
Debug.Log ("Player created successfully");
}
}
I guess you need force your Parse queries to execute on Main Thread. you can achieve this by
public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action> ();
Add your query Method in this Queue. Like
ExecuteOnMainThread.Enqueue (() => {
StartCoroutine (SaveData (ID, playerName)); });
In your SaveData() Coroutine you need to execute your Parse queries.
and finally:
void Update()
{
while (ExecuteOnMainThread != null && ExecuteOnMainThread.Count > 0)
{
Action currentAction = ExecuteOnMainThread.Dequeue();
if (currentAction != null)
{
currentAction.Invoke ();
}
}
}
Weird, the same script works fine with unity 4.6 but not 5.1 !

Remote-notifications working when app is in foreground, but not in the background

I have a Xamarin.iOS app working that can successfully receive an APNS push notification when the app is running in the foreground. However, I also want to be able to handle the push notification when the app is running in the background, or not running at all.
This page on Xamarin appears to say that you can indeed do this:
http://developer.xamarin.com/guides/ios/application_fundamentals/backgrounding/part_3_ios_backgrounding_techniques/updating_an_application_in_the_background/
I am using the Remote Notifications strategy outlined above. So I implemented exactly what it said, including changing the info.plist to have Remote Notifications as a background operation. However, I do not get any calls either in the DidFinishedLaunching, or ReceivedRemoteNotification callbacks when the app is running in the background. When the app is running in the foreground, everything works just fine. Needless to say, it's super frustrating.
Has anyone else run into this problem?
Any help is much appreciated!
Here is the code I am using to register for the remote notifications:
public static void NotifyAppStart()
{
if (GetRemoteWipePreference())
{
if (Utils.CheckOsVersion(8, 0))
{
// iOS 8 version
UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else
{
// Only works on iOS 7 and earlier
UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}
}
}
And here is the PushSharp code I am using to send the push notifications on the server side:
push.RegisterAppleService(new ApplePushChannelSettings(appleCert, GetApplePwd() ));
push.QueueNotification(new AppleNotification()
.ForDeviceToken( token ).WithContentAvailable(1)
.WithCustomItem(msg, device.device_local_guid) );
Side note: There are a few other questions on stack overflow about this general area, but none of them actually are about this issue.
if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))
{
var settings = UIUserNotificationSettings.GetSettingsForTypes (UIUserNotificationType.Sound |
UIUserNotificationType.Alert | UIUserNotificationType.Badge, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings (settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications ();
}
else
{
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(UIRemoteNotificationType.Badge |
UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert);
}
also you need this
public override void RegisteredForRemoteNotifications (UIApplication application, NSData deviceToken)
{
var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");
var strFormat = new NSString("%#");
var dt = new NSString(MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr(new MonoTouch.ObjCRuntime.Class("NSString").Handle, new MonoTouch.ObjCRuntime.Selector("stringWithFormat:").Handle, strFormat.Handle, deviceToken.Handle));
var newDeviceToken = dt.ToString().Replace("<", "").Replace(">", "").Replace(" ", "");
string sql;
if (string.IsNullOrEmpty(oldDeviceToken) || !deviceToken.Equals(newDeviceToken))
{
do someting
}
if (oldDeviceToken == newDeviceToken)
{
do someting
} else
{
do something
}
NSUserDefaults.StandardUserDefaults.SetString(newDeviceToken, "PushDeviceToken");
Console.WriteLine("Device Token: " + newDeviceToken);
}
if your program is foreground you can use like this
void processNotification(NSDictionary options, bool fromFinishedLaunching)
{
if (null != options && options.ContainsKey(new NSString("aps")))
{
NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
string alert = string.Empty;
string sound = string.Empty;
int badge = -1;
if (aps.ContainsKey(new NSString("alert")))
alert = (aps[new NSString("alert")] as NSString).ToString();
if (aps.ContainsKey(new NSString("sound")))
sound = (aps[new NSString("sound")] as NSString).ToString();
if (aps.ContainsKey(new NSString("badge")))
{
string badgeStr = (aps[new NSString("badge")] as NSObject).ToString();
int.TryParse(badgeStr, out badge);
}
if (!fromFinishedLaunching)
{
if (badge >= 0)
UIApplication.SharedApplication.ApplicationIconBadgeNumber = badge;
if (sound == "xx.caf")
{
UIAlertView avAlert = new UIAlertView ("Dogrular App", alert, null, "Tamam", null);
avAlert.Show ();
}
if (sound == "yyy.caf")
{
UIAlertView avAlert = new UIAlertView ("Dogrular App", alert, null, "Tamam", null);
avAlert.Show ();
NSUrl request = new NSUrl("https://xxx.com");
UIApplication.SharedApplication.OpenUrl(request);
}
}
}
}
Is your json file consists of content-available boolean key is "false"?
Example:
{
"to": "GCM Registration ID",
"priority":"high",
"data": {
"notificationId":123,
"title":"Spot you!",
"message": "<font color=\"red\"><b>Test RED Bold text maybe ?</b></font><br/>Normal second line.<br/><br/>",
"photoUrl": "http://babymetal.net/wp-content/uploads/2015/07/ladybeard-e1427784688234.jpg",
"badge": 1
},
"dry_run" : false,
"time_to_live" : 4,
"content_available" : false
}
Above json return should be calling your method
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)

Categories

Resources