iOS How can I use UIApplication launchApplicationWithIdentifier which is in private APIs?
REQUIREMENTS
- Jailbroken iDevice
- Valid certificates/keys in your keychain and its associated provisioning profile. (If you aren't enrolled in the apple developer program, use this workaround: self sign my code and test on iphone in xCode)
MY SOLUTION
1) Enable Entitlements in your XCode project.
To add Entitlements to your project, select your project in project navigator, then on active Target -> Summary -> Entitlements -> check Enable entitlements check box. New file with name "YourProject.entitlements" would appear in project navigator right after.
2) Add folowing property to Entitlements.
3) Since launchApplicationWithIdentifier:suspended:
is private API, you need to explicitly declare it in order to build your app. Just add folowing code in appropriate place(s):
// Simply make declaration inside a Category.
#import "BlahBlah.h"
@interface UIApplication (Undocumented)
- (void) launchApplicationWithIdentifier: (NSString*)identifier suspended: (BOOL)suspended;
@end
....
@implementation BlahBlah
...
4) Build your project.
5) Copy YourProject.app into device's /Application folder (via SFTP, for example)
6) Respring or reboot iDevice.
7) ...
8) Profit!
SEE ALSO
Special API to launch an app from my application - another solution
What is the bundle identifier of apple's default applications in iOS?
iOS How to use private API?
Just specify the private methods in a category interface above the class implementation where you want to use it, like this:
@interface UIApplication (Private)
- (BOOL)launchApplicationWithIdentifier:(id)identifier suspended:(BOOL)suspended;
@end
Don't import the whole class-dump file and link with the original UIKit framework.
You must be very careful when using private API. These methods can change or be removed in future iOS versions!
Check if the method really exists with respondsToSelector:
at runtime and be prepared for the case that it does not exist.
I used a secret MapKit feature in my own application and I knew that the private methods only exist in iOS 5. So my app still works in all iOS versions but this feature is only available in iOS 5 (Apple removed or changed it in iOS 6 beta 1).
Special API to launch an app from my application
Let me first say that this method is jailbreak only! It uses private API's that Apple can stop supporting at any time in a future version!
Let's get to it, this method uses the [UIApplication launchApplicationWithIdentifier:suspended:]
private method:
[[UIApplication sharedApplication] launchApplicationWithIdentifier:@"com.apple.Preferences" suspended:NO];
From what I've tested calling this method from an application not running as root is useless, apparently SpringBoard (or LaunchServices) only allow root applications to launch other applications using this method.
So, first you need to jailbreak your iPhone, then you need to get your application running as root.
To get your app running as root you need to place it in /Applications/YourApp.app instead of the usual /User/Applications/UUID/YourApp.app.
You can install OpenSSH using Cydia and use SSH to access your phone's shell.
Then, after having your app in the right place you need to set permissions, for example:
I would use the same ones as Cydia:
chown -R root:wheel /Applications/YourApp.app
Next, a little trick. The binary will need the setuid bit:
chmod 4755 /Applications/YourApp.app/YourApp
And for the last step, SpringBoard doesn't open apps with the setuid bit, but it opens a script (which can open another app)! Just change the name of the binary to something like YourApp_:
mv /Applications/YourApp.app/YourApp /Applications/YourApp.app/YourApp_
And create a new file named YourApp in your app folder with the following script:
#!/bin/bash
CrrDir=$(dirname "$0")
exec "${CrrDir}"/YourApp_
Now, just respring (there's an app for that in Cydia) and you're ready to go.
Sorry if this seems hard, it isn't, I don't remember where I learned it, but it was a long time ago. This method works fine in all iOS versions and I've just tested it with iOS 5.1.
Again, YOUR APP WILL NOT BE APPROVED BY APPLE IF YOU DO THIS.
Test private APIs on iPhone
yes as long as your device is registered (on the provisioning page) and marked "use for development." you can test on your device without any kind of interference from apple.
Open Mobile Safari without using openURL:url
I solved this using the answers on this page ..
iOS How can I use UIApplication launchApplicationWithIdentifier which is in private APIs?
Though I didn't have to move my .app file in to /Applications
It was enough to add the entitlements, then simply call it using ...
[[UIApplication sharedApplication] launchApplicationWithIdentifier:@"com.apple.mobilesafari" suspended:NO];
Plasma
iOS How to use Entitlement.plist to specify property of my app
I see two problems/questions in your post:
1) you get the error
'Receiver type 'UIApplication' for instance message does not declare a
method with selector 'launchApplicationWithIdentifier:suspended:''
Is that a compiler error? It sounds like maybe it is. Here's the thing. There's plenty of objective-c classes in the set of Public Frameworks that still have some private methods in them. Thus, in the normal headers (.h files) for the public frameworks, those private methods won't be listed. But, they're there in the dynamic libraries. If you want to build an app that uses these, then one way to solve the problem is to find a copy of the full header.
For example, here's a copy of the full UIApplication.h header.
Then, you can copy the declaration of the private methods, and in your own code, declare them like so:
// Used to disable warning for non-public methods
@interface UIApplication (Extensions)
- (BOOL)launchApplicationWithIdentifier:(id)identifier suspended:(BOOL)suspended;
@end
That should stop the compiler from complaining that the private method doesn't exist.
For the future, you should read about class-dump
, which is a tool that you can run on the public or private frameworks in the SDK, and reverse generate headers like the one above, yourself. They'll change with every release of the SDK, so it's good to be able to generate them yourself.
2) you ask about using entitlements without code signing.
First, read what Saurik originally wrote about it here. Yes, you do need to code sign the entitlements. But, no, it doesn't have to be with an Apple certificate on jailbroken phones. You can fake code sign, by downloading the ldid
executable, and doing
cd MyAppName.app
ldid -Sentitlements.xml MyAppName
assuming your app is named MyAppName and you made the entitlements file entitlements.xml. I believe that this entitlements file would work for you, if you fake code-signed it with ldid:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.springboard.launchapplications</key>
<true/>
</dict>
</plist>
Be careful. I have found ldid
on the internet in a couple places. I'm really not sure which one is the right one. I recall that once, I tried to do this, and the version of ldid
I was using did not work for signing entitlements. I downloaded ldid
from another source, and then it worked. So, beware.
Related Topics
Gcd - Main VS Background Thread for Updating a Uiimageview
Swift Framework Does Not Include Symbols from Extensions to Generic Structs
iOS 11 Animated Gif Display in Uiimageview
Swiftui: How to Get Continuous Updates from Slider
Remove Uiwebview's Internal Cache
Pass Uicollectionview Touch Event to Its Parent Uitableviewcell
Autolayout: Origin and Size Should Change According to Width and Height Factor
Understanding Model-View-Controller
Uiwebview Not Go to Didfailloadwitherror When Weblink Not Found
How to Create a Uiimage with Uibezierpath
iOS App Getting Throttled from Local Searches
Xcode Creates Wrong IPA Folder Structure
Convert Arabic String to English Number in Swift
How to Add External Webvtt Subtitles into Http Live Stream on iOS Client
Avplayer Uitapgesturerecognizer Not Working