I am trying to port my WP7 app to android. I was using Bing translation service to download & play audio for specific words/phrases. How can I do this in android? in bing, the stream comes as a .wav file. Here was my WP7 code:
private void button1_Click(object sender, RoutedEventArgs e)
{
this.Speak();
}
public void Speak()
{
string appId = "Your ID";
string text = "Speak this for me";
string language = "en";
string uri = "http://api.microsofttranslator.com/v2/Http.svc/Speak?appId=" + appId +
"&text=" + text + "&language=" + language + "&file=speak.wav";
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri(uri));
}
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null) return;
var sound = e.Result;
Player.Source = null;
string filename = "MyAudio";
using (IsolatedStorageFile userStoreForApplication = IsolatedStorageFile.GetUserStoreForApplication())
{
bool fileExists = userStoreForApplication.FileExists(filename);
if (fileExists)
{
userStoreForApplication.DeleteFile(filename);
}
var isolatedStorageFileStream = userStoreForApplication.CreateFile(filename);
using (isolatedStorageFileStream)
{
SaveFile(e.Result, isolatedStorageFileStream);
if (e.Error == null)
{
Player.SetSource(isolatedStorageFileStream);
}
}
}
}
public static void SaveFile(System.IO.Stream input, System.IO.Stream output)
{
try
{
byte[] buffer = new byte[32768];
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
return;
}
output.Write(buffer, 0, read);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
void mysound_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
MessageBox.Show(e.ErrorException.Message);
}
void mysound_MediaOpened(object sender, RoutedEvent开发者_如何学运维Args e)
{
Player.Play();
}
I thought I'd just drop a generic response about executing HTTP requests and downloading files, but the more troublesome thing I ran into is how Microsoft Azure wants to do authentication. Evidently using an App ID is deprecated and their API is extremely picky about the request headers and parameters.
In any case, I'd suggest starting with writing an AsyncTask
that handles executing a HttpURLConnection
. I ended up with:
/**
* Tailor-made HTTP request for Microsoft Azure, downloading a file to a
* specified location.
*/
private class HttpDownloadFile extends AsyncTask<String, Integer, String> {
private String mDir;
@Override
protected String doInBackground(String... params) {
if (params.length < 2) {
throw new IllegalArgumentException(
"Two arguments required for "
+ getClass().getSimpleName());
}
String response = null;
String uri = params[0];
String query = params[1];
try {
if (query.length() > 0) {
uri += "?" + query;
}
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
if (params.length > 2) {
connection.setRequestProperty("Authorization", "Bearer "
+ params[2]);
}
connection.connect();
int fileLength = connection.getContentLength();
String charset = PREFERRED_CHARSET;
if (connection.getContentEncoding() != null) {
charset = connection.getContentEncoding();
}
InputStream input;
OutputStream output;
boolean isError = false;
try {
input = connection.getInputStream();
output = new FileOutputStream(mDir);
} catch (IOException e) {
input = connection.getErrorStream();
output = new ByteArrayOutputStream();
isError = true;
}
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
if (!isError) {
response = mDir;
} else {
response = ((ByteArrayOutputStream) output).toString(charset);
Log.e(TAG, response);
response = null;
}
output.close();
input.close();
} catch (Exception e) {
Log.e(TAG, "Failed requesting " + uri, e);
}
return response;
}
}
You can then execute the task with the correct parameters:
HttpDownloadFile task = new HttpDownloadFile();
task.execute(
getString(R.string.url_speak),
getString(R.string.url_speak_query,
text, toLanguage, file),
accessToken,
Environment.getExternalStorageDirectory().getPath()
+ "/temp.wav");
My strings.xml
contains:
<string
name="url_speak"
formatted="false"
translate="false">http://api.microsofttranslator.com/v2/Http.svc/Speak</string>
<string
name="url_speak_query"
formatted="false"
translate="false">text=%s&language=%s&file=%s</string>
Unfortunately, this implies that you have to code for obtaining the authentication token already done. No worries! I've written the complete code for all of that, too:
MainActivity.java
strings.xml
This seems pretty Straight Forward to me, first use HttpUrlConnection
to make call to the web service, and then handle the response as a wav file, either you can first save the file locally and then load it in a Mediaplayer
instance or you can directly load it as a live stream.
精彩评论