Know if the user launched an app - objective-c

Alright, this title might seem strange, but bear with me. I have an app which can be set on its preferences by the user to launch at login. That means I can expect sometimes the app will be launched by the user (clicking on the Dock/Finder, etc), but some other times the app will be launched automatically by the system, on login.
I would like to show a window when the app is launched by the user, but not when it is launched automatically (as I imagine that would be a pain for the user). How can I do that?

Although it may depend on how you intend to automate the launch of the app, you could use command line arguments to distinguish between system launch vs. user launch.
So, the command line launch might like like this:
MyApp -autoLaunch "Y"
To parse the command line args in a Cocoa app, you could use NSUserDefaults (Yes, you can!):
if( ![[NSUserDefaults standardUserDefaults] objectForKey:#"autoLaunch"] isEqualToString:"Y"] ) {
// do something for user initiated launch
}

I don't have an exact answer to your question. However, may I suggest that your app should show the window if the window was visible when the user last quit your app?
This may be more in-line with the Mac UI guidelines' suggestion on restoring apps and windows, and is within the user's expectations.
Also, a user who set your app to launch at login will probably understand to close the window and not have it restored the next time, or make the system also hide your app during login.

Related

Bring other running app's window to front

What I am trying to achieve: when user presses "buy" in my app, App Store window should appear with my app url in it.
This works fine when App Store is not running: [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"macappstore://..."]];
But when App Store is already running and is minimised in the dock it's window doesn't show up. It becomes active, yes, but the window doesn't appear.
What I have already tried: fetched app using NSRunningApplication and trying to unhide, activateWithOptions: it, but this doesn't work.
I don't see more options in NSWorkspace and NSRunningApplication, so if someone have some solutions for this, it would be appreciated.
Mmm I can't think of any approach that does not involve Applescript or Accessibility APIs which then requires the user give your app access permission which is even worse. (I mean, you could quit and relaunch App Store, but that's jarring.) Honestly this is bad behavior in App Store, so you should file a report with Apple noting the window doesn't come to the front. It won't help you now, though.
But doesn't this bring it to the front even if it's minimized?
NSWorkspace.shared.launchApplication("App Store")

Provide an OSX Service Without Launching the App?

I have successfully implemented a "faceless service" (background-only app with .service extension) and get it to work (see this question), based on Apple's documentation and other tutorials on the web.
Now, I want to advertise a service from an existing, single-window GUI app that I have.
I have setup the Info.plist file of my app to advertise the service, and it gets installed when I build the app.
But when I invoke the service from the context menu in (say) TextEdit.app (my service colours the selected text based on a certain criterion), my app gets launched, main window and everything. To make things worse, I am right-clicking on a TextEdit window that is in a secondary monitor, so my app's main window appears for an instant in the secondary monitor, then quickly repositions into the main monitor (this might have something to do with my window-centering logic, but nevermind...).
I would like to provide the service (i.e., have the class that provides the service in my app
instantiated and execute its method in response to the request), without my app appearing on the Dock or showing its window and main menu.
Is this possible? Safari advertises "Search With Google", so it should be possible...
EDIT: Now that I think about it, "Search With Google" must launch Safari every time in order to work, so this remark does not apply.
Perhaps I can put some logic in -applicationWillFinishLaunching/-applicationDidFinishLaunching to determine if the app is being launched in response to a service, and skip creating the window(notice the lack of withOptions: in OSX)?
But still, that doesn't feel right.
It does have a lame version of withOptions: -- NSApplicationLaunchIsDefaultLaunchKey tells you if your application was launched to either:
open or print a file, to perform a Service action, if the app had saved state that will be restored, or if the app launch was in some other sense not a default launch
So in your applicationDidFinishLaunching you can see if that key is in the notification and set to NO. Unfortunately, the main way to tell that it is one of the possibilities other than the Service, you have to detect and record whether or not you also got an application:openFile:, etc.

Long-running task performed in foreground is suspended when app enters background

When a user first opens my app, I need to download and install some content from a server before they can begin using the app. The problem is that this takes around 5 minutes on wifi, during which time the app goes into the background and the download is suspended.
Is there any way to either:
prevent an iOS app from entering the background whilst I perform my download
or continue peforming the task in the background (i.e. perform the task irrespective of whether the app is in the foreground or background)
Thanks
It really doesn't matter, if the user presses the home button it will go to background. Although you can do two things to mitigate the problem:
Use beginBackgroundTaskWithExpirationHandler, to give you a bit more time to download. Which you can read here.
Don't allow the device to become iddle, with [UIApplication sharedApplication].idleTimerDisabled = YES;. You can read more about that here.
Either way, the best thing you can do is to tell the user, that is an important download and he shouldn't quit the application.
Can't you include some or all of the content in your app bundle instead, and just download changes on first run?
I can't imagine this is a good first user experience, and it may not pass App Store review like this.
The only third party apps that are allowed to download in the background are newsstand apps loading issue content, and Apple are pretty strict about what they allow as newsstand apps.
You can't do what you want, in this situation. One way, and I think the best and only, is to resume your download when you app becomes active (returns to foreground state). Also, don't forget to register for connectivity notifications (Reachability class can be used for this purpose from this Apple sample app http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html). Good Luck!

IOS - How to create a modal user/password outside the UIApplication?

I am not sure this can be done at all...
Background: I am constructing an in-house application which means it does not get into appstore so i am not limited by the appstore guidelines.
I have a dylib which loads before the main application. It is a kind of augmenting library for applications. I am using the constructor __attribute__ to load my stuff. In there i would like to put an alertview or any kind of popup which will receive a user/password question. If the password is correct than the user is allowed to continue into the original application.
Since this is in the dylib i do not yet have a UIApplication and i do not want to interfere in the original application or sources.
Suggestions, tips are welcome...
Thanks.
This is how i've done very similar thing in my application:
0) Intercept applicationDidFinishLaunching message, add your own code, run original implementation.
1) Make opaque fullscrean UIWindow (for example, black).
2) Set its windowLevel to UIWindowLevelAlert + 1 So it hides every other window in app.
3) Add fields for user and password to this UIWindow.
I'm pretty sure you can't show a UIAlertView without having initialized the UIApplication and UIWindow instance.
Only the iOS itself can show alerts outside the application, for example when it asks for permissions or in case of iTunes or game center login ...
As a workaround you can:
make a login view inside the application
create a web application for the login process. The web app could launch the native app with a custom URL scheme and pass parameters like 'user' and 'password' to the app.
You should create a View for the Login then if you pass the login you can go on using the app otherwise you just make the app shut itself.
You could start a thread when loading your dylib and make it listen for your UIApplication to become available, then display the alert on the main thread.

how to delay application quit time in iphone sdk?

I want to register my app for push notification when my application terminates so i think if i delay my app quitting time it could be possible.Does someone knows how to delay application quitting time? I think this method
[self performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait];
will do my job but i don't know how to use this method if someone knows please tell.I need to send some data to a server along with registering for Push Notification when my app quits.
I can't imagine why you would want to do this. If it were even possible it would be extremely annoying for a user to tap the home button and the app to take x amount of time to shut down. This time 'x' being dependent on the server connection creates even more user headache.
Apple have the home button exit apps immediately for a reason.
If you want to register the Push Notifications like you suggest, do it while the app is running. If your worrying that they won't be properly set if the user exits prematurely... don't.
As users, we all know there are sometimes consequences of exiting a program without giving it time to save your settings.
For push notification it is better to register when the app first starts and then send the push token to your server in the background. However, if you have a good reason why you need to do the registration just as the app terminates, I believe you can do this if you are using iOS 4. iOS 4 has a new feature called "task finishing" that allows an app to stay running for a few minutes after the user closes it so that it may finish up any tasks it was in the middle of (such as saving data).