CPDistributedMessagingCenter not working ios7 - ios

I am fairly new to jailbreak iOS development and had a question. I am trying to send a message between two processes(MobileSafari to SpringBoard) and am having a problem, the reciever function in SpringBoard is never called! So far in SpringBoard I have this:
-(void)applicationDidFinishLaunching:(id)arg1{
%orig(arg1);
//register for notifications
CPDistributedMessagingCenter *messagingCenter = [CPDistributedMessagingCenter centerNamed:#"com.magnusdevelopment.flow"];
[messagingCenter runServerOnCurrentThread];
[messagingCenter registerForMessageName:#"updateWallpaper" target:self selector:#selector(handleMessageNamed:withUserInfo:)];
[messagingCenter registerForMessageName:#"updateScalingMode" target:self selector:#selector(handleMessageNamed:withUserInfo:)];
[messagingCenter registerForMessageName:#"downloadWallpaper" target:self selector:#selector(handleMessageNamed:withUserInfo:)];
UIAlertView *testAlert = [[UIAlertView alloc] initWithTitle:#"Yo!" message:#"registered" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[testAlert show];
}
}
%new
-(NSDictionary *)handleMessageNamed:(NSString *)name withUserInfo:(NSDictionary *)userInfo{
UIAlertView *testAlert = [[UIAlertView alloc] initWithTitle:#"Yo!" message:#"2" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[testAlert show];
if([name isEqualToString:#"updateWallpaper"]){
//get info for wallpaper
NSString *wallpaperImagePath = [userInfo objectForKey:#"WALLPAPER_PATH"];
int option = [[userInfo objectForKey:#"OPTION"] intValue];
BOOL retValue = setWallpaperImage(wallpaperImagePath, option);
//return the dictionary
NSMutableDictionary *replyDict = [[NSMutableDictionary alloc] init];
[replyDict setObject:[NSString stringWithFormat:#"%hhd",retValue] forKey:#"RETURN_VALUE"];
return replyDict;
}else if([name isEqualToString:#"updateScalingMode"]){
//get info from dictionary
int option = [[userInfo objectForKey:#"OPTION"] intValue];
NSString *scalingMode = [userInfo objectForKey:#"SCALING_MODE"];
//set wallpaper scaling mode
setWallpaperScalingMode(scalingMode,option);
}//end if
return nil;
}//end method
and when a button is pressed in MobileSafari I call this code:
NSString *option = [NSString stringWithFormat:#"%i",wallpaperOption];
NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: wallpaperPath, #"WALLPAPER_PATH", option, #"OPTION", nil];
CPDistributedMessagingCenter *messagingCenter = [CPDistributedMessagingCenter centerNamed:#"com.magnusdevelopment.flow"];
[messagingCenter sendMessageAndReceiveReplyName:#"downloadWallpaper" userInfo:infoDict];
UIAlertView *testAlert = [[UIAlertView alloc] initWithTitle:#"Yo!" message:#"sent" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[testAlert show];
I get the alert "registered" whenever SpringBoard starts up and then when I press the button I get the message "sent". The only thing that isn't called is the function handleMessageNamed:withUserInfo:
Why isn't this working?
Thanks!

Try darwin notifications https://developer.apple.com/library/mac/documentation/corefoundation/Reference/CFNotificationCenterRef/Reference/reference.html It's a public API, shouldn't be hard to find sample code.

If you look at this document entitled "Updating extensions for iOS 7, it looks there are problems using CPDistributedMessagingCenter on iOS 7, but Ryan Petrich has published a library that may help you work around them:
Inter-process communication
CPDistributedMessagingCenter, XPC and other IPC methods built on top
of bootstrap registered mach services don't work; you get deny lookup
in the Xcode console.
Workaround: rpetrich has built a workaround called RocketBootstrap: "One common way processes communicate with each other
on iOS and OS X is through a messaging system called mach ports. Each
port is a channel that can either receive or send messages. There is a
central registration system for these ports called bootstrap, where
ports can be registered and accessed by a service name assigned to
them. Recent versions of iOS restrict which names a process can
access—MobileMail, MobileSafari and App Store apps are only allowed to
access a very specific set of services that come with iOS.
RocketBootstrap adds a secondary lookup service that doesn't restrict
which processes can access which services."

Related

Obtain an array with notifications

I am trying to put notifications in an array as they become available, but the count of the array is reset to 1 when I push a new notification.
This is the code:
int r = 0;
listMsgReceived = [[NSMutableArray alloc] init];
if (notification)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Notification received" message:[NSString stringWithFormat:#"%#", message] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
[listMsgReceived insertObject:message atIndex:r];
r++;
NSLog(#"apres: %d \n", [listMsgReceived count]);
}
It looks like you are initializing the variables r and listMsgReceived each time your notification is received (though it's hard to tell from the context you provided).
You should not do that, because that gets you a new array each time, where you insert one object - hence the count will be one after each notification.
You could try moving your array initialization outside of your method; declare it as a property on your class and initialize it in the initializer.

saveEvent returning "No calendar has been set"

I am attempting to save an event into the calendar, from my application.
My code works for iOS 7, but on iOS 6, it returns No calendar has been set.
The application prompts for user to grant access to the calendar, on iOS 7.
But no such prompt appears for iOS 6. Although the application is granted access in the Settings-> Privacy -> Calendar.
And yes, I have already implemented the requestAccessToEntityType:completion:.
Here is my code snippet.
EKEventStore *objStore = [[EKEventStore alloc]init];
if ([objStore respondsToSelector:#selector(requestAccessToEntityType:completion:)])
{
// iOS 6 and later
[objStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
// code here for when the user allows your app to access the calendar
EKEvent *calEvent = [EKEvent eventWithEventStore:objStore];
calEvent.title = mstrTitleEvent;
calEvent.startDate = self.dateToBeSet;
calEvent.endDate = self.dateToBeSet;
calEvent.calendar = objStore.defaultCalendarForNewEvents;
EKAlarm *objAlarm = [EKAlarm alarmWithAbsoluteDate:self.dateToBeSet];
[calEvent addAlarm:objAlarm];
NSError *error;
BOOL _bStatus = [objStore saveEvent:calEvent span:EKSpanThisEvent commit:YES error:&error];
UIAlertView *alertV;
if(_bStatus)
{
alertV = [[UIAlertView alloc]initWithTitle:#"Congratulations" message:#"Saved To Calendar" delegate:nil cancelButtonTitle:#"Right On!" otherButtonTitles:nil];
[alertV show];
}
else
{
alertV = [[UIAlertView alloc]initWithTitle:#"Alert" message:[NSString stringWithFormat:#"Error saving to calendar, with error %#.",[error localizedDescription]] delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alertV show];
}
}
else
{
// code here for when the user does NOT allow your app to access the calendar
UIAlertView *alertV = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Please grant access to the calendar, and try again later." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertV show];
}
});
}];
}
Just managed to somehow find a solution for my problem.
I had to navigate from one page to another, so posting the link to the two pages.
First ->
https://discussions.apple.com/message/16497282#16497282
Then, from there to ->
https://discussions.apple.com/message/16479587#16479587
I had to go into Settings>iCloud> and turn on Calendars.
After that, I tried to attempt and run my code, and it was working well and fine again.
Do attempt this, if you facing a similar problem.
I was working on iPad 2, and with iOS 6.1.3 installed on the device.
Amazing I am testing my code on two different devices, one it works fine and the other it will not work. Just looked in setting and the one with it not working has iCloud calendar and reminders turned off, just turn them on and it all works now... this has to be a bug

Why does my Tweak Not work Correctly?

I am making my First MobileSubstrate Tweak For the iPhone Running IOS 7.
I am using this tutorial.
This tutorial explains the basics of Hooking and providers a git hub example of his source code.
To test the code he wrote worked and to get my head round theos compiling terminal I compiled his project.
The project is suppose to show a UIAlert when an application is launched and put a setting switching with the state of on or off within the settings application in the iPhone.
When installing this compiled deb onto my iphone the setting page is added so i can turn the function on or off but when the function is ON the alert does not show.
Here is my Tweak.xm code:
#interface SBApplicationIcon
-(void)launch;
-(id)displayName;
#end
%hook SBApplicationIcon
-(void)launch
{
NSString *appName = [self displayName];
NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithContentsOfFile:
[NSString stringWithFormat:#"%#/Library/Preferences/%#", NSHomeDirectory(), #"com.AndyIbanez.NotifierSettings.plist"]];
NSNumber* shouldNotify = [settings objectForKey:#"alertLaunch"];
if([shouldNotify boolValue] == YES)
{
NSString *message = [NSString stringWithFormat:#"The app %# has been launched", appName, nil];
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:appName message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert1 show];
[alert1 release];
}
%orig;
}
%end
Here is the GitHub Example File I am following and compelling: https://github.com/AndyIbanez/TutorialProjects/tree/master/launchnotifier
launch is for iOS 6 and you need to use launchFromLocation: on iOS 7.
#interface SBIcon : NSObject
- (void)launch; // iOS 6
- (void)launchFromLocation:(NSInteger)location; //iOS 7
#end

UIActionSheet works fine in iOS6 but crashes in iOS7 -- data structures were at fault

EDIT: The error is with the data structures that are being used during PDF generation. I'll be able to debug it once I can get a copy of OSX that supports iOS7. Thanks for all the help everyone!
At work I have Mac dedicated to working on iOS 6 apps. So far it hasn't been possible to update to a newer version of OSX so my version of XCode can't be upgraded to support iOS7 naturally. So long story short I can't debug iOS7 apps, so I am not sure why the app is crashing.
I have a UIActionSheet. I used to be using one with those completion blocks but was trying to debug so I have stripped everything away to just the basic barebones and it still crashes when I click on the button.
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send by Email", #"Send To...", #"Open In...", nil ];
[actionSheet showFromBarButtonItem:sender animated:YES];
That's just sitting on the end of a PDF generation method.
Any ideas? I've been researching this all afternoon and I haven't found any reason why it would stop working like this. I did try storing the action sheet as data in the view controller so the reference was being kept, but to no avail.
I am using ARC.
EDIT: I tried an UIAlertView with the same results. Maybe it's the PDF context ruining things somehow?
Thanks for all the help everyone.
EDIT: Big breakthrough in solving this one: When commenting out my PDF generation code that's before my action sheet/modal dialog/alert view, it opens without complaint. So it's some kind of hybrid issue, and I'll post the majority of my method here so everybody can see what's up:
-(void)shareTapped:(id)sender
{
if (actionSheet.isVisible)
return;
if (![MFMailComposeViewController canSendMail])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No mail setup" message:#"You must setup your email in the main settings app before you can share." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return;
}
for( NSIndexPath *indexPath in self.tableView.indexPathsForSelectedRows )
{
// should only get run once due to UI
Calculation* calc = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *filename = [calc.name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *path = [[[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent:filename] stringByAppendingPathExtension:#"ipc"];
[[PPCalculation sharedInstance] openCalculation:path];
}
[[PPCalculation sharedInstance] calculate];
// let's generate the PDF here!
NSMutableData* pdfData = [[NSMutableData alloc] init];
UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
UIGraphicsBeginPDFPage();
// 200 lines of drawing commands here
UIGraphicsEndPDFContext();
// save to file
NSString* path;
for( NSIndexPath *indexPath in self.tableView.indexPathsForSelectedRows )
{
// should only get run once due to UI
Calculation* calc = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* filename = [calc.name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
path = [[[[self applicationDocumentsDirectory] path] stringByAppendingPathComponent:filename] stringByAppendingPathExtension:#"pdf"];
[[NSFileManager defaultManager] createFileAtPath:path
contents:pdfData
attributes:nil];
}
// ActionSheet, modal dialog, composer dialog, alert view, all of them crash when I try to put them here
UIActionSheet* sheet = [[UIActionSheet alloc] initWithTitle:#"Share" delegate:nil cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send By Email", nil];
[sheet showFromBarButtonItem:sender animated:YES];
}
Thanks again guys.
EDIT: It seems that, from my investigation and commenting things out line by line and sending them to the device over TestFlight that it's the internal data structures somehow not working properly, which is strange, as the rest of the app works fine. I probably will get a copy of Mountain Lion or something so I can debug this thing properly.
Try below code... May be it will help you...
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send by Email", #"Send To...", #"Open In...", nil];
//actionSheet.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
actionSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
actionSheet.tag = ((UIButton*)sender).tag;
[actionSheet showFromRect:[(UIButton*)sender frame] inView:[(UIButton*)sender superview] animated:YES];
By sheer trial and error and commenting out code, I have narrowed it down to the PDF generation itself. Somewhere in the guts of the C++ data structures something is happening that is making iOS7 sad but the others fine. I've managed to convince the boss to order Mountain Lion so once that arrives I can build for iOS7 directly and debug it properly.
Try This it will help yo
your barbutton action method :
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:nil: delegate:nil cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Send by Email", #"Send To...", #"Open In...", nil ];
[actionSheet showInView:self.view];

Rechability connection to internet

I want to execute some code only, and only if I am connected to the internet:
//Reachability
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
Reachability * reach = [Reachability reachabilityWithHostname:#"www.dropbox.com"];
reach.reachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Block Says Reachable");
connect = #"yes";
});
};
reach.unreachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
connect = #"no";
});
};
[reach startNotifier];
//Reachability
if (connect == #"no") {
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"There is no internet connection. Please connect to the internet. If you are already connected, there might be a problem with our server. Try again in a moment." delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
} else if (titleSet == NULL){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please select a group or create a new one" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
}else if (NavBar.topItem.title.length < 1){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please select a group or create a new one" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
} else if (newmessagename.text.length < 4){
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"" message:#"Please give a name to your event that is at least 4 characters long" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles: nil];
[alert1 show];
}
It seems that the code is not executed in order. I think it is taking more time to check the Internet connection than it takes to execute the code. How can I fix this?
Please do not tell me to place the code directly in the parenthesis where connect = #"no"; is located.
The blocks aren't executed sequentially, they are executed asynchronously.
This means that you can't tell when the code inside the blocks is going to be called. The code using the block may finish and execute before the rest of your method (however this is unlikely, especially with Internet connections).
You should place your ifs in a method that is called at a valid time. This time is probably when you receive a response from your blocks, or, if my memory serves true, [reach startNotifier]; can notify you when there is a change in reachability status, this appears to be your reachabilityChanged: method:
-(void) reachabilityChanged:(id) parameter
{
//Query reachability and notify / cache as required.
}
Of course its not executed in order, the whole point of those methods is to stop the ui to freeze while you get your reachability response. Basically you set up the reachability responses and immediately ask for the result when nothing has been checked yet. What you have to really is to move it inside the brackets.
Something else that you can do is make a function with those results, and call this function in both of the blocks.
If you want to have this on the load of the viewcontroller or before you display anything else, then you either have to check for reachability before you show this controller, or add a "loading" screen.
EDIT: Something else that i dont understand is, those reachability methods seem to fire a block when they get the results, but you are registering for a notification as well. And i dont see you posting a notification for this. You are using 2 asynchronous approches here (blocks and notifications)

Resources