I'm using background file transfer and background audio player.
in the TransferStatusChanged event i save the file to the isolated storage then play it with the audio player,
It works fine if the application is active and i want to do the same if the application is not active.
In WP8.0 it isn't possible as your TransferStatusChanged is in your App process which is stopped when you navigate away from it:
When the user navigates forward, away from an app, after the Deactivated event is raised, the operating system will attempt to put the app into a dormant state. In this state, all of the application’s threads are stopped and no processing takes place, but the application remains intact in memory.
You can make it work under LockScreen by disabling IdleDetection but it won't work when your App is put into dormant/tombstoned state.
You may consider to start playing when you activate the App or put some logic in BAP where you can check for example upon TrackChange if the file was downloaded and then play it.
edit
thanks to #Romasz suggestion of use empty track to play while the file complete downloading
then in TrackChange i check if the file downloaded and remove it from the download queue -this can be done in the audio background- things work fine now. here is some code
private AudioTrack GetNextTrack(bool isStart = false)
{
AudioTrack track = null;
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isStart)
{
currentSongIndex = -1;
}
currentSongIndex++;
if (currentSongIndex == _ProgressList.Count())
{
//currentSongIndex = 0;
return track;
}
if (ISF.FileExists("shared/transfers/" + _ProgressList[currentSongIndex].FileName))
{
var request = requests.Where(it => it.Key == _ProgressList[currentSongIndex].FileName).FirstOrDefault().Value;
if (request != null)
{
bool isDone = ProcessTransfer(request, _ProgressList[currentSongIndex].Directory);
if(!isDone )
{
if(request.BytesReceived > LastDownloadedSize)
{
NumberOfTrialsToLoadNextTrack = 0;
LastDownloadedSize = request.BytesReceived;
}
else
{
++NumberOfTrialsToLoadNextTrack;
}
}
}
}
else
{
++NumberOfTrialsToLoadNextTrack;
}
if (ISF.FileExists(_ProgressList[currentSongIndex].Directory+_ProgressList[currentSongIndex].FileName))
{
track = playList[currentSongIndex];
NumberOfTrialsToLoadNextTrack = 0;
LastDownloadedSize = 0;
}
else
{
currentSongIndex--;
if (NumberOfTrialsToLoadNextTrack < 10)
{
track = new AudioTrack(new Uri("halfsec.mp3", UriKind.Relative),
"empty",
"empty",
"empty",
null);
}
}
}
return track;
}
private bool ProcessTransfer(BackgroundTransferRequest transfer, string directory = "")
{
bool isDone = false;
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
{
RemoveTransferRequest(transfer.RequestId);
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
string filename = transfer.Tag;
System.Diagnostics.Debug.WriteLine(directory + filename);
if (isoStore.FileExists(directory + filename))
{
isoStore.DeleteFile(directory + filename);
}
if (isoStore.FileExists(transfer.DownloadLocation.OriginalString))
{
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, directory + filename);
}
}
isDone = true;
}
else
{
RemoveTransferRequest(transfer.RequestId);
if (transfer.TransferError != null)
{
}
}
break;
}
return isDone;
// NotifyComplete();
}
private void RemoveTransferRequest(string transferID)
{
// Use Find to retrieve the transfer request with the specified ID.
BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);
// try to remove the transfer from the background transfer service.
try
{
BackgroundTransferService.Remove(transferToRemove);
}
catch (Exception)
{
}
}
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackEnded:
player.Track = GetNextTrack();
break;
case PlayState.TrackReady:
player.Play();
break;
case PlayState.Shutdown:
// TODO: Handle the shutdown state here (e.g. save state)
break;
case PlayState.Unknown:
break;
case PlayState.Stopped:
break;
case PlayState.Paused:
break;
case PlayState.Playing:
break;
case PlayState.BufferingStarted:
break;
case PlayState.BufferingStopped:
break;
case PlayState.Rewinding:
break;
case PlayState.FastForwarding:
break;
}
NotifyComplete();
}
this code in the AudioPlayer class, the files added to the download queue in the xaml.cs normally
Related
Using Websockets, I am able to use 1 computer and 1 kinect v2.0 to generate JSON objects of the joints x,y, and z coordinates in real-time. The next steps is to have this data transferred to another computer, using possibly TCP/IP network. My question is to anyone who knows how this is done. Having this data transferred to another computer.
Output that needs to be transferred to another computer in real-time
namespace WebSockets.Server
{
class Program
{
// Store the subscribed clients.
static List<IWebSocketConnection> clients = new List<IWebSocketConnection>();
// Initialize the WebSocket server connection.
static Body[] bodies = new Body[6];
//static KinectSensor kinectSensor = null;
static CoordinateMapper _coordinateMapper;
static Mode _mode = Mode.Color;
static void Main(string[] args)
{
//const string SkeletonStreamName = "skeleton";
//SkeletonStreamMessage skeletonStreamMessage;// = new SkeletonStreamMessage { stream = SkeletonStreamName };
KinectSensor kinectSensor = KinectSensor.GetDefault();
BodyFrameReader bodyFrameReader = null;
bodyFrameReader = kinectSensor.BodyFrameSource.OpenReader();
ColorFrameReader colorFrameReader = null;
colorFrameReader = kinectSensor.ColorFrameSource.OpenReader();
_coordinateMapper = kinectSensor.CoordinateMapper;
kinectSensor.Open();
WebSocketServer server = new WebSocketServer("ws://localhost:8001");
server.Start(socket =>
{
socket.OnOpen = () =>
{
// Add the incoming connection to our list.
clients.Add(socket);
};
socket.OnClose = () =>
{
// Remove the disconnected client from the list.
clients.Remove(socket);
};
socket.OnMessage = message =>
{
if (message == "get-video")
{
int NUMBER_OF_FRAMES = new DirectoryInfo("Video").GetFiles().Length;
// Send the video as a list of consecutive images.
for (int index = 0; index < NUMBER_OF_FRAMES; index++)
{
foreach (var client in clients)
{
string path = "Video/" + index + ".jpg";
byte[] image = ImageUtil.ToByteArray(path);
client.Send(image);
}
// We send 30 frames per second, so sleep for 34 milliseconds.
System.Threading.Thread.Sleep(270);
}
}
else if (message == "get-bodies")
{
if (kinectSensor.IsOpen)
{
if (bodyFrameReader != null)
{
bodyFrameReader.FrameArrived += bodyFrameReader_FrameArrived;
}
}
}
else if (message == "get-color")
{
if (kinectSensor.IsOpen)
{
if (colorFrameReader != null)
{
colorFrameReader.FrameArrived += colorFrameReader_FrameArrived;
}
}
}
};
});
// Wait for a key press to close...
Console.ReadLine();
kinectSensor.Close();
}
private static void colorFrameReader_FrameArrived(object sender, ColorFrameArrivedEventArgs e)
{
//throw new NotImplementedException();
using (ColorFrame colorFrame = e.FrameReference.AcquireFrame()) {
if (colorFrame != null) {
var blob = colorFrame.Serialize();
foreach (var client in clients)
{
if (blob != null)
{
client.Send(blob);
Console.WriteLine("After color Blob sent");
}
}
}
}
}
private static void bodyFrameReader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
//throw new NotImplementedException();
bool dataReceived = false;
using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
{
if (bodyFrame != null)
{
if (bodies == null)
{
bodies = new Body[bodyFrame.BodyCount];
}
// The first time GetAndRefreshBodyData is called, Kinect will allocate each Body in the array.
// As long as those body objects are not disposed and not set to null in the array,
// those body objects will be re-used.
bodyFrame.GetAndRefreshBodyData(bodies);
dataReceived = true;
}
}
if (dataReceived)
{
foreach (var client in clients)
{
var users = bodies.Where(s => s.IsTracked.Equals(true)).ToList();
if (users.Count>0){
string json = users.Serialize(_coordinateMapper, _mode);
Console.WriteLine("jsonstring: " + json);
Console.WriteLine("After body serialization and to send");
}
}
}
}
}
}
Try changing it from
WebSocketServer server = new WebSocketServer("ws://localhost:8001");
to
WebSocketServer server = new WebSocketServer(" ws://192.168.X.X:8001");
on the client end. Enter the IP address of the client computer and make sure both server and client are on the same network.
I need to run test in two browsers with the same view but logged with different users. As the server is changing the cookie and logging out the first user because of the shared cookie between multiple windows in Chrome I cannot run the test. So, I wonder if it is possible to run a Chrome normal instance and an incognito one simultaneously.
Another option is to run a Chrome and a Firefox instance but I need to control what to do with each browser.
You can use two browsers. Run a script to find out which browser you are in and then have different users to log based on that.
First, get the browser, here is a script for that:
browser.getCapabilities()
.then(function(s) {
var platform = s.caps_.platform,
browserName = s.caps_.browserName,
browserVersion = s.caps_.version,
shortVersion = browserVersion.split('.')[0],
ie = /i.*explore/.test(browserName),
ff = /firefox/.test(browserName),
ch = /chrome/.test(browserName),
sa = /safari/.test(browserName),
shortName;
if (ie) {
shortName = 'ie';
} else if (ff) {
shortName = 'ff';
} else if (ch) {
shortName = 'ch';
} else if (sa) {
shortName = 'sa';
} else {
throw new Exception('Unsupported browser: '+ browserName);
}
// Returns one of these: ['ch', 'ff', 'sa', 'ie']
browser.getShortBrowserName = function() {
return shortName;
};
// Returns one of these: ['ch33', 'ff27', 'sa7', 'ie11', 'ie10', 'ie9']
browser.getShortNameVersionAll = function() {
return shortName + shortVersion;
};
// Returns one of these: ['ch', 'ff', 'sa', 'ie11', 'ie10', 'ie9']
browser.getShortNameVersion = function() {
if (ie) {
return shortName + shortVersion;
} else {
return shortName;
}
};
// Return if current browser is IE, optionally specifying if it is a particular IE version
browser.isIE = function(ver) {
if (!ver) {
return ie;
} else {
return ie && ver.toString() === shortVersion;
}
};
browser.isSafari = function() {
return sa;
};
browser.isFirefox = function() {
return ff;
};
// Return if current browser is Chrome, optionally specifying if it is a particular Chrome version
browser.isChrome = function(ver) {
if (!ver) {
return ch;
} else {
return ch && ver.toString() === shortVersion;
}
};
then you need a function to know which user to log in:
global.getUserAndPassword = function getUser() {
var rv_user = process.env.PROTRACTOR_USER;
if (browser.isFireFox() && typeof process.env.PROTRACTOR_USER_2 !== 'undefined') {
rv_user = process.env.PROTRACTOR_USER_2;
}
return [rv_user, process.env.PROTRACTOR_PASSWORD];
};
and then a login function:
global.loginFn = function loginFn() {
var user_and_pass = getUserAndPassword();
username.sendKeys(user_and_pass[0]);
password.sendKeys(user_and_pass[1]);
login.click();
};
I am building a WP8 app that downloads images using HttpClient in a background task. My problem is that some images are not downloaded no matter how much time I wait for them to finish. The image sizes are a few megabytes at maximum.
The code I use to download images:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// 12MB max images
client.Timeout = TimeSpan.FromSeconds(5);
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 2;
//client.Timeout = TimeSpan.FromSeconds(5);
byte[] image_byte_arr;
try
{
/* var requestMessage = new HttpRequestMessage( HttpMethod.Get, image_url );
var responseMessage = await client.SendAsync((requestMessage));
// byte array of image
image_byte_arr = await responseMessage.Content.ReadAsByteArrayAsync();
*/
// byte array of image
image_byte_arr = await client.GetByteArrayAsync(image_url);
}
// Could not download
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
This is an example image that fails to download: https://upload.wikimedia.org/wikipedia/commons/9/95/Tracy_Caldwell_Dyson_in_Cupola_ISS.jpg
In my experience all wikimedia images fail to download for some reason.
I see no way of tracking download progress using HttpClient. Is there a way to do so?
Edit: It seems that setting the timeout does not have any function. The HttpRequestException is not thrown after 5 seconds.
Edit2: I tried a different approach, the one that anonshankar suggested. With that method the code would get stuck at the line:
byte[] img = response.Content.ReadAsByteArrayAsync();
So the HttpResponse arrives, but somehow the bytes could not be read out, no matter how much time I gave it. How could this even happen? The hard part is getting the response, reading out the bytes should be simple.
Again, this only happens with some images, most of them downloads correctly. One example is mentioned above.
I have modified my image downloader code, so that it times out after a few seconds. Here is my final code:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// prevent running out of memory
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 3;
byte[] image_byte_arr = null;
using (CancellationTokenSource cts = new CancellationTokenSource())
{
var task = Task.Factory.StartNew(() =>
{
try
{
image_byte_arr = client.GetByteArrayAsync(image_url).Result;
}
catch (AggregateException X)// Handling read errors, usually image is too big
{
Console.WriteLine(X.Message);
foreach (var v in X.InnerExceptions)
Console.WriteLine(v.Message);
image_byte_arr = null;
}
}, cts.Token);
bool finished_in_time = task.Wait(TimeSpan.FromSeconds(5));
if (!finished_in_time)// Timeout
{
cts.Cancel();
task.Wait();
return false;
}
else if (image_byte_arr == null)// Read error
{
return false;
}
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
Any improvement suggestions are welcome, and I still don't understand why does the method HttpContent.ReadAsByteArrayAsync() gets stuck.
Just try out this snippet which worked for me.
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("give the url");
byte[] img = response.Content.ReadAsByteArray();
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(randomAccessStream.GetOutputStreamAt(0));
writer.WriteBytes(img);
await writer.StoreAsync();
BitmapImage b = new BitmapImage();
b.SetSource(randomAccessStream);
pic.Source = b; //(pic is an `<Image>` defined in the `XAML`
Hope it helps!
i found this example(https://developer.nokia.com/Community/Wiki/Windows_Phone_8_communicating_with_Arduino_using_Bluetooth) in my research to develop a bluetooth console to windows phone 8. This example work very well, except for the TERMINATE function. When i call TERMINATE function, the ReceiveMessages function still trying receive data, but there is no more socket available and it generate a system.exception. I tried a lot of workaround, but i dont have enough experience with C#, this is my first APP. Anyone know how can i workaround this situation or have a better example?
i did only 1 modificiation:
private async void AppToDevice()
{
if (!connected)
{
ConnectAppToDeviceButton.Content = "Connecting...";
PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
var pairedDevices = await PeerFinder.FindAllPeersAsync();
if (pairedDevices.Count == 0)
{
Debug.WriteLine("No paired devices were found.");
}
else
{
foreach (var pairedDevice in pairedDevices)
{
if (pairedDevice.DisplayName == DeviceName.Text)
{
connectionManager.Connect(pairedDevice.HostName);
ConnectAppToDeviceButton.Content = "Disconnect";
DeviceName.IsReadOnly = true;
//ConnectAppToDeviceButton.IsEnabled = false;
continue;
}
}
}
}
else
{
connectionManager.Terminate();
ConnectAppToDeviceButton.Content = "Connect";
}
}
I found a solution here:
WinRT: DataReader.LoadAsync Exception with StreamSocket TCP
I did only a few modifications:
public void Terminate()
{
try
{
if (socket != null)
{
taskLoadLength.Cancel();
taskLoadLength.Close();
taskLoadMessage.Cancel();
taskLoadMessage.Close();
socket.Dispose();
dataReadWorker.CancelAsync();
dataReader.Dispose();
dataWriter.Dispose();
isInicialized = false;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
private void ReceiveMessages(object sender, DoWorkEventArgs ev)
{
while (true)
{
try
{
// Read first byte (length of the subsequent message, 255 or less).
//uint sizeFieldCount = await dataReader.LoadAsync(1);
taskLoadLength = dataReader.LoadAsync(1);
taskLoadLength.AsTask().Wait();
uint sizeFieldCount = taskLoadLength.GetResults();
if (sizeFieldCount != 1)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the message.
uint messageLength = dataReader.ReadByte();
taskLoadMessage = dataReader.LoadAsync(messageLength);
taskLoadMessage.AsTask().Wait();
uint actualMessageLength = taskLoadMessage.GetResults();
//uint actualMessageLength = await dataReader.LoadAsync(messageLength);
if (messageLength != actualMessageLength)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the message and process it.
string message = dataReader.ReadString(actualMessageLength);
MessageReceived(message);
}
catch (AggregateException ae)
{
MessageBox.Show(ae.Message);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}
Below code throws net.rim.device.api.io.file.FileIOException: File system out of resources this exception.
Can anyone tell me how it happens?
public Bitmap loadIconFromSDcard(int index) {
FileConnection fcon = null;
Bitmap icon = null;
InputStream is=null;
try {
fcon = (FileConnection) Connector.open(Shikshapatri.filepath + "i"
+ index + ".jpg", Connector.READ);
if (fcon.exists()) {
byte[] content = new byte[(int) fcon.fileSize()];
int readOffset = 0;
int readBytes = 0;
int bytesToRead = content.length - readOffset;
is = fcon.openInputStream();
while (bytesToRead > 0) {
readBytes = is.read(content, readOffset, bytesToRead);
if (readBytes < 0) {
break;
}
readOffset += readBytes;
bytesToRead -= readBytes;
}
EncodedImage image = EncodedImage.createEncodedImage(content,
0, content.length);
image = resizeImage(image, 360, 450);
icon = image.getBitmap();
}
} catch (Exception e) {
System.out.println("Error:" + e.toString());
} finally {
// Close the connections
try {
if (fcon != null)
fcon.close();
} catch (Exception e) {
}
try {
if (is != null)
is.close();
is = null;
} catch (Exception e) {
}
}
return icon;
}
Thanks in advance...
Check this BB dev forum post - http://supportforums.blackberry.com/t5/Java-Development/File-System-Out-of-Resources/m-p/105597#M11927
Basically you should guaranteedly close all connections/streams as soon as you don't need them, because there is a limited number of connection (be it a file connection or http connection) handles in OS. If you execute several loadIconFromSDcard() calls at the same time (from different threads) consider redesign the code to call them sequentially.
UPDATE:
To avoid errors while reading the content just use the following:
byte[] content = IOUtilities.streamToBytes(is);
And since you don't need file connection and input stream any longer just close them right after reading the content (before creating EncodedImage):
is.close();
is = null; // let the finally block know there is no need to try closing it
fcon.close();
fcon = null; // let the finally block know there is no need to try closing it
Minor points:
Also in the finally block it is worth set fcon = null; explicitly after you close it, I believe this can help old JVMs (BB uses Java 1.3 - rather old one) to decide quicker that the object is ready to be garbage collected.
I also believe that the order you close streams in the finally block may be important - I'd change to close is first and then fcon.