MCSession delegate methods are not firing when i send the media - ios11

I am doing one application using Multipeer connectivity.In that when i send the media files from one iOS to another iOS device using sendResourceURL method, destination device receiving correctly.But when i try to send from iOS 11 device to below versions, MCsession one of the delegate method is not firing
- (void) session:(MCSession *)session
didFinishReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
atURL:(NSURL *)localURL
withError:(nullable NSError *)error
{
}
At some point this method is not firing, but media file saved to temporary location.I found this using the delegate method
- (void) session:(MCSession *)session
didStartReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
withProgress:(NSProgress *)progress
{
}
So can you please help me how to resolve this.

Related

How to use connectionDidFinishDownloading:destinationURL: and connectionDidFinishLoading:

I have implemented both the NSURLConnectionDownloadDelegate, NSURLConnectionDataDelegate delegate methods as given below.
The problem is that after connection:didReceiveResponse: , connectionDidFinishDownloading:destinationURL: is called but not connectionDidFinishLoading: Even connection:didReceiveData: is not called.
When I comment the NSURLConnectionDownloadDelegate methods, the other three are called without any issues.
I have a NSURLConnections which gets JSON from server. The NSURLConnectionDataDownloading delegate methods are used by newsstand to download issues.
How do i manage this?
Here are all the delegate methods than I am implementing
- (void)connection:(NSURLConnection *)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes {
}
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL {
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
}
Here is my .h file
#interface FirstTopViewController : UIViewController <NSURLConnectionDownloadDelegate, NSURLConnectionDataDelegate, NSURLConnectionDelegate, UITableViewDataSource, UITableViewDelegate>
This is how I am connecting to server to get JSON
[[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
This is the code for downloading an issue if needed
NSURLRequest *urlReq = [NSURLRequest requestWithURL:myURL];
NKAssetDownload *asset = [currentIssue addAssetWithRequest:urlReq];
[asset downloadWithDelegate:self];
The problem is with the call to get JSON from server. Issue downloading works fine.
NSURLConnectionDataDelegate define delegate methods used for loading data to memory.
NSURLConnectionDownloadDelegate: delegate methods used to perform resource downloads directly to a disk file.
Then if you implemented connectionDidFinishDownloading:destinationURL: in your delegate. That will inform NSURLConnection you want to download the data to a disk file other than to memory as NSData. The
NSURLConnectionDataDelegate method won't get called. If you eliminate connectionDidFinishDownloading:destinationURL: from your delegate class implementation, connection:DidReceiveData: will get called instead.
For your case, implement two helper delegates for different usage.
When you want to get your JSON data in -connection:didReceiveData:, you need to set the delegate to an object which implements NSURLConnectionDataDelegate; when you want to download an issue to a file, the delegate needs to be an object that implements NSURLConnectionDownloadDelegate. A single class can't do both at once.
This is not explained very well in the NSURLConnection docs, but the comments in NSURLConnection.h make it a little more explicit:
An NSURLConnection may be used for loading of resource data
directly to memory, in which case an
NSURLConnectionDataDelegate should be supplied, or for
downloading of resource data directly to a file, in which case
an NSURLConnectionDownloadDelegate is used. The delegate is
retained by the NSURLConnection until a terminal condition is
encountered. These two delegates are logically subclasses of
the base protocol, NSURLConnectionDelegate.

OutOfMemoryException while bulk data processing with WCF RIA & WF4

I have an existing Silverlight 5 application. I'm adding a page to it to allow users to process mass updates to data in a 3rd party database system. The application currently uses WCF RIA services to communicate to the 3rd party system via SOAP. The functionality of the update is contained in a Workflow 4 application I created and is referenced as an assembly on the server-side of the SL application. Lastly, the application is hosted right now in my local instance of IIS 7.5 running on Windows 7; I'm also debugging with IIS, not the VS dev server.
At the basic level, the application functions as follows:
Select text file
Click "Start" button
Event handler creates an instance of a user-defined Type that keeps track of the batch
Event handler creates a new BackgroundWorker instance and wires up handlers for the DoWork, ProgressChanged, and RunWorkerCompleted events
Event handler calls RunWorkerAsync()
Here's the shortened code for the DoWork event handler, since that's where the majority of the work is done.
private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
{
var worker = sender as BackgroundWorker;
// Iterate through each record of data file and call the 'UpdateAddress' function
// of the AddressDomainService which, in turn, executes the Workflow
foreach (var item in batchProcess.FileData)
{
// Check if operation has been cancelled
if (worker.CancellationPending)
{
doWorkEventArgs.Cancel = true;
break;
}
. . .
// Invoke THINKComm.CustomerAddressUpdate Workflow via AddressContext
var invokeOp = _addressDomainContext.UpdateAddress(activityData);
// 'activityData' is an instance of Dictionary<string, string>
invokeOp.Completed += (o, args) => InvokeOpOnCompleted(o, args, batchProcess);
}
}
The handlers for the ProgressChanged and RunWorkerCompleted events, as well as the Completed event of the InvokeOperation instance all, for the most part, update a part of the UI. If you think posting any of that code would be helpful, I'd be happy to update the post.
Speaking of UI, the parts that are updated by the event handlers are two ProgressBar controls - one that tracks the records as they're read from the file and a second one that tracks the records as the update has taken place on the 3rd party database.
Getting to the actual problem...
I've processed files of 10, 100, and 1,000 records with no problem. I then attempted to process a complete file containing ~15,000 records (or 1,907KB of data). The process starts and I can see in the debugger output that the Workflow is being executed. About a quarter of the way through or so, I get an OutOfMemoryException. Here's the stack trace:
at System.ServiceModel.DomainServices.Client.WebDomainClient`1.BeginInvokeCore(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainClient.BeginInvoke(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainContext.InvokeOperation(String operationName, Type returnType, IDictionary`2 parameters, Boolean hasSideEffects, Action`1 callback, Object userState)
at THINKImportSystem.Web.Address.AddressDomainContext.UpdateAddress(Dictionary`2 activityData)
at THINKImportSystem.BatchProcessPage.BwOnDoWork(Object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
at THINKImportSystem.BatchProcessPage.<>c__DisplayClass10.<StartButtonClick>b__6(Object s, DoWorkEventArgs args)
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRun(Object argument)
Then, the JIT debugger pops up with an error of Unhandled Error in Silverlight Application Code:4004 with a message of System.ServiceModel.DomainServices.Client.DomainOperationException: Invoke operation 'UpdateAddress' failed. Error HRESULT E_FAIL has been returned from a call to a COM component.
I should mention that, sometimes, I get the JIT debugger first. I see in the Debug output that threads are still exiting, and then about 10 or 20 seconds later, the VS debugger pops up with the out of memory exception.
My best guess is that, objects somewhere (maybe related to the DomainService?) aren't being released and therefore, memory usage is building. From what I understand, IIS places restrictions on the amount of memory an application can use, but I can't tell if that's the case here or not.
I was thinking that, each time a record in the file is processed, the objects related to it's processing would be released and therefore overall memory usage would be pretty low. But obviously I'm not understanding how everything is being executed!
I was also wondering if using the TPL as opposed to BackgroundWorker would make a difference?

Windows Phone 7 Push Notifications Not Showing Up On My Phone

UPDATE: The plot thickens. I changed my channel name and it is suddenly working (which means it wasn't a problem with my push service, since I'm getting the same HTTP response from the Microsoft Push Notification server).
To me, however, this is not a solution. How will I be able to test this and KNOW my users are getting their push notifications if I'm getting the same response when it's not working as I do when it is?
[ORIGINAL POST]
I've been trying to get push notifications sent to my Windows Phone 7 device, but I'm having very big problems that I can't find any answers for. I'll start with the c# code.
I set up push notifications using the following C# code.
private HttpNotificationChannel channel;
private static string PUSH_CHANNEL = "MySpecialPushChannel";
private Uri PushUri = null;
private bool IsPushRegistered = false;
public void StartPushSubscription()
{
try
{
channel = HttpNotificationChannel.Find(PUSH_CHANNEL);
}
catch
{}
if (channel != null)
{
PushUri = channel.ChannelUri;
if (!channel.IsShellTileBound)
channel.BindToShellTile();
}
else
{
channel = new HttpNotificationChannel(PUSH_CHANNEL);
channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(channel_ChannelUriUpdated);
channel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(channel_HttpNotificationReceived);
channel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(channel_ErrorOccurred);
try
{
channel.Open();
channel.BindToShellTile();
}
catch (Exception err)
{
channel = null;
IsPushRegistered = false;
// Code to try again
}
}
}
void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
PushUri = e.ChannelUri;
IsPushRegistered = true;
}
I'm following the standard WP7 push structure:
Find the HttpNotificationChannel (or start a new one)
Register event handler to get the push notification uri back
Open the channel
Bind to the tile
Handle the channel Uri (which we send to our service to await the happy day when we send the push notification
OK... so far so good. No errors, I get my Uri, send it to my service just fine. I pin my app to the start screen and my service sends a push request to the Uri (sending just the count so that I get a little push count number in the upper right hand corner). I get back an HTTP 200 status with the following:
DeviceConnectionStatus => Connected
NotificationStatus => Received
SubscriptionStatus => Active
And then... nothing. No push status shows up on my app. I've now tried it on my device, in the emulator, on another device, and with multiple servers and the result is always the same. Everything looks like it is working except for the fact that it doesn't work.
To me, however, this is not a solution. How will I be able to test this and KNOW my users are getting their push notifications if I'm getting the same response when it's not working as I do when it is?
The answer is, you can't. It's a limitation of how WP7 handles notifications.
For structured notifications like Tile and Toast, if you get the Connected/Active/Received/200 response, then you can know that MPNS accepted your notification request. However, this does not mean that you have sent a valid XML payload.
The component that handles parsing XML is the Push Client, the process running on the phone that accepts push notifications and deals them out to appropriate applications, displays the toast, etc.
If you have sent invalid XML, there is absolutely no indication that you've done so. At most, if you try to send the notification again to that same push channel URI, you'll get a 404 in response. Apparently getting an invalid XML payload for a specific application makes that application's push channel close, requiring you to go through the whole procedure again.
I've discovered this while debugging with our server team, and through trying to get the phone to display an alternate live tile. The only advice I can offer you is to quadruple-check your XML.
You will get errors in your error event handler for your push notification channel for Toast notifications that have invalid XML, since you are able to send/receive toast notifications while the application is active.
If anyone from Microsoft is reading this, PLEASE provide more thorough documentation on possible error states in the push notification system. We also need an event handler for Tile notifications, or at least allow us to receive tile notifications while the app is in the foreground and fire the notification channel error event so that we can be aware that our XML payload is invalid.
Especially if your web service isn't built with WCF, .NET, Azure, and whatever, working with Push Notifications on WP7 is like wandering blind.
Documentation for an exception message reading "InvalidOperationException(Failed to open channel)" should not read: "This exception is raised when the notification channel failed to open. Try opening the notification channel again." (reference)
are you getting the URL from each device? you need to get a URL from the push notification sevice for each device everytime your device connects,
when it does you need to find a way of retrieving the url from each client,
once you do that and your still not receiving push notifications then I would write to microsoft to see if they can see anything to do with the push notifications

Runtime debugging tips for Windows Service?

I have a Windows Service that monitors a COM port connected to a vendors hardware. This is a very busy piece of hardware that is constantly polling other devices on the wire (this is a twisted-pair RS485 "network"). My software needs to emulate X number of hardware devices on this wire, so I've got a multi-threaded thing going on with a multi-tiered state machine to keep track of where the communications protocol is at any moment.
Problem is with a Windows Service (this is my first one, BTW) is that you need some debugging to let you know if stuff is working properly. When I was first developing this state machine/multi-thread code I had a windows form with a RichTextBox that displayed the ASCII chars going back-n-forth on the line. Seems like I can't really have that GUI niceness with a service. I tried opening a form in the service via another program that sent the service messages that are received via the OnCustomCommand() handler but it didn't seem to work. I had "Allow service to interact with desktop" checked and everything. I was using the Show() and Hide() methods of my debug form.
I guess I don't need to see all of the individual characters going on the line but man that sure would be nice (I think I really need to see them :-) ). So does anyone have any crazy ideas that could help me out? I don't want to bog down the system with some IPC that isn't meant for the voluminous amount of data that is sure to come through. It will only be very short-term debugging though, just confirmation that the program, the RS485-to-USB dongle, and hardware is all working.
Use OutputDebugString to write to the debugging buffer and then use DebugView to watch it. If you're running on Windows XP or earlier, then you can use PortMon to see the raw bytes going through the serial port. The advantage over a log file is that there's very little overhead, particularly when you're not watching it. You can even run DebugView from another machine and monitor your service remotely.
I dunno if it will work for you, but I always build my services with a extra Main that build them as console app to get debug output.
Edit:
Some example:
class Worker : ServiceBase
{
#if(RELEASE)
/// <summary>
/// The Main Thread where the Service is Run.
/// </summary>
static void Main()
{
ServiceBase.Run(new Worker());
}
#endif
#if(DEBUG)
public static void Main(String[] args)
{
Worker worker = new Worker();
worker.OnStart(null);
Console.ReadLine();
worker.OnStop();
}
#endif
// Other Service code
}
You could write the output to a log file and then use another application to watch that file. This question about "tail" outlines several options for watching log files with windows.
What I usually do when working on a Windows Service is to create it so that it can be run either as a service, or as a plain old command-line application. You can easily check whether you are running as a service by checking Environment.UserInteractive. If this property is true, then you are running from the command line. If the property is false, then you are running as a service. Add this code to Program.cs, and use it where you would normally call ServiceBase.Run(servicesToRun)
/// <summary>Runs the provided service classes.</summary>
/// <param name="servicesToRun">The service classes to run.</param>
/// <param name="args">The command-line arguments to pass to the service classes.</param>
private static void RunServices(IEnumerable<ServiceBase> servicesToRun, IEnumerable args)
{
var serviceBaseType = typeof(ServiceBase);
var onStartMethod = serviceBaseType.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStartMethod.Invoke(service, new object[] { args });
Console.WriteLine(service.ServiceName + " started.");
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
var onStopMethod = serviceBaseType.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
foreach (var service in servicesToRun)
{
onStopMethod.Invoke(service, null);
Console.WriteLine(service.ServiceName + " stopped.");
}
}
Now you can debug your service, set breakpoints, anything you want. When you run your application, you'll get a console window, appropriate for displaying console messages, and it will stay open until you hit a key.
I'm answering my own question here. I tried a couple of suggestions here but here's what I ended up doing...
I created a Windows Form application with a single Button and RichTextBox. This application constructed a NamedPipeServerStream on it's end. The Button's job was to send either "debug on" (command 128) or "debug off" (129) to the Windows Service. The initial value was "debug off". When the button was clicked, a command of 128 was sent to the Windows Service to turn debugging on. In the Windows Service this triggered an internal variable to be true, plus it connected to the Form application with a NamedPipeClientStream and started sending characters with a BinaryWriter as they were received or sent on the COM port. On the Form side, a BackgroundWorker was created to WaitForConnection() on the pipe. When it got a connection, a BinaryReader.ReadString() was used to read the data off of the pipe and shoot it to the RichTextBox.
I'm almost there. I'm breaking my pipe when I click the debug button again and a subsequent click doesn't correctly redo the pipe. All in all I'm happy with it. I can post any code if anyone is interested. Thanks for the responses!

How to register own protocol using the WebBrowser control?

In a WP7 Silverlight application with a WebBrowser control I want to use an own protocol like "myttp://" to deliver some local content. I can't use Navigate() to an IsolatedStrorage because some content will by created on demand. For the same reason NavigateToString() is also not usable for me.
I tried to register a WebRequestCreator descend for my MYTP protocol
myCreator = new MyRequestCreator();
WebRequest.RegisterPrefix("mytp://", myCreator);
but it isn't called from the browser control if I navigate to "mytp://test.html".
If I create a WebRequest via code
WebRequest request;
request = WebRequest.Create("mytp://test.html");`
everythings works fine.
Any suggestions what is wrong or how to do it?
The WebBrowser control will use the Windows Phone Internet Explorer Browser's HTTP stack to statisfy web requests. This HTTP stack is entirely separate from the Client HTTP stack being used by the application. Hence the browser does not see your protocol at all.
I agree with AnthonyWJones words, though I dont know, what exactly he meant by "Browser HTTP stack".
The standard Silverlight's "access to Browser's stack" (used to handle sessions etc) in form of System.Net.Browser.WebRequestCreator.BrowserHttp httprequest factory (versus the "normal/aside" System.Net.Browser.WebRequestCreator.ClientHttp factory) is actually available to the application code in WP7. It is hidden from the SDK, but available on the device and with small effort, the application can use it, for example, to have its emitted cookies in sync with the Browser's cache. For description, please see my humble other post
However, while using that factory and having all your session/cookies/userauth handling within those connections in sync with the WebBrowser, despite being very similar to the ClientHttp factory, you find (at least in 7.0 and 7.1 versions) that it is completely ignorant of any custom prefixes. Trying to open anything with this factory results in (WP7 v. Mango 7.1):
A first chance exception of type 'System.Net.ProtocolViolationException' occurred in System.Windows.dll
at System.Net.Browser.BrowserHttpWebRequest.InternalBeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Browser.AsyncHelper.BeginOnUI(BeginMethod beginMethod, AsyncCallback callback, Object state)
at System.Net.Browser.BrowserHttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at MyApp.MyPage..ctor()
relevant code snippet of the MyPage:
public class WRC : IWebRequestCreate { public WebRequest Create(Uri uri) { return null;/*BREAKPOINT1*/ } }
WebRequest.RegisterPrefix("js://", new WRC()); // register the above handler
brwHttp = (IWebRequestCreate)typeof(System.Net.Browser.WebRequestCreator).GetProperty("BrowserHttp").GetValue(null, null);
var tmp = brwHttp.Create(new Uri("js://blah.blah.blah"));
var yyy = tmp.BeginGetResponse(callback, "wtf");
var response = tmp.EndGetResponse(yyy); /*BREAKPOINT2*/
var zzz = tmp.BeginGetRequestStream(callback, "wtf"); /*<---EXCEPTION*/
var stream = tmp.EndGetRequestStream(zzz); /*BREAKPOINT3*/
Execution results:
breakpoint1 never hit
breakpoint2 allows to see that "response" is NULL
breakpoint3 never hit due to the exception pasted above
My conclusion is, that the Silverlight Browser's stack is hardcoded to use some builtin set of prefixes, and all other prefixes are ignored/throw ProtocolViolation. My guess is, that in WP7 (7.0, 7.1) they are actually hardcoded to use http since my custom "js://" was passed to a BrowserHttpWebRequest.InternalBeginGetRequestStream as it's visible on the stacktrace :)
That confirms what Anthony had written - no way of having custom protocol handlers to work gracefully with the Silverlight's Browser Stack API.
However, I cannot agree with that the WebBrowser uses this connection factory. While is it true that the hidden factory is called BrowserHttp, and is true that it shares some per-user or per-session settings with the webbrowser, everything I try tens to indicate that the WebBrowser component uses yet completly other factory for its connections, and quite probably it is some native one. As an argument for that, I can only provide that I was able to successfully replace the original BrowserHttp factory with my simple custom implementation of it (both on the emulator and the phone), and with at least 6 webbrowsers in my current app, it wasn't used at all, not even once! (neither on the emulator, nor phone)

Resources