Get extern [UIApplication sharedApplication]? - iphone

I am currently developing an "in device" (not simulator) monitoring system for an iPad app. The system should be able to do the following:
-User input simulation: Simulate user inputs: taps, drags, keyboard.
-Information recollection: Get text values and results after doing inputs.
This information will be later reported to an event management server. I have already taken care of the two points in a single app, by using some code from KIF software https://github.com/square/KIF and some self developed code. I use the accessibleName property of the UIView objects to get their pointer and send artificial events to the [[UIApplication sharedApplication] sendEvent:] method.
Here’s the thing: I need to send these events from app#1 in which I am, to app#2. (To keep the monitoring independent, also embedding all the code in app#2 is not an option) I use the [[UIApplication sharedApplication] openURL:] method to open the app#2.
https://developer.apple.com/library/IOs/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW18
The problem is, I cannot send events from app#1 to app#2 because I cannot seem to get the pointer to the [UIApplication sharedApplication] object of app#2 in the app#1 code.
A shared memory communication between the processes would be great, but according to the information that I found, the URL messaging scheme seems to be the only communication between apps (or processes) in iOS. The NSConnection class is also not present in iOS. I've also read a little bit about Mach ports and POSIX file descriptors, but they seem fairly complicated and I have no idea if they can help.
I even tried to send the value of the pointer of the app#2 [UIApplication sharedApplication] instance as a string parameter in the URL message, then converted the string back to a pointer in app#1, but got a EXC_BAD_ACCESS. I suppose the pointer address does not mean the same in both processes. Maybe each process has its own "offset"?
Any help would be greatly appreciated.

In first instance I wold clarify that what you want to do is not possibile without private APIs.
Each app is sandboxed and you cannot access to other apps (directly). I think that your problem is really big.
Each app running in iOS is like small, independent, eco-system that ends when the user press the 'Home' button (except if you declare some background services like VOIP, localization or audio player). Once the app has been closed the only thing that you can still run is a process that should not be longer than 10 mins. This is to prevent an excessive usage of background tasks and even here, the app isn't accessible from other apps.
I think the only way is to search for private APIs, hoping someone else already found a way to create a data streaming (directly) between 2 apps.

Related

Custom URL scheme with custom app behavior

I am making an app that has multiple usage cases. It has the main functionality (activated by pressing the app icon), then other subsets of the main functionality which are activated by a custom URL scheme.
To explain my problem, I should explain how I currently tell my app to behave differently.
I have been using:
-(BOOL)application:didFinishLaunchingWithOptions:
grabbing the url from the options:
[launchOptions objectForKey:[keyArray objectAtIndex:0]]
Now I parse that urlString and grab all of my launchType parameters, putting them in NSUserDefaults. Then I wait for my splash screen to come up, then it will tell my app how to behave.
This seemed okay at first, but then I realized that: if I deep-link into the app, and am presented with functionality B, then the app goes into the background, the next time the app take the foreground (no matter which way), it will display functionality B.
I was wondering if anyone had an idea about the standard practice, what methods do people usually use?
FYI,
I am going to be trying to fix this problem by telling my navigationcontroller to popToRootViewController, when
-(BOOL)application:application handleOpenURL:
is called, UNLESS didFinishLaunchingWithOptions is called before it, in which case, just do what I had previously implemented.
It sounds to me like there are a couple of things for you to consider about this approach.
First of all take a look at the UIApplicationDelegate documentation. -application:willFinishLaunchingWithOptions: warns:
If your app was launched to open a URL, you should examine the value
of the UIApplicationLaunchOptionsURLKey key and return a Boolean value
indicating whether your app can actually open the URL. You should not
try to open the URL in this method. Instead, implement the
application:openURL:sourceApplication:annotation: method in your app
delegate and use that method to open the URL.
Looking at -application:openURL:sourceApplication:annotation: we see:
If your app had to be launched to open the URL, the app calls the
application:willFinishLaunchingWithOptions: and
application:didFinishLaunchingWithOptions: methods first, followed by
this method. The return values of those methods can be used to prevent
this method from being called. (If the application is already running,
only this method is called.)
Secondly it sounds like you are using NSUserDefaults to persistently store what should be a temporary state (if the app was launched via a url or not). Do you ever reset the values you set there or does launching the app via a url once leave it stuck always following that path.
Finally users have a reasonable expectation that apps will resume where they left off. Users will leave your app to respond to phone calls, text messages, notifications, external distractions, needs for other apps, and any number of other reasons. Refusing to allow them to return to where they left off when they resume/relaunch the app (not via a url) may produce a poor user experience.

How to run a ~30sec process in the background every hour (iphone app)

I have an iphone app that has a 30second process that does some network IO. Basically, while the app is in the background, i want this process to run every hour (actually once a day, but if it fails i want it to re-run in an hours time).
With the background features of ios 4, is this possible? If so, how? What are the limitations that i'll come up against?
Thanks so much!
Take a look at Apple's documentation about running code in the background.
http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html
There are few different ways of approaching backgrounded tasks. The only apps that can have fully backgrounded processes are "audio", "voip" and "location" apps, and this needs to be declared in the Info.plist.
If your app is not of this type, you'll probably find it difficult to do what you want easily. There are methods which allow you to keep your app alive in the background for a finite period of time (also at that link), but eventually your app will be shut down.
Local Notifications will only prompt the user to open the app - do you really want to have an alert pop-up on the phone every 30 seconds?
I was making some kind of similar research, have a look at this SO answer in case you didn't manage to find it before. Applications like DataMan or Data Usage must have some sort of periodic code execution in the background, so I'm not 100% convinced that what you're asking for is impossible..
I believe that Using Local notifications will help....
check following....
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1
An application can create and schedule a local notification, and the operating system then delivers it at the schedule date and time. If it delivers it when the application is not active in the foreground, it displays an alert, badges the application icon, or plays a sound—whatever is specified in the UILocalNotification object. If the application is running in the foreground, there is no alert, badging, or sound; instead, the application:didReceiveLocalNotification: method is called if the delegate implements it.
The delegate can inspect the properties of the notification and, if the notification includes custom data in its userInfo dictionary, it can access that data and process it accordingly. On the other hand, if the local notification only badges the application icon, and the user in response launches the application, the application:didFinishLaunchingWithOptions: method is invoked, but no UILocalNotification object is included in the options dictionary.

Xmpp Gets disconnected After iphone goes idle for more than 10 mins [duplicate]

The XMPPFramework for iPhone is powerful. I have it up and running, but how do you keep the connection alive while in the background for more than 10 minutes? I would appreciate some more documentation/how-tos on how to accomplish this.
So the use case is simple and common: Joe is online and in the iPhone chat app. He leave the chat app and goes to Safari, plays a game, streams a movie, and does other stuff for 3 hours (or more). Joe wants to keep receiving messages during that time.
The example app allows Joe to receive local notifications in the background, but for only 10 minutes it seems. Here's the relevant code (I think). Thanks!
To help out other folks, to even get to this point, you need to the xmppstream property enableBackgroundingSocket to YES (it's done for you in the iphoneXMPP example project which you should copy) and in the appname-info.plist (i.e., iosChat-info-plist) file you need to add a new key/value pair. You should right click somewhere and "add row". You should choose for the key "required background modes" and then type in "voip". Xcode will detect that you mean "App provides Voice over IP services" after you press enter. This gets you 10 minutes of keeping the chat app open in the background (I think). But we want indefinitely, and I suspect that the answer lies in the method below. Am I just supposed to "reconnect" within this method or something,e.g., [self connect] (I have a connect method)?
- (void)applicationDidEnterBackground:(UIApplication *)application{
DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
if ([application respondsToSelector:#selector(setKeepAliveTimeout:handler:)])
{
[application setKeepAliveTimeout:600 handler:^{
DDLogVerbose(#"KeepAliveHandler");
// Do other keep alive stuff here.
}];
}}
10 minutes is the approximate time iOS allows you to stay connected. You can
also look at [app beginBackgroundTaskWithExpirationHandler], which will allow you
to request more time to finish a task. In order to remain connected 100%, you will
need to either add a voip, audio or location tag to info.plist (that is UIBackgroundModes).
Backgrounding will not work unless you add one of those tags. In addition, adding a tag
will allow you to remain connected, but the actual tag must be valid if you're submitting to the App Store. Apple will reject the app if there's not a real use-case.
To remain connected longer without a tag, you will need to resort to using some type of server, which maintains the connection and then uses push notifications to deliver messages.

Suspend the application

How can I suspend my application or send a suspend message to my application?
I want to simulate pressing the home button.
There is a private instance method for UIApplication:
The following code would work, (tested in an iPhone 3GS):
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:#selector(suspend)];
In swift:
UIControl().sendAction(#selector(NSURLSessionTask.suspend), to: UIApplication.sharedApplication(), forEvent: nil)
Edit Swift3:
UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
Quitting your application or sending it to the background programmatically is a violation of the iOS Human Interface Guidelines, which usually doesn't bode well for getting through the review process:
Don’t Quit Programmatically
Never quit an iOS application
programmatically because people tend
to interpret this as a crash. However,
if external circumstances prevent your
application from functioning as
intended, you need to tell your users
about the situation and explain what
they can do about it. Depending on how
severe the application malfunction is,
you have two choices.
Display an attractive screen that describes the problem and suggests a
correction. A screen provides
feedback that reassures users that
there’s nothing wrong with your
application. It puts users in control,
letting them decide whether they want
to take corrective action and continue
using your application or press the
Home button and open a different
application
If only some of your application's features are not working, display
either a screen or an alert when
people activate the feature. Display
the alert only when people try to
access the feature that isn’t
functioning.
The philosophical reason for this is explained earlier in that document:
People, not applications, should
initiate and control actions. Although
an application can suggest a course of
action or warn about dangerous
consequences, it’s usually a mistake
for the app to take decision-making
away from the user. The best apps find
the correct balance between giving
people the capabilities they need
while helping them avoid dangerous
outcomes.
Users feel more in control of an app
when behaviors and controls are
familiar and predictable. And, when
actions are simple and
straightforward, users can easily
understand and remember them.
People expect to have ample
opportunity to cancel an operation
before it begins, and they expect to
get a chance to confirm their
intention to perform a potentially
destructive action. Finally, people
expect to be able to gracefully stop
an operation that’s underway.
There should be no reason that you need to force your application into the background during its operation. It should remain fully functional when displayed onscreen and it should be up to the user when they want to switch away from your application.
You can't do this.
If you want to exit your app, don't fear rejection and love false positive crash report emails from users you could call exit(0);
Use :
sleep(15)
it will suspend your app for specific time
When the application is suspended, a UIApplicationWillResignActiveNotification notification is posted.
I would guess you could try to post this notification manually. Didn't try this myself though.

How to test memory low condition on real iphone/ipad device (not simulator)?

I know that there is a "Simulate Memory Warning" on the simulator. However, many people said that the app should be test on real device. How can I test the memory low condition on real device? Running as many apps as possible in background? Any better way?
Thanks.
You can use private API to send low memory message:
[[UIApplication sharedApplication] _performMemoryWarning];
Though remember to remove from release otherwise your app might get rejected ;)
Kudos goes to: http://forum.148apps.com/showpost.php?p=8603&postcount=3
The previous answer doesn't compile on my machine. The workaround is to call performSelector:, like this:
[[UIApplication sharedApplication] performSelector:#selector(_performMemoryWarning)];
There are a few tricks you can try:
Put some NSLog statements in your low memory delegate calls to see if your app is getting stress tested in normal use.
If not:
Prior to running your app, start several large slow web sites downloading in Safari; then while testing your app, send some large emails to a push account on your test device.
For stress testing purpose (use a preprocessor define that is NOT in your distribution build), malloc an extra 10 or 20 or some-test-number megabytes that your app doesn't need, write into it some junk/rand() data to dirty the pages, and don't release it (you can purposely leak 25MB for max stress).
You can also create your own test background app, say a music player that plays silence, put it in the background before testing your app, and have the background audio callback allocate and dirty some large chunks of data.