F0rc0sigan
F0rc0sigan

Reputation: 674

Xamarin Android: Share image via standard api (email, facebook etc.)

I need to implement standard sharing in Xamarin Android. I found and changed code for Xamarin. It looks like this

    public void Share (string title, string content)
    {
        if (string.IsNullOrEmpty (title) || string.IsNullOrEmpty (content))
            return;

        var name = Application.Context.Resources.GetResourceName (Resource.Drawable.icon_120).Replace (':', '/');
        var imageUri = Uri.Parse ("android.resource://" + name);
        var sharingIntent = new Intent ();
        sharingIntent.SetAction (Intent.ActionSend);
        sharingIntent.SetType ("image/*");
        sharingIntent.PutExtra (Intent.ExtraText, content);
        sharingIntent.PutExtra (Intent.ExtraStream, imageUri);
        sharingIntent.AddFlags (ActivityFlags.GrantReadUriPermission);
        ActivityContext.Current.StartActivity (Intent.CreateChooser (sharingIntent, title));
    }

This code call standard share function, but when i choose Facebook or email, i am getting "Cant load image". File is located in "/Resources/drawable-xhdpi/icon_120.png".

Can you point me what i am doing wrong?

Upvotes: 5

Views: 6212

Answers (2)

Abdullah Tahan
Abdullah Tahan

Reputation: 2129

I have implemented share for twitter and fb . You can use native facebook ShareDialog and if isn't available use OAuth2Authenticator to get access token then post using FB graph and using OAuth1Authenticator for posing on twitter

public void ShareViaSocial(string serviceType, string urlToShare)
        {
            ShareDialog di = new ShareDialog(MainActivity.Instance);
             var facebookShareContent = new ShareLinkContent.Builder();
             facebookShareContent.SetContentUrl(Android.Net.Uri.Parse(urlToShare));
            if (serviceType == "Facebook")
            {
                if (di.CanShow(facebookShareContent.Build(), ShareDialog.Mode.Automatic))
                {
                    di.Show(facebookShareContent.Build());
                }
                else
                {
                    var auth = new OAuth2Authenticator(
                    clientId: 'ClientId',
                    scope: "public_profile,publish_actions",
                    authorizeUrl: new Uri("https://m.facebook.com/dialog/oauth/"),
                    redirectUrl: new Uri( "http://www.facebook.com/connect/login_success.html"));

                    MainActivity.Instance.StartActivity(auth.GetUI(MainActivity.Instance.ApplicationContext));

                    auth.AllowCancel = true;
                    auth.Completed += (s, e) =>
                    {
                        if (e.IsAuthenticated)
                        {
                            Account fbAccount = e.Account;
                            Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "link", urlToShare } };
                            var requestUrl = new Uri("https://graph.facebook.com/me/feed");
                            var request = new OAuth2Request(SharedConstants.requestMethodPOST, requestUrl, dictionaryParameters, fbAccount);

                            request.GetResponseAsync().ContinueWith(this.requestResult);
                        }
                        else { OnShare(this, ShareStatus.NotSuccessful); }
                    };
                    auth.Error += Auth_Error;
                }
            }

            else
            {
                var auth = new OAuth1Authenticator(
                               'TwitterConsumerKey',
                               'TwitterConsumerSecret',
                               new Uri("https://api.twitter.com/oauth/request_token"),
                               new Uri("https://api.twitter.com/oauth/authorize"),
                               new Uri("https://api.twitter.com/oauth/access_token"),
                               new Uri('TwitterCallBackUrl'));

                auth.AllowCancel = true;
                // auth.ShowUIErrors = false;
                // If authorization succeeds or is canceled, .Completed will be fired.
                auth.Completed += (s, e) =>
                {
                    // We presented the UI, so it's up to us to dismiss it.

                    if (e.IsAuthenticated)
                    {
                        Account twitterAccount = e.Account;
                        Dictionary<string, string> dictionaryParameters = new Dictionary<string, string>() { { "status", urlToShare } };
                        var request = new OAuth1Request(SharedConstants.requestMethodPOST, new Uri("https://api.twitter.com/1.1/statuses/update.json"), dictionaryParameters, twitterAccount);
                        //for testing var request = new OAuth1Request("GET",new Uri("https://api.twitter.com/1.1/account/verify_credentials.json "),null, twitterAccount);
                        request.GetResponseAsync().ContinueWith(this.requestResult);
                    }
                    else { OnShare(this, ShareStatus.NotSuccessful); }
                };
                auth.Error += Auth_Error;
                //auth.IsUsingNativeUI = true;
                MainActivity.Instance.StartActivity(auth.GetUI(MainActivity.Instance.ApplicationContext));
            }


        }

Upvotes: 0

Iain Smith
Iain Smith

Reputation: 9703

I think the app icon is created in a directory that is private to your app, so other apps wont be able to get at it.

You will need to save it out somewhere where the other apps can access it then share it from that location some thing like this:

public void Share (string title, string content)
{
    if (string.IsNullOrEmpty (title) || string.IsNullOrEmpty (content))
                return;

    Bitmap b = BitmapFactory.DecodeResource(Resources,Resource.Drawable.icon_120);

    var tempFilename = "test.png";
    var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
    var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
    using (var os = new FileStream(filePath, FileMode.Create))
    {
        b.Compress(Bitmap.CompressFormat.Png, 100, os);
    }
    b.Dispose ();

    var imageUri = Android.Net.Uri.Parse ($"file://{sdCardPath}/{tempFilename}");
    var sharingIntent = new Intent ();
    sharingIntent.SetAction (Intent.ActionSend);
    sharingIntent.SetType ("image/*");
    sharingIntent.PutExtra (Intent.ExtraText, content);
    sharingIntent.PutExtra (Intent.ExtraStream, imageUri);
    sharingIntent.AddFlags (ActivityFlags.GrantReadUriPermission);
    StartActivity (Intent.CreateChooser (sharingIntent, title));
}

Also add ReadExternalStorage and WriteExternalStorage permissions to your app.

Let me know if that works.

Upvotes: 7

Related Questions