0

I am looking for a possibility to start my own Windows App after some content is shared with it through the charm bar. I have found this MS example https://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782/ But after the share button is clicked the app closes. I have tryed it this code at the button click method:

var rootFrame = new Frame();
rootFrame.Navigate(typeof(DefaultPage));
Window.Current.Content = rootFrame;
Window.Current.Activate();

But this has no effect. Also I have tryed to use Application.Start() but the parameter should be a Callback and I don't understand which one.

-------Edit: I want the following behavior.

  1. open IE (already done)
  2. open Charm Bar and click on Share (already done)
  3. select my App (already done)
  4. My App show a Sharing page with information and a share button (already done)
  5. after the share button at my app is clicked open Mainpage (at the MS example the Default page)

So I can't find a solution for the last step. Switching from the Sharing page of my app to the Main Page of my app.

Edit End-------

Every thing I want is to start my App after some content is shared with it. I hope somebody can help me. Or is this not possible?

----Edit 2:

App.xaml.cs:

using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

    // The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227

    namespace AppName
    {
        /// <summary>
        /// Provides application-specific behavior to supplement the default Application class.
        /// </summary>
        sealed partial class App : Application
        {
            /// <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();
                this.Suspending += OnSuspending;
            }

            /// <summary>
            /// Invoked when the application is launched normally by the end user.  Other entry points
            /// will be used such as when the application is launched to open a specific file.
            /// </summary>
            /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            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)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();
                // Set the default language
                rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <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 void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }

        /// <summary>
        /// Invoked when the application is activated as the target of a sharing operation.
        /// </summary>
        /// <param name="e">Details about the activation request.</param>
        protected override void OnShareTargetActivated(Windows.ApplicationModel.Activation.ShareTargetActivatedEventArgs e)
        {
            var shareTargetPage = new AppName.ShareTargetPage();
            shareTargetPage.Activate(e);
            Window.Current.Activate();
        }

        protected override void OnActivated(IActivatedEventArgs args)
        {
            base.OnActivated(args);
        }

    }
}

Mainpage.xaml.cs:

using System;
using Windows.UI.Xaml.Controls;


// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace AppName
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        public void ReceiveUri(Uri sharedWebLink)
        {
            tbMessages.Text = sharedWebLink.ToString();
        }

        protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
        {
            // It is possible to get in this method after the Share button at the 
            // sharetargetpage is clicked but at this point I don't know how to 
            // activate the app

            //base.OnNavigatedTo(e);
        }

    }
}

Sharepargetpage.xaml.cs:

using Windows.UI.Core;
using AppName.Common;
using System;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;

// The Share Target Contract item template is documented at http://go.microsoft.com/fwlink/?LinkId=234241

namespace AppName
{
    /// <summary>
    /// This page allows other applications to share content through this application.
    /// </summary>
    public sealed partial class ShareTargetPage : Page
    {
        private Uri sharedWebLink;


        /// <summary>
        /// Provides a channel to communicate with Windows about the sharing operation.
        /// </summary>
        private Windows.ApplicationModel.DataTransfer.ShareTarget.ShareOperation _shareOperation;
        private ObservableDictionary defaultViewModel = new ObservableDictionary();

        /// <summary>
        /// This can be changed to a strongly typed view model.
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }

        public ShareTargetPage()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Invoked when another application wants to share content through this application.
        /// </summary>
        /// <param name="e">Activation data used to coordinate the process with Windows.</param>
        public async void Activate(ShareTargetActivatedEventArgs e)
        {
            this._shareOperation = e.ShareOperation;

            // Communicate metadata about the shared content through the view model
            var shareProperties = this._shareOperation.Data.Properties;
            var thumbnailImage = new BitmapImage();
            this.DefaultViewModel["Title"] = shareProperties.Title;
            this.DefaultViewModel["Description"] = shareProperties.Description;
            this.DefaultViewModel["Image"] = thumbnailImage;
            this.DefaultViewModel["Sharing"] = false;
            this.DefaultViewModel["ShowImage"] = false;
            this.DefaultViewModel["Comment"] = String.Empty;
            this.DefaultViewModel["Placeholder"] = "Add a comment";
            this.DefaultViewModel["SupportsComment"] = true;
            Window.Current.Content = this;
            Window.Current.Activate();

            try
            {
                this.sharedWebLink = await this._shareOperation.Data.GetWebLinkAsync();
                this.DefaultViewModel["URL"] = this.sharedWebLink.ToString();
            }
            catch (Exception ex)
            {
                NotifyUserBackgroundThread("Failed GetWebLinkAsync - " + ex.Message, NotifyType.ErrorMessage);
            }

            // Update the shared content's thumbnail image in the background
            if (shareProperties.Thumbnail != null)
            {
                var stream = await shareProperties.Thumbnail.OpenReadAsync();
                thumbnailImage.SetSource(stream);
                this.DefaultViewModel["ShowImage"] = true;
            }
        }

        /// <summary>
        /// Invoked when the user clicks the Share button.
        /// </summary>
        /// <param name="sender">Instance of Button used to initiate sharing.</param>
        /// <param name="e">Event data describing how the button was clicked.</param>
        private void ShareButton_Click(object sender, RoutedEventArgs e)
        {
            this.DefaultViewModel["Sharing"] = true;
            this._shareOperation.ReportStarted();

            // TODO: Perform work appropriate to your sharing scenario using
            //       this._shareOperation.Data, typically with additional information captured
            //       through custom user interface elements added to this page such as 
            //       this.DefaultViewModel["Comment"]

            this._shareOperation.ReportCompleted();

            // TRY1: Navigate to MainPage
            //Frame rootFrame = Window.Current.Content as Frame;
            //if(rootFrame == null)
            //{
            //    rootFrame = new Frame();
            //    Window.Current.Content = rootFrame;
            //}
            //if(rootFrame.Content == null)
            //{
            //    rootFrame.Navigate(typeof(MainPage));
            //}

            //  TRY2: Navigate to MainPage
            //var p = rootFrame.Content as MainPage;
            //p.ReceiveUri(sharedWebLink);
            //Window.Current.Activate();


            var rootFrame = new Frame();
            rootFrame.Navigate(typeof(MainPage));
            Window.Current.Content = rootFrame;
            Window.Current.Activate();

            // TRY3: Start the App
            // Application.Start();
            // App.Start();
            // but I don't know which callback method should be the param of start
        }

        async private void NotifyUserBackgroundThread(string message, NotifyType type)
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                NotifyUser(message, type);
            });
        }

        private void NotifyUser(string strMessage, NotifyType type)
        {
            switch (type)
            {
                // Use the status message style.
                case NotifyType.StatusMessage:
                    StatusBlock.Style = Resources["StatusStyle"] as Style;
                    break;
                // Use the error message style.
                case NotifyType.ErrorMessage:
                    StatusBlock.Style = Resources["ErrorStyle"] as Style;
                    break;
            }
            StatusBlock.Text = strMessage;
        }

        public enum NotifyType
        {
            StatusMessage,
            ErrorMessage
        };
    }
}

Edit 2 End ---------

Damien
  • 37
  • 6
  • Would you like to share you code here ? Without that no one will be able to detect the problem – Adnan Umer Dec 22 '14 at 09:07
  • I don't knows your current implementation. What I understand is you want to launch your app as user clicks share button. If you want to do that remember WinRT doesn't allows you to launch any app. You can try protocols and use `Launcher` to launch protocol. If you app is associated with that protocol you app will simply launches. Otherwise you can always use `Frame.Navigate` to navigate to other page. But this will not launches your app. – Adnan Umer Dec 22 '14 at 09:18
  • I have add some code ... hopefully this explain more my problem. – Damien Dec 22 '14 at 11:48
  • I edited my answer below and included the solution. Have a look – Adnan Umer Dec 22 '14 at 17:49
  • @AdnanUmer : Can you provide a source which states we cannot launch the app in WinRT using share Target as I wanted to do something similar to what whatsapp does when sharing images(After sharing the app remains open). – AbsoluteSith Aug 18 '15 at 09:02
  • @AbsoluteSith See reply here https://social.msdn.microsoft.com/Forums/en-US/14e2be68-ef86-4480-a3fd-6ddf7ec7d1f1/how-to-start-a-external-program-from-metro-app?forum=winappswithcsharp – Adnan Umer Aug 19 '15 at 14:05

2 Answers2

0

To enable your app's behavior as Share Targeted app, you have to override OnShareTargetActivated(ShareTargetActivatedEventArgs args) method in App class.

protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    var rootFrame = new Frame();

    // TODO: Load content in frame

    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

EDIT

From your current implementation you are going to setShareTargetPage inside windows and later you cast Windows.Current.Content to Frame that is always null. So, you can't do this way. My recommendation is to do it this way.

Change OnShareTargetActivated method inside App.xaml.cs to this

protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(ShareTargetPage), args);
    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

Remove this from Activate method in ShareTargetPage.xaml.cs

Window.Current.Content = this;
Window.Current.Activate();

Overrides OnNavigatedTo in ShareTargetPage class

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Calling Activate method here
    Activate((ShareTargetActivatedEventArgs)e.Parameter);
}

And then to navigate to another page you can simply Calls Frame.Navigation something like that inside ShareTargetPage

this.Frame.Navigate(typeof(MainPage));

EDIT 2

If you want to navigate to another page on share button click then remove this line of code

this._shareOperation.ReportCompleted();

This calling above method informs the OS that your app has finished sharing request and is now safely terminated. That's why your app terminates without navigation to another page

Adnan Umer
  • 3,669
  • 2
  • 18
  • 38
  • The possebility to Share Content with the Exempel app is not the Problem. I already can Do that. I am Looping for the possebility to Start my app after the User press tue Share Button on the Charme bar. – Damien Dec 21 '14 at 19:27
  • Open Properties and Check "Do not launch, but debug my app when starts" in Debug section. Debug your app to see why your app crashes. – Adnan Umer Dec 21 '14 at 19:33
  • Your new solution is only partly working after I add in Mainpage.xaml.cs `code`protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); } after I add this, it is possible to stop there with an break point but this also don't open the main page. Maybe this is because the app and the sharingpage are different threads and the API don't allow to start an app afer something is shared with it. What do you think? – Damien Dec 23 '14 at 07:50
  • Can you upload your solution somewhere and paste a link here. So I can debug your code better. – Adnan Umer Dec 23 '14 at 08:00
  • I have upload it here ... https://onedrive.live.com/redir?resid=B29E5A118ABE8C0%2154075 ... thanks für your help :) – Damien Dec 23 '14 at 09:53
  • sry to be a pain in the ass ... but unfortunately this is not the behavior that i want. If I delete the ReportCompleted() Method the Mainpage is showen in the Sharing window but not fully. I am looking for a possebilety to open my app completly not only in the sharing window (fly out). – Damien Dec 23 '14 at 14:31
  • As in my previous comment I explained that WinRT doesn't allows direct execution of any app. You can associate your app with a protocol and launch that particular protocol. More detail here http://blog.jerrynixon.com/2012/10/walkthrough-using-windows-8-custom.html – Adnan Umer Dec 23 '14 at 14:41
  • @Damien it would be nice to put this solution (**usage of custom url protocol**) somewhere at your initial question at the end - just to make it more clear and easily discoverable by others, since it is not part of the accepted answer. – Sevenate Aug 04 '16 at 00:13
  • @Sevenate the answere with the green tick is the solution ;) so feel free to read it – Damien Aug 05 '16 at 07:11
0

What you are trying to do goes against the Windows Store guidelines, and your app would be rejected if you managed to achieve it.

See the guidelines here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465251.aspx

Your share target app must pop up only as a share target and must be dismissed with any user interaction outside the sharing panel.

You could probably get around this by adding a button in the share panel 'launch full app', and then create a custom URI that launches your app. But that is probably not advisable.

pumpkinszwan
  • 1,312
  • 11
  • 21
  • are you shure? I have read it bevore and now again and can't find anything about my wanted behavior. – Damien Dec 23 '14 at 14:38
  • "•Don't perform time-consuming, complex, or multi-step interactions in your target app. Text formatting, tagging people in photos, or setup tasks like connecting to data sources are best handled outside of the Share charm. If your app requires multi-step sign-in or setup processes, tell users to open your app directly to complete more complex interactions." And your app is supposed to report back to the sharing app when sharing is finished so the sharing app can resume. – pumpkinszwan Dec 23 '14 at 15:50
  • now I have find a solution where the share app is finished correctly and after this the button click method calls my own protcol which starts my own app. We will see if my app will rejected or not :) – Damien Dec 23 '14 at 16:15