Is there a way to update SMLoginItemBookmarks data on launchd overrides.plist - objective-c

I'm working on an OS X app that most users choose to "launch at login", the kind you'd find at the menu bar.
In order to launch it at login I'm using SMLoginItemSetEnabled to launch a LoginHelper app that will open the main app, as described in this tutorial.
The app is failing to start up at login for just a handful of our users.
I was unable to reproduce this or to track the cause but I found (on a user's machine) that:
Deleting /Root/_com.apple.SMLoginItemBookmarks/[myapp] and /Root/[myapp] on /var/db/launchd.db/com.apple.launchd.peruser.$UID/overrides.plist and then resetting the Launch at login on the app fixed the issue. Also, we diff'd the files and the Data on the bookmark had changed.
For reference, I found about the overrides.plist here.
Since the app has both a Mac App Store and a Direct download version, I'm suspecting multiple copies of the app setting themselves as Launch at login may be the reason for this to fail, maybe these "bookmarks" are trying to open another instance of the app, that may or may not be deleted.
Now the questions, provided that this app needs to remain sandboxed:
Is there a way of updating that Data on the overrides.plist bookmarks?
Is there any way of deleting one self's app from the overrides.plist to start clean?
Is this maybe a known issue?
Any other suggestions on why the bookmark seems to point nowhere or how to fix it will be appreciated.
Note: This is my first question on StackOverflow, please excuse me if I failed to follow some of the suggested etiquette.

I don't know a definitive solution to this, I wasn't even aware of the overrides.plist. It could be related to multiple copies. As far as I understand, adding login through SMLoginItemSetEnabled sets a metadata flag that this Bundle ID should be launched on start. Then Spotlight, on start, will go do a metadata search on the file system and see which Bundle IDs need to be launched. Then, I guess, it will initiate the launch using the bundle ID. In my own application, Trickster, which uses the same technique for launching, I see that if I enable launch-on-login through the app itself, it might pop-up this strange message which refers to a debug build. I'm not even sure why it says about the first time. Very strange.
So, to have them launched, you have to make sure that the relevant bundles are in locations where Spotlight indexes (that the user hasn't disable Spotlight for these locations). Usually users don't disable Spotlight, especially for /Applications/ but I'm just saying.
What I usually suggest when support comes my way (and how I have it set up for me because I have multiple copies), is I to disable launch from within the app and instead add the correct one (from /Applications) manually in Login Items in System Preferences.

Related

Cannot come out from the play store internal beta testing

We have uploaded an update of our existing app (WASFAT) as internal testing build. We can access it successfully.
Now I want to leave from the internal testing and want to access the live build.
There is not leave button the playstore wasfat page. Please have a look at the attached image.
When we have released beta version, we had that leave button. But in the internal release, we don't have it.
How can I get out from this internal testing mode? How can I access the original live build? Also I don't want to remove my id from play console internal testing.
Thanks for any suggestions
As far as I know, you can opt-out of internal testing with the same link you used to enter in the internal testing program. Also, you need to remove your email from internal tester. However, It will take some time to be able to access live mode again
The simplest way I have found is to just switch to a different account within play store.
Open play store afresh
On top right, tap your account icon (or where ever it is located)
Click the drop down and tap "Add another account"
Later on it is just a matter of selecting an account, no password entry needed if done before.
The advantage of this is that you don't have to wait for Googles services to register that you have disabled a testing account. When you need to enable the testing account you will have to wait again. So this is pretty nifty for me.
I'm reliably able to restart my phone, and have changes to beta status reflected immediately.

What is the standard method for writing a continuously running app that is allowed on the Mac App Store

I'm brand new to OS X and mac programming. I'm looking to write an app that runs continuously or is woken up every 30 seconds to do some minor task. It would do something like check the weather via a web service and shoot off an email if the temperature drops below freezing. In Windows I would just use a service or put a repeating task in the task scheduler. Is there a standard way to accomplish this in OS X which the mac app store allows? I would like to write something that I can put in the store but Apple seems to have vague restrictions against running background processes.
I've learned a little about launchd but I can't tell if I am allowed to use it. Ideally the process would get run even when no one is logged in, but it probably won't need root access. If someone does happen to be logged in, it would trigger some popup if it sent an email temperature alert out. I would also have some GUI which the user would be able to modify the configuration files that determine the behavior of the background process. I don't anticipate any app store restriction for that piece of the project though.
I'm pretty sure an app that runs invisibly like that would not be allowed into the App Store. What you're going to want is to create a menubar-only application, which can be enabled by setting a key in your app's info, namely LSUIElement. Although it won't be able to be run unless a user is signed in, it's your only way to get it into the store successfully.
The MAS guidelines have several prohibitions that would impact you. Go to the guidelines and read section 2. In particularly consider 2.15, 2.23, and 2.27. I don't know any way to get your application running prior to login without at some point requesting admin privileges (even if you don't use the privilege when you run).
I would probably make it a Login Item (System Preferences>Users>Login Items), probably as an LSUIElement app as sudo rm -rf suggests. Definitely if it's your first app, I wouldn't go diving into launchd in any case. It is one of the most infuriating system processes I've ever dealt with.

Load another application when entering background

Is it possible to load up another application when the first application enters the background?
Say I have application 1 and application 2 installed.
When application 1 enters the background, the method is called to invoke the loading of application 2, but application 2 is never loaded.
Is it possible that Apple have disallowed this sort of thing?
I am 100% sure that the custom URL schemes I'm using are able to be called as I have done testing within MobileSafari to make sure they work.
Should mention this is for an iPad application and not iPhone application. Albeit, I don't think there should be much difference between the two when it comes to this issue...
EDIT
Let me explain. The application itself is for a specific purpose. What we want to do is allow our clients to set a setting that will allow the application to "bounce" back via another installed application.
We want to limit the users of the application to only be able to use the application in question. This is due to the fact that the iPad's using this application will ONLY be using this application. Hence why we want to lock it down as best we can.
This will not work, simply because the application can only have the system open URL schemes while in the foreground. Think of it like this, if your application is not in the foreground can it, say, present a modal view such as a UIAlertView or a simple Modal View Controller?
Also, you would be horribly breaking Human Interface Guidelines and would most likely be rejected. URL schemes, especially custom ones, should only be called when the user prompts.
Sounds to me like you want a lockdown/kiosk iOS system. There's simply no way to do this and make it work like they want without breaking out of apple's sandbox. Jail breaking. Or, write one application with two halves. The initial half with authentication or whatever, then the secured half. Maybe we need more context, but as you describe it, URL schemes are incredibly easy to circumvent or fail altogether. What happens when they just delete the goto app?
Now why would you do that? Say the user is getting a call and he proceeds to take it. He definitely wouldn't want to go to another app in between. Other case considered, he would actually leave your app to go to another app he wants to attend to without being taken to another app in between.

Gain root acces in iOS and launch Daemon

I am an iPhone Developer, now I am making an App that need to run commands (like "launchctl")
The only way I can launcht is with root privileges, but i dont know how to get root privileges.
I want to call it with System("launchctl....") or there is other way?
Thanks in advance ;)
You cannot get root privileges if your going to distribute this in the App Store. However, you can get root access if you're developing this for jailbroken devices.
I built a jailbreak app once that was trying to do something similar. I wasn't using launchctl, but I was issuing a call using system().
What I found was that even if I let my app run as user root, which requires more than what edc1591 outlined in his comment above, system calls would still run whatever command you passed it (e.g. launchctl) with user mobile privileges. (Aside: I think the reason might be related to this issue).
If you want to do that, I found a rather convoluted way of doing so. See that answer here.
First of all, using system(); is a C method and is not very reliable at all for executing commands like that, (I know from experience).
What you would want to do, is copy the NSTask.h file from the foundation.framework into your project window and use it. the way to find it is by opening a new project for the mac and clicking show in finder on the foundation.framework and then copy it. (Make sure to remove the lines near the top that check if you have Mac OS 10.6 or greater)
Then try running it. If it still doesn't have the right privileges, try looking into setuid(); but other than that, i don't know how it's done.
Maybe you can contact the developer of iFile, he would know how...
Unfortunately, there is no Apple sanctioned way to do this. In other words, apps that require root access will not be approved for use in the App Store. It is possible that Apple will grant an exception, but that's is seriously, extremely, unlikely.

Changing provided services based on user preferences in OSX?

I would like to be able to change the OSX services that my application provides based on the current user's preferences (like adding more, changing the name,...). This basically means modifying the Info.plist (NSService key), but I don't think it is a good practice when an application modifies its own Info.plist while running, right? (At least based on few searches here). Is there any other option how to get this functionality?
I guess it should always be an external entity who does modify the Info.plist? So far I can only think about providing a system preference bundle which will do the modification in the actual app? Do you have any ideas?
Thank you
One way would be to install a service in ~/Library/Services that provides the services, and edit that application's Info.plist from your main application.
Of course, that should be an explicit action, so the user (hopefully) knows to delete the service if they delete your application. And you should document that procedure on your product's support web page, just in case they don't.
Here's a small twist to the previous recommendations, create a separate app that handles the service and bundle it within your Resources. When you want to enable the service, instead of copying the file over to ~/Library/Services, create a symbolic link within the ~/Library/Services folder that points to the app you bundled in your Resources.
This way if the user deletes your application, all that will be left behind is a symbolic link pointing to an invalid location. Does less arm than actually leaving the app behind and will have the added benefit that the service will no longer be available (since the info.plist will have been removed when the user deleted your app).