Follow us on X (Twitter)  Like us on Facebook  Connect with us on LinkedIn  Subscribe to our YouTube Channel  Subscribe to our WhatsApp Group

Continuing my Windows Phone 7 Tutorials on Launchers and Choosers. Today in this blog post we will discuss about the Windows Phone 7 class named “SaveRingtoneTask”. We will first describe about the internal class implementation of the SDK itself. Later we will see how to implement it in your application.

 

Continue reading to learn about the API and code implementation. Don’t forget to share your thoughts and feedbacks at the end in the comments section. Also, share this to your friends/colleagues who might feel it useful too.

 

Know About the API

SaveRingtoneTask” is a sealed class present in the “Microsoft.Phone.Tasks” namespace and inherits ChooserBase class of type TaskEventArgs. It enables an application to launch the ringtones application and allows users to save a ringtone from the application to the system ringtones list. It exposes three properties named Source, DisplayName and IsShareable.

 

You can set or retrieve the file path to the local copy of the audio file to be added to the ringtone directory using the Source property. DisplayName used to identify the ringtone in the picker and IsShareable property is a flag that indicates if the ringtone should be accessible to other applications.

 

Here is the meta data of the SaveRingtoneTask:

 

namespace Microsoft.Phone.Tasks
{
    public sealed class SaveRingtoneTask : ChooserBase<TaskEventArgs>
    {
        public Uri Source { get; set; }
        public string DisplayName { get; set; }
        public bool IsShareable { get; set; }
 
        public override void Show();
    }
}

 

The Show() method enables an application to launch the ringtones application. Call the method when you want to save the ringtone in the system ringtone list.

 

Do you want to know, how the class has been internally implemented by the WP7 SDK? Ok, as I did in the earlier posts, I am sharing the complete code of the SaveRingtoneTask class. It is a decompiled version of the class and hence I can’t give you 100% guarantee of the code.

 

Here is the decompiled version of the SaveRingtoneTask class:

 

 
namespace Microsoft.Phone.Tasks
{
  public sealed class SaveRingtoneTask : ChooserBase<TaskEventArgs>
  {
    private const int MAX_PATH = 260;
    private const int MAX_FILE_SIZE = 1048576;
    private Uri _source;
    private string _displayName;
    private string _tokenId;
 
    public Uri Source
    {
      get
      {
        return this._source;
      }
      set
      {
        if (value == (Uri) null)
          throw new ArgumentNullException("Source", "Path cannot be null.");
        string str = value.LocalPath.Substring(value.LocalPath.LastIndexOf(".") + 1);
        if (!str.ToLower().Equals("wma") && !str.ToLower().Equals("mp3"))
          throw new ArgumentOutOfRangeException("Source", "Ringtone file is in an invalid format.");
        this._source = value;
      }
    }
 
    public string DisplayName
    {
      get
      {
        return this._displayName;
      }
      set
      {
        if (value == null || ((object) value).ToString().Length < 1)
        {
          this._displayName = "";
        }
        else
        {
          if (((object) value).ToString().Length > 260)
            throw new ArgumentException("DisplayName is too long.");
          this._displayName = value;
        }
      }
    }
 
    public bool IsShareable { get; set; }
 
    public override void Show()
    {
      if (!ChooserHelper.NavigationInProgressGuard((Action) (() => this.Show())))
        return;
      if (this._source == (Uri) null)
        throw new InvalidOperationException("Path cannot be null.");
      this.Source = this._source;
      this.DisplayName = this._displayName;
      HostInfo hostInfo = new HostInfo();
      string str = string.Empty;
      string fileSystemPath;
      try
      {
        fileSystemPath = hostInfo.GetFileSystemPath(this.Source.ToString());
        this._tokenId = DSC.DSCreateSharedFileTokenManaged(fileSystemPath);
      }
      catch (Exception ex)
      {
        throw new InvalidOperationException("Path must point to a file in your " + 
                                "Isolated Storage or Application Data directory.");
      }
      ParameterPropertyBag ppb = new ParameterPropertyBag();
      ppb.CreateProperty("TokenId").StringValue = this._tokenId;
      ppb.CreateProperty("Source").StringValue = fileSystemPath;
      ppb.CreateProperty("DisplayName").StringValue = this.DisplayName;
      ppb.CreateProperty("IsShareable").BoolValue = this.IsShareable;
      byte[] buffer = ChooserHelper.Serialize(ppb);
      Uri appUri = new Uri("app://D8CF8EC7-EC6D-4892-AAB9-1E3A4B5FA24B/SaveRingtone", 
                                                                    UriKind.Absolute);
      base.Show();
      ChooserHelper.Invoke(appUri, buffer, (IChooser) this._genericChooser);
    }
 
    internal override void OnInvokeReturned(byte[] outputBuffer, Delegate fireThisHandlerOnly)
    {
      bool flag = false;
      uint num = 0U;
      if (outputBuffer.Length > 0)
      {
        ParameterProperty property = new ParameterPropertyBag(outputBuffer, 
                                         (uint) outputBuffer.Length).GetProperty("Error");
        if (property.ValueType == ParameterPropertyValueType.ValueType_Int32)
          num = (uint) property.Int32Value;
        flag = (int) num == 0;
      }
      else
        num = 4U;
      if (flag)
      {
        this.FireCompleted((object) this, 
                            new TaskEventArgs(TaskResult.OK), 
                            fireThisHandlerOnly);
      }
      else
      {
        TaskEventArgs e = new TaskEventArgs(TaskResult.Cancel);
        if (num > 0U)
        {
          switch (num)
          {
            case 1U:
              e.Error = (Exception) new InvalidOperationException
                                            ("Ringtone file is in an invalid format.");
              break;
            case 2U:
              e.Error = (Exception) new InvalidOperationException
                                            ("Ringtone file is too large.");
              break;
            case 3U:
              e.Error = (Exception) new IOException
                                            ("There is not enough space on disk.");
              break;
            case 4U:
              break;
            default:
              e.Error = (Exception) new IOException
                                            ("Failed to save ringtone.");
              break;
          }
        }
        this.FireCompleted((object) this, e, fireThisHandlerOnly);
      }
    }
 
    internal enum SAVE_RINGTONE_RESULT
    {
      SAVE_RINGTONE_RESULT_SUCCESS,
      SAVE_RINGTONE_RESULT_ERRORINVALIDDATA,
      SAVE_RINGTONE_RESULT_ERRORFILETOOLARGE,
      SAVE_RINGTONE_RESULT_ERRORDISKFULL,
      SAVE_RINGTONE_RESULT_ERRORCANCEL,
    }
  }
}

 

 

From the above code snippet, you can easily understand how Microsoft implemented their SDK to save a ringtone and handled it in various exception with the Ringtone Result.

 

Implementation Steps

How to Save Ringtones in WP7 using the SaveRingtoneTask?

Let’s begin with the code implementation in your application. If you want to integrate the ring tone saving feature in your application, first create the instance of the SaveRingtoneTask class and set the properties (optional) properly.

 

If you want to handle the result, just register for the completed event of the task.

 

In the final step, call the Show() method to launch the Ringtone application to start the saving task.

 

 

Here is the code snippet:

 

 
var saveRingtoneChooser = new SaveRingtoneTask
                              {
                                  Source = new Uri(AUDIO_PATH, UriKind.RelativeOrAbsolute)
                              };
saveRingtoneChooser.Completed += SaveRingtoneChooserCompleted;
saveRingtoneChooser.Show();

 

 

In the completed event implementation, check the e.TaskResult of the event. If the TaskResult comes as “OK” handle the user task as completed and if it returns other result, you can understand that the user interrupted the saving task and based on that you can handle the next steps.

 

Here is the code snippet of the sample completed event implementation:

 

 
void SaveRingtoneChooserCompleted(object sender, TaskEventArgs e)
{
    switch (e.TaskResult)
    {
        case TaskResult.OK:
            // Ringtone saved successfully by the user
            
            break;
 
        case TaskResult.Cancel:
            // Saving interrupted by the user
           
            break;
 
        default:
            break;
    }
}

 

I hope that, the post was easy for you to understand the API implementation and actual code implementation in your application. If you have any queries, please use the comment form below to leave your queries. I will try to answer you as soon as possible. Your feedback and suggestions are always welcome and highly appreciable.

 

Stay tuned to my blog, twitter or facebook to read more articles, tutorials, news, tips & tricks on various technology fields. Also Subscribe to our Newsletter with your Email ID to keep you updated on latest posts. We will send newsletter to your registered email address. We will not share your email address to anybody as we respect privacy.

Have a question? Or, a comment? Let's Discuss it below...

Thank you for visiting our website!

We value your engagement and would love to hear your thoughts. Don't forget to leave a comment below to share your feedback, opinions, or questions.

We believe in fostering an interactive and inclusive community, and your comments play a crucial role in creating that environment.