开发者

Difficulty on sharing image on Facebook + asynchronization

I am preparing an application that when user selects a photo from gallery & clicks on share button from Application Bar, it must be shared on Facebook wall. I taken One canvas (tempcanvas), added image on it & i have to share that image.

My MainPage.xaml contains..

//When user clicks on share button of Application bar.
private void ApplicationBarShareButton_Click(object sender, EventArgs e)
{            
    NavigationService.Navigate(new Uri("/LoginPage.xaml", UriKind.Relative));
    postPhotoToFacebook();
}

//Share photo on Facebook by using FBPhotoPost.cs methods
public void postPhotoToFacebook()
{
   FBPhotoPost objFBPhotoPost = new FBPhotoPost(); ;
   objFBPhotoPost.PostStatus += new FBPhotoPost.PostStatusEventHandler(objFBPhotoPost_PostStatus);
   objFBPhotoPost.ResetBoundaryString();
   objFBPhotoPost.AccessToken = App.AccessToken;
   objFBPhotoPost.PhotoToPost = objFBPhotoPost.GetBitmapImageFromUIElement(tempCanvas);
   objFBPhotoPost.PostPhoto();
   MessageBox.Show("Photo Posted");
}

void objFBPhotoPost_PostStatus(object sender, FBPhotoPost.PostStatusEventArgs e)
{
   //throw new NotImplementedException();
}

My LoginPage.xaml contains a webbrowser which is used to display login page & authentication.

public LoginPage()
{
    InitializeComponent();             
}

private void wbLogin_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    string strLoweredAddress = e.Uri.OriginalString.ToLower();
    if (strLoweredAddress.StartsWith("http://www.facebook.com/connect/login_success.html?code="))
    {
        txtStatus.Text = "Trying to retrieve access token";
        wbLogin.Navigate(FBUris.GetTokenLoadUri(e.Uri.OriginalString.Substring(56)));
        return;
    }
    string strTest = wbLogin.SaveToString();
    if (strTest.Contains("access_token"))
    {
        int nPos = strTest.IndexOf("access_token");
        string strPart = strTest.Substring(nPos + 13);
        nPos = strPart.IndexOf("</PRE>");
        strPart = strPart.Substring(0, nPos);
        //REMOVE EXPIRES IF FOUND!
        nPos = strPart.IndexOf("&amp;expires=");
        if (nPos != -1)
        {
            strPart = strPart.Substring(0, nPos);
        }
        App.AccessToken = strPart;


        //automaticall leave the page after login success.   
        NavigationService.GoBack();                                

        return;
    }
}

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    wbLogin.Navigate(FBUris.GetLoginUri());
}                      

FBUris.cs contains...

public static class FBUris
{
    #region AppID
    private static string m_strAppID = "   "; //APP ID
    #endregion
    #region AppSecret - only needed because of the fragment bug
    private static string m_strAppSecret = "";  //APP secret.
    #endregion
    //the correct url - but not working due to the WebBrowser fragment bug
    //private static string m_strLoginURL = "https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri=http://www.facebook.com/connect/login_success.html&type=user_agent&display=touch&scope=publish_stream,user_hometown";
    private static string m_strLoginURL = "https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri=http://www.facebook.com/connect/login_success.html&display=touch&scope=publish_stream,user_hometown";
    private static string m_strGetAccessTokenURL = "https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri=http://www.facebook.com/connect/login_success.html&client_secret={1}&code={2}";
    private static string m_strQueryUserURL = "https://graph.facebook.com/me?fields=id,name,gender,link,hometown,picture&locale=en_US&access_token={0}";
    private static string m_strLoadFriendsURL = "https://graph.facebook.com/me/friends?access_token={0}";
    private static string m_strPostMessageURL = "https://graph.facebook.com/me/feed";

    public static Uri GetLoadFriendsUri(string strAccressToken)
    {
        return (new Uri(string.Format(m_strLoadFriendsURL, strAccressToken), UriKind.Absolute));
    }

    public static Uri GetPostMessageUri()
    {
        return (new Uri(m_strPostMessageURL, UriKind.Absolute));
    }
    public static Uri GetQueryUserUri(string strAccressToken)
    {
        return (new Uri(string.Format(m_strQueryUserURL, strAccressToken), UriKind.Absolute));
    }
    public static Uri GetLoginUri()
    {
        return (new Uri(string.Format(m_strLoginURL, m_strAppID), UriKind.Absolute));
    }

    public static Uri GetTokenL开发者_JAVA百科oadUri(string strCode)
    {
        return (new Uri(string.Format(m_strGetAccessTokenURL, m_strAppID, m_strAppSecret, strCode), UriKind.Absolute));
    }
}

FBPhotoPost.cs contains..

public class FBPhotoPost
{
     #region class setup 

    //local property variables

    private string ms_boundary = string.Empty;
    private string ms_accesstoken = string.Empty;
    private BitmapImage mimg_phototopost;
    private string ms_caption = "WP7 Upload Photo";      

    // some multipart constants we will use in the strings we create
    private const string Prefix = "--";
    private const string NewLine = "\r\n"; 

    public FBPhotoPost() { } 

    public BitmapImage PhotoToPost
    {
        get {return mimg_phototopost;}
        set {mimg_phototopost = value;}
    }


    public string PhotoCaption
    {
        get { return ms_caption; }
        set { ms_caption = value; }
    }


    public String BoundaryString
    {
        get
        {
            if (ms_boundary == string.Empty)
            { ResetBoundaryString(); }
            return ms_boundary;
        }
    }


    public void ResetBoundaryString()
    {
        ms_boundary = "----------------------------"+ DateTime.Now.Ticks.ToString("x");
    }


    public String AccessToken
    {
        get{return ms_accesstoken;}
        set{ ms_accesstoken = value;}
    }

    #endregion



    #region Post Data Stuff      

    //builds a byte array with the image in it and passes it to PostPhotoHTTPWebRequest
    //which sends the data via a POST to facebook
    public void PostPhoto()
    {
        if ((mimg_phototopost != null) && (ms_accesstoken != String.Empty))
        PostPhotoHTTPWebRequest(BuildPostData());
    }


    //Uses the PhotoToPost and BoundaryString to build a byte array we can use as the data in the POST message
    private byte[] BuildPostData()
    {
        // Build up the post message header
        var sb = new StringBuilder();
        //accepts a message parameter which will be the caption to go with the photo
        sb.Append(Prefix).Append(BoundaryString).Append(NewLine);
        sb.Append("Content-Disposition: form-data; name=\"message\"");
        sb.Append(NewLine);
        sb.Append(NewLine);
        sb.Append(PhotoCaption);
        sb.Append(NewLine); 

        //data for the image
        string filename = @"FacebookUpload.jpg";
        string contenttype = @"image/jpeg"; 

        sb.Append(Prefix).Append(BoundaryString).Append(NewLine);
        sb.Append("Content-Disposition: form-data; filename=\"").Append(filename).Append("\"").Append(NewLine);
        sb.Append("Content-Type: ").Append(contenttype).Append(NewLine).Append(NewLine);
        byte[] ba_Header = Encoding.UTF8.GetBytes(sb.ToString());
        byte[] ba_photo = ImageToByteArray(PhotoToPost);
        byte[] ba_footer = Encoding.UTF8.GetBytes(String.Concat(NewLine, Prefix, BoundaryString, Prefix, NewLine));


        // Combine all the byte arrays into one - this is the data we will post

        byte[] postData = new byte[ba_Header.Length + ba_photo.Length + ba_footer.Length];
        Buffer.BlockCopy(ba_Header, 0, postData, 0, ba_Header.Length);
        Buffer.BlockCopy(ba_photo, 0, postData, ba_Header.Length, ba_photo.Length);
        Buffer.BlockCopy(ba_footer, 0, postData, ba_Header.Length + ba_photo.Length, ba_footer.Length);



        //Set the lastposteddata variable to we can show it
        ms_lastposteddata = ByteArrayToString(postData);

        //return the data as a byte array
        return postData;
    }


    //Converts the raw post data so you can display it for testing, etc...
    private string ByteArrayToString(byte[] bytes)
    {
        System.Text.Encoding enc = System.Text.Encoding.UTF8;
        string PostString = enc.GetString(bytes, 0, bytes.Length);
        return PostString;
    } 

    private string ms_lastposteddata = "No Data Posted Yet";

    public string LastPostedData
    {
        get { return ms_lastposteddata; }
    }

    #endregion

    //Posts the data to Facebook - can only post to me/photos (no access to users wall)
    #region HTTPWebRequest 

    private void PostPhotoHTTPWebRequest(byte[] postData)
    {
        try
        {
            //Fire up an HttpWebRequest and pass in the facebook url for posting as well as the AccessToken
            //The AccessToken has to be in the URL - it didn't work just passing it as part of the POST data

            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(string.Format("https://graph.facebook.com/me/photos?access_token={0}", App.AccessToken));
            httpWebRequest.ContentType = String.Concat("multipart/form-data; boundary=", BoundaryString);
            httpWebRequest.Method = "POST";
            // start the asynchronous operation
            httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, postData); }, httpWebRequest);
        }

        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

            // End the operation
            Stream postStream = request.EndGetRequestStream(asynchronousResult); 

            // Write to the request stream.
            postStream.Write(postData, 0, postData.Length);
            postStream.Close(); 

            // Start the asynchronous operation to get the response
            request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);

        }

        catch (Exception ex)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetRequestStreamCallback]:", ex.ToString()); });                
        }
    }


    private void GetResponseCallback(IAsyncResult asynchronousResult)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState; 

            // End the operation
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();
            StreamReader streamRead = new StreamReader(streamResponse);
            string responseString = streamRead.ReadToEnd();

            System.Diagnostics.Debug.WriteLine(responseString);
            //Update the UI 

            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Upload Success! Picture ID:", responseString); });

            // Close the stream object
            streamResponse.Close();
            streamRead.Close();
            // Release the HttpWebResponse
            response.Close();
        }

        catch (Exception ex)
        {
            //MessageBox.Show(ex.ToString());
            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetResponseCallback]:", ex.ToString()); });
        }
    }

    #endregion



    #region ImageManipulation

    //Opens an image file in isolated storage and returns it as a
    //BitmapImage object we could use as the image in the PostData method
    public BitmapImage GetImageFromIsolatedStorage(String ImageFileName)
    {
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                // Open the file
                using (IsolatedStorageFileStream isfs = isf.OpenFile(ImageFileName, FileMode.Open, FileAccess.Read))
                {
                    //use the stream as the source of the Bitmap Image
                    BitmapImage bmpimg = new BitmapImage();
                    bmpimg.SetSource(isfs);
                    isfs.Close();
                    return bmpimg;
                }
            }
        }
    }


    //ImageToByteArray(BitmapImage) accepts a BitmapImage object and
    //converts it to a byte array we can use in the POST buffer
    private byte[] ImageToByteArray(BitmapImage bm_Image)
    {
        byte[] data;
        {
            // Get an Image Stream
            MemoryStream ms_Image = new MemoryStream();
            // write an image into the stream
            System.Windows.Media.Imaging.Extensions.SaveJpeg(new WriteableBitmap(bm_Image), ms_Image, bm_Image.PixelWidth, bm_Image.PixelHeight, 0, 100);
            // reset the stream pointer to the beginning
            ms_Image.Seek(0, 0);
            //read the stream into a byte array
            data = new byte[ms_Image.Length];
            ms_Image.Read(data, 0, data.Length);
            ms_Image.Close();
        }
        //data now holds the bytes of the image
        return data;
    }



    //GetBitmapImageFromUIElement accepts a UIElement (canvas, grid, image, etc...)1
    //and builds a BitmapImage of it including any child elements
    public BitmapImage GetBitmapImageFromUIElement(UIElement element)
    {
        try
        {
            WriteableBitmap bmp = new WriteableBitmap((int)element.RenderSize.Width, (int)element.RenderSize.Height);
            bmp.Render(element, null);
            bmp.Invalidate(); 

            // Get an Image Stream
            MemoryStream ms_Image = new MemoryStream(); 

            // write the image into the stream

            bmp.SaveJpeg(ms_Image, (int)element.RenderSize.Width, (int)element.RenderSize.Height, 0, 100);
            // reset the stream pointer to the beginning
            ms_Image.Seek(0, 0);
            //use the stream as the source of the Bitmap Image
            BitmapImage bmpimg = new BitmapImage();
            bmpimg.SetSource(ms_Image);
            ms_Image.Close();

            return bmpimg;
        }

        catch (Exception ex)
        {
            UpdatePostStatus("Error Getting Bitmap from UIElement:", ex.Message);
            return null;
        }

    }

    #endregion

    #region Events code



    //Raise the PostStatus Event so the calling code knows whats going on

    private void UpdatePostStatus(string strHeader, string strContents)
    {
        if (PostStatus != null)
        {
            PostStatus(this, new PostStatusEventArgs(strHeader, strContents));
        }
    }

    public class PostStatusEventArgs : EventArgs
    {

        private readonly string msg_header = string.Empty;
        private readonly string msg_contents = string.Empty;
        // Constructor. 

        public PostStatusEventArgs(string msgHeader, string msgContents)
        {  
            this.msg_header = msgHeader;
            this.msg_contents = msgContents;
        }



        // Properties.
        public string MessageHeader { get { return msg_header; } }
        public string MessageContents { get { return msg_contents; } }

    }



    //the PostStatus Event sends status updates

    public delegate void PostStatusEventHandler(object sender,PostStatusEventArgs e); 

    public event PostStatusEventHandler PostStatus;



    #endregion
}

My Problem is asynchronization. When user clicks on share button on ApplicationBar, the 'LoginPage.xaml' is navigated. But before executing / loading the LoginPage.xaml, the returns back & executes postPhotoToFacebook(). postPhotoToFacebook() uses FBFBPhotoPost methods to share photo on facebook. As webbrowser is not completely loaded, the photo does not reaches when I clicks on ApplicationBar button. Sometimes, it reaches to facebook while sometimes not. I want that when user clicks on share button, image must be shared on facebook (ofcourse when user is logged in).

I also taken postPhotoToFacebook() on LoginPage, but canvas (from MainPage.xaml) cannot be accessed from LoginPage. After coming back from LoginPage, i have to execute postPhotoToFacebook().

Please help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜