How you can add custom ringtones to your Windows Phone 7 from your app (w/out Marketplace)

http://dotnet.dzone.com/articles/how-you-can-add-custom

We all know that Windows Phone 7 doesn't carry support ringtone modifications (not by default). This can be a bit frustrating for people who don't like any of the 30 pre-loaded tunes (although it's probably hard to find one). In this article I am going to show you how it is possible to upload your own ringtone to your WP7 device. If you are not interested in the code part of the problem and detailed explanations related to it, I would recommend going to Chris Walshie's blog and downloading the ringtone installerright away.

First thing you need to know is that this method is not official. Using it in your app will most likely cause the app to be rejected from the Windows Phone Marketplace. So use this at your own risk.

The easiest method is to use the Microsoft.Phone.Media.Extended library - it can be downloaded directly from this place. I will also show how to do the same thing via reflection, so that you won't have to add an extra dependency, but that's for later.

Before I start coding, prepare a bunch of ringtones that you want to copy to the phone. It should be aWMA (Windows Media Audio) file. There are no restrictions on the bitrate. I used Expression Encoder 4 to encode a MP3 file to WMA starting at 48kbps and ending with 320kbps and uploaded them on the phone - every single one played correctly.

Once you added a reference to Microsoft.Phone.Media.Extended, you will need to instantiate the RingtoneLibrary class. It is a singleton, therefore you need to use the current instance:

RingtoneLibrary lib = RingtoneLibrary.Instance;

 

NOTE: As pointed by keyboardP, "ID_CAP_RINGTONE_ADD" is a capability that must be declared in WMAppManifest.xml.

This class has one method that is needed to perform the operation - AddRingtone. It accepts two parameters - a Stream instance (ringtone contents) and a string (the name of the ringtone). The name of the ringtone must contain the wma extension in order to be registered.

So for example, here is how I can call  it for a ringtone that I want to call Morning:

lib.AddRingtone(stream, "Morning.wma");

The WMA extension will not be shown in the ringtone list. The stream for the WMA file can be obtained in a multitude of ways. For example, I can download it:

WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri("http://dennisdel.com/someFile.wma"));

Once the data is downloaded:

void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
MemoryStream st = new MemoryStream();
byte[] buffer = new byte[1024];

int count;

while ((count = e.Result.Read(buffer, 0, buffer.Length)) > 0)
{
  st.Write(buffer, 0, count);
}

byte[] b = st.ToArray();

MemoryStream s = new MemoryStream(b);

RingtoneLibrary lib = RingtoneLibrary.Instance;

lib.AddRingtone(s, "Morning.wma");

}

You might be wondering - why I am using two MemoryStream instances here. For some reason, when I am passing the MemoryStream instance that was created from based on the existing Stream (e.Result), the track isn't played (although the length of the byte array remains the same). When MemoryStream is created from a byte array directly, the audio is correctly registered and played later on.

This method also works on the emulator and if you have the debugging console enabled, you will see how the ringtone addition process is logged.

Now let's take a look at the code snippet that will do the same thing without adding an extra DLL reference:

Assembly extendedAssembly = Assembly.Load("Microsoft.Phone.Media.Extended, Version=7.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e");
           
 
Type ringtoneLib = extendedAssembly.GetType("Microsoft.Phone.RingtoneLibrary");
FieldInfo instanceF = ringtoneLib.GetField("Instance");

 

object instance = instanceF.GetValue(null);

 

MethodInfo m = ringtoneLib.GetMethod("AddRingtone");

m.Invoke(instance, new object[] { s, "main.wma" });

That's it - not that long as one would expect. Given that I already knew the types and methods used, it is fairly easy to go the Reflection way. The only thing to remember here is that there is a singleton present and in order to get the current class instance I need to get the value of the Instance field.

转载于:https://www.cnblogs.com/Hack-ok/archive/2012/12/25/2832847.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值