Multipeer Connectivity - State Not Changing - iphone

I'm working on an app the uses the Multipeer Conectivity Framework. So far everything is going great, I've implemented programmatic browsing and invitations.
My issue is when the user accepts the invitation the Browser is not receiving the state change - thereby not creating the session.
This is the advertiser did receive invitation method i have created using an action sheet integrated with blocks.
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser
didReceiveInvitationFromPeer:(MCPeerID *)peerID
withContext:(NSData *)context
invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler
{
[UIActionSheet showInView:self.view
withTitle:[[NSString alloc]initWithFormat:#"%# would like to share %# information with you.",peerID.displayName, (NSString *)context]
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Deny"
otherButtonTitles:#[#"Accept"]
tapBlock:^(UIActionSheet *actionSheet, NSInteger buttonIndex) {
NSLog(#"%i",buttonIndex==1?true:false);
MCSession *newSession=[[MCSession alloc]initWithPeer:[[MCPeerID alloc] initWithDisplayName:#"CRAP23456"]];
[newSession setDelegate: self];
NSLog(#"button index %i ",buttonIndex==1?true:false);
invitationHandler(buttonIndex==1?YES:NO,newSession);
}];
}
The above method is being called and the invitation handler is returning the correct value.
My implementation from the browser side is very simple - and this is the method that should be called when the user either accepts/declines the method. However, it's only being called when the user declines the invite:
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state
{
NSLog(#"%d",state);
NSLog(#"%ld",(long)MCSessionStateConnected);
}
Thanks in advance.
James.

I hope one of these will help:
Implement session:didReceiveCertificate:fromPeer:certificateHandler:
I read here that this is necessary.
Keep browsing and advertising between two peers a one-way deal; that is, don't accept invitations on both ends if both are browsing as well (at least don't accept an invitation and pass same session you're browsing with in invitationHandler()).
Wrap your code in the didChangeState in a block like this:
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%d",state);
NSLog(#"%ld",(long)MCSessionStateConnected);
});

I ran into this issue too. My code on the browser side looked like this:
MCSession *session = [[MCSession alloc] initWithPeer:[self peerID]];
session.delegate = self;
[browser invitePeer:peerID toSession:session withContext:nil timeout:30.0f];
The issue with this is that the browser does not retain a reference to the session and so ARC comes around and cleans it up before the other end had the opportunity to accept.
Changing it to the following fixed the issue:
_session = [[MCSession alloc] initWithPeer:[self peerID]];
_session.delegate = self;
[browser invitePeer:peerID toSession:_session withContext:nil timeout:30.0f];
.. where _session is an ivar on my class.
HTH

Related

SiriKit with VoIP call Application not working in iOS 10

I am doing VoIP call Application. There i can make call through my application. I have integrated SiriKit setup and added following code.
#pragma mark -Start Audio Call
- (void)resolveContactsForStartAudioCall:(INStartAudioCallIntent *)intent
withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion{
NSLog(#"maytest resolveContactsForStartAudioCall");
NSArray<INPerson *> *recipients = intent.contacts;
NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
if (recipients.count == 0) {
completion(#[[INPersonResolutionResult needsValue]]);
return;
}else if(recipients.count==1){
[resolutionResults addObject:[INPersonResolutionResult successWithResolvedPerson:recipients.firstObject]];
}else if(recipients.count>1){
[resolutionResults addObject:[INPersonResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
}else{
[resolutionResults addObject:[INPersonResolutionResult unsupported]];
}
completion(resolutionResults);
}
- (void)confirmStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeReady userActivity:userActivity];
completion(response);
}
- (void)handleStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeContinueInApp userActivity:userActivity];
completion(response);
}
But, its not making calls through my app. Its making calls through native dialer and some times showing application not yet set up with siri.
Could anyone guide me and after make call, how to save call history.
Thanks!
I encountered this problem too!!!
I my case, it's because I'm calling Siri in Chinese!!!! It takes me a half day to figure it out!!
If I change Siri language to English and everything works just fine!
In Chinese Siri will only call through native dialer no matter how I specify the application.
I'm not sure if it happens on other languages too since I can only test those two.

Can't connect to [QBChat Instance] connect with User, in Quickblox

I am using Quickblox Api, for chat and video chat. iOS. And I am using the latest version of the API
When I try to Make a video call,
most of the times i don't get video, only audio.
i get video on both ends 1 out of 15 times.
3 out of 10 times video on one end.
very weird. I have good internet connection. connecting to chat users are receiving the call. Can seem to find out the issue.
After spending sometime to find the issue, I received and help from Quickblox Help Center.
If your face such Behavior on the API
1.Make Sure that you set Delegate Methods in viewDidLod, not view did appear or etc. For Ex:
- (void)viewDidLoad {
[super viewDidLoad];
[[QBChat instance] addDelegate:self];
[QBRTCClient.instance addDelegate:self];
[QBSettings setCarbonsEnabled:YES];
}
Use Breakpoints to find out if they are getting called, once you make or receive calls.
2.Make Sure that your Calling methods are correct. An array containing Users must not equal to currentUser.ID.
NSInteger currentUserID = [QBSession currentSession].currentUser.ID;
int count = 0;
NSNumber *currentUserIndex = nil;
for (NSNumber *opponentID in opponentsIDs) {
if ([opponentID integerValue] == currentUserID) {
currentUserIndex = #(count);
break;
}
count++;
}
if (currentUserIndex) [opponentsIDs removeObjectAtIndex:[currentUserIndex intValue]];
QBRTCSession *session = [QBRTCClient.instance createNewSessionWithOpponents:opponentsIDs
withConferenceType:QBRTCConferenceTypeVideo];
NSDictionary *userInfo = #{ #"key" : #"value" };
[session startCall:userInfo];
if (session) {
self.currentSession = session;
[self performSegueWithIdentifier:#"openDialogSeg" sender:self];
}
else {
[SVProgressHUD showErrorWithStatus:#"You should login to use chat API. Session hasn’t been created. Please try to relogin the chat."];
}
}
Check View Layout, size and width. make sure they are set correctly.

Retrieving Account Info from DBAccountInfo in Dropbox Datastore iOS API

I'm trying to get a user's display name from the Dropbox Datastore API. The documentation for iOS says that DBAccountInfo is retrieved in the background, and to use an observer.
This is what I'm trying, but I'm getting nothing back (the block never fires):
NSLog(#"Here");
//-- Log: Here --
[[DBAccountManager sharedManager] addObserver:self block:^(DBAccount *acctInfo) {
DBAccountInfo *info = acctInfo.info;
NSLog(#"Info: %#",info);
//-- Log: <nothing> --
}];
Any idea what I am doing wrong?
It looks like you're adding an observer to the DBAccountManager, which will only fire when an account is linked or unlinked.
If you want to observe when the account info changes, you should add an observer to the DBAccount. Take a look at the DBAccount.addObserver:block: documentation.
Here is the full code for anyone else that might be having trouble with this:
//Use weak reference because we are using `account` in a block
__weak DBAccount *account = [[DBAccountManager sharedManager] linkedAccount];
[account addObserver:self block:^(){
DBAccountInfo *info = account.info;
NSLog(#"Info: %#",info);
}];

Delegate functions not being called

Long time lurker, first time poster.
I'm making a ServerConnection module to make it a whole lot modular and easier but am having trouble getting the delegate called. I've seen a few more questions like this but none of the answers fixed my problem.
ServerConnection is set up as a protocol. So a ServerConnection object is created in Login.m which makes the call to the server and then add delegate methods in Login to handle if there's an error or if it's done, these are called by ServerConnection like below.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if( [self.delegate respondsToSelector:#selector(connectionDidFinish:)]) {
NSLog(#"DOES RESPOND");
[self.delegate connectionDidFinish:self];
} else {
NSLog(#"DOES NOT RESPOND");
}
self.connection = nil;
self.receivedData = nil;
}
It always "does not respond". I've tried the CFRunLoop trick (below) but it still doesn't work.
- (IBAction)processLogin:(id)sender {
// Hide the keyboard
[sender resignFirstResponder];
// Start new thread
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Acutally call the server
[self authenticate];
// Prevent the thread from exploding before we've got the data
CFRunLoopRun();
// End thread
[pool release];
}
I copied the Apple URLCache demo pretty heavily and have compared them both many times but can't find any discrepancies.
Any help would be greatly appreciated.
Here are the questions to ask:
Does your delegate respond to connectionDidFinishLoading:?
Does the signature match, i.e. it takes another object?
Is the delegate set at all or is it nil? (Check this in that very method)
If any of those are "NO", you will see "doesn't respond"... and all equally likely to happen in your application, but all are easy to figure out.

How can my iPhone Objective-C code get notified of Javascript errors in a UIWebView?

I need to have my iPhone Objective-C code catch Javascript errors in a UIWebView. That includes uncaught exceptions, syntax errors when loading files, undefined variable references, etc.
This is for a development environment, so it doesn't need to be SDK-kosher. In fact, it only really needs to work on the simulator.
I've already found used some of the hidden WebKit tricks to e.g. expose Obj-C objects to JS and to intercept alert popups, but this one is still eluding me.
[NOTE: after posting this I did find one way using a debugging delegate. Is there a way with lower overhead, using the error console / web inspector?]
I have now found one way using the script debugger hooks in WebView (note, NOT UIWebView). I first had to subclass UIWebView and add a method like this:
- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject {
// save these goodies
windowScriptObject = newWindowScriptObject;
privateWebView = webView;
if (scriptDebuggingEnabled) {
[webView setScriptDebugDelegate:[[YourScriptDebugDelegate alloc] init]];
}
}
Next you should create a YourScriptDebugDelegate class that contains methods like these:
// in YourScriptDebugDelegate
- (void)webView:(WebView *)webView didParseSource:(NSString *)source
baseLineNumber:(unsigned)lineNumber
fromURL:(NSURL *)url
sourceId:(int)sid
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: called didParseSource: sid=%d, url=%#", sid, url);
}
// some source failed to parse
- (void)webView:(WebView *)webView failedToParseSource:(NSString *)source
baseLineNumber:(unsigned)lineNumber
fromURL:(NSURL *)url
withError:(NSError *)error
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: called failedToParseSource: url=%# line=%d error=%#\nsource=%#", url, lineNumber, error, source);
}
- (void)webView:(WebView *)webView exceptionWasRaised:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: exception: sid=%d line=%d function=%#, caller=%#, exception=%#",
sid, lineno, [frame functionName], [frame caller], [frame exception]);
}
There is probably a large runtime impact for this, as the debug delegate can also supply methods to be called for entering and exiting a stack frame, and for executing each line of code.
See http://www.koders.com/noncode/fid7DE7ECEB052C3531743728D41A233A951C79E0AE.aspx for the Objective-C++ definition of WebScriptDebugDelegate.
Those other methods:
// just entered a stack frame (i.e. called a function, or started global scope)
- (void)webView:(WebView *)webView didEnterCallFrame:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
// about to execute some code
- (void)webView:(WebView *)webView willExecuteStatement:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
// about to leave a stack frame (i.e. return from a function)
- (void)webView:(WebView *)webView willLeaveCallFrame:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
Note that this is all hidden away in a private framework, so don't try to put this in code you submit to the App Store, and be prepared for some hackery to get it to work.
I created a nice little drop-in category that you can add to your project...
It is based on Robert Sanders solution. Kudos.
You can dowload it here:
UIWebView+Debug
This should make it a lot easier to debug you UIWebView :)
I used the great solution proposed from Robert Sanders: How can my iPhone Objective-C code get notified of Javascript errors in a UIWebView?
That hook for webkit works fine also on iPhone. Instead of standard UIWebView I allocated derived MyUIWebView. I needed also to define hidden classes inside MyWebScriptObjectDelegate.h:
#class WebView;
#class WebFrame;
#class WebScriptCallFrame;
Within the ios sdk 4.1 the function:
- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject
is deprecated and instead of it I used the function:
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
Also, I get some annoying warnings like "NSObject may not respond -windowScriptObject" because the class interface is hidden. I ignore them and it works nice.
One way that works during development if you have Safari v 6+ (I'm uncertain what iOS version you need) is to use the Safari development tools and hook into the UIWebView through it.
In Safari: Enable the Develop Menu (Preferences > Advanced > Show Develop menu in menu bar)
Plug your phone into the computer via the cable.
List item
Load up the app (either through xcode or just launch it) and go to the screen you want to debug.
Back in Safari, open the Develop menu, look for the name of your device in that menu (mine is called iPhone 5), should be right under User Agent.
Select it and you should see a drop down of the web views currently visible in your app.
If you have more than one webview on the screen you can try to tell them apart by rolling over the name of the app in the develop menu. The corresponding UIWebView will turn blue.
Select the name of the app, the develop window opens and you can inspect the console. You can even issue JS commands through it.
Straight Forward Way: Put this code on top of your controller/view that is using the UIWebView
#ifdef DEBUG
#interface DebugWebDelegate : NSObject
#end
#implementation DebugWebDelegate
#class WebView;
#class WebScriptCallFrame;
#class WebFrame;
- (void)webView:(WebView *)webView exceptionWasRaised:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: exception: sid=%d line=%d function=%#, caller=%#, exception=%#",
sid, lineno, [frame functionName], [frame caller], [frame exception]);
}
#end
#interface DebugWebView : UIWebView
id windowScriptObject;
id privateWebView;
#end
#implementation DebugWebView
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
{
[sender setScriptDebugDelegate:[[DebugWebDelegate alloc] init]];
}
#end
#endif
And then instantiate it like this:
#ifdef DEBUG
myWebview = [[DebugWebView alloc] initWithFrame:frame];
#else
myWebview = [[UIWebView alloc] initWithFrame:frame];
#endif
Using #ifdef DEBUG ensures that it doesn't go in the release build, but I would also recommend commenting it out when you're not using it since it has a performance impact. Credit goes to Robert Sanders and Prcela for the original code
Also if using ARC you may need to add "-fno-objc-arc" to prevent some build errors.
I have created an SDK kosher error reporter that includes:
The error message
The name of the file the error happens in
The line number the error happens on
The JavaScript callstack including parameters passed
It is part of the QuickConnectiPhone framework available from the sourceForge project
There is even an example application that shows how to send an error message to the Xcode terminal.
All you need to do is to surround your JavaScript code, including function definitions, etc. with try catch. It should look like this.
try{
//put your code here
}
catch(err){
logError(err);
}
It doesn't work really well with compilation errors but works with all others. Even anonymous functions.
The development blog is here
is here and includes links to the wiki, sourceForge, the google group, and twitter. Maybe this would help you out.
I have done this in firmware 1.x but not 2.x.
Here is the code I used in 1.x, it should at least help you on your way.
// Dismiss Javascript alerts and telephone confirms
/*- (void)alertSheet:(UIAlertSheet*)sheet buttonClicked:(int)button
{
if (button == 1)
{
[sheet setContext: nil];
}
[sheet dismiss];
}*/
// Javascript errors and logs
- (void) webView: (WebView*)webView addMessageToConsole: (NSDictionary*)dictionary
{
NSLog(#"Javascript log: %#", dictionary);
}
// Javascript alerts
- (void) webView: (WebView*)webView runJavaScriptAlertPanelWithMessage: (NSString*) message initiatedByFrame: (WebFrame*) frame
{
NSLog(#"Javascript Alert: %#", message);
UIAlertSheet *alertSheet = [[UIAlertSheet alloc] init];
[alertSheet setTitle: #"Javascript Alert"];
[alertSheet addButtonWithTitle: #"OK"];
[alertSheet setBodyText:message];
[alertSheet setDelegate: self];
[alertSheet setContext: self];
[alertSheet popupAlertAnimated:YES];
}
See exception handling in iOS7:
http://www.bignerdranch.com/blog/javascriptcore-example/
[context setExceptionHandler:^(JSContext *context, JSValue *value) {
NSLog(#"%#", value);
}];
First setup WebViewJavascriptBridge ,
then override console.error function.
In javascript
window.originConsoleError = console.error;
console.error = (msg) => {
window.originConsoleError(msg);
bridge.callHandler("sendConsoleLogToNative", {
action:action,
message:message
}, null)
};
In Objective-C
[self.bridge registerHandler:#"sendConsoleLogToNative" handler:^(id data, WVJBResponseCallback responseCallback) {
NSString *action = data[#"action"];
NSString *msg = data[#"message"];
if (isStringValid(action)){
if ([#"console.error" isEqualToString:action]){
NSLog(#"JS error :%#",msg);
}
}
}];
A simpler solution for some cases might be to just add Firebug Lite to the Web page.