I have an app in private which need to scan all applications and schemes and get it by using private API LSApplicationWorkspace defaultWorkspace
with others functional method, such as privateURLSchemes
allInstalledApplications
. This app works good and I can get all I need from the private API before iOS 11, but in this version I only got some warning and an empty array. It seems Apple limits private API that developer can't use in private in iOS 11.
So my question is what alternative ways can achieve my need in iOS 11?
UPDATE: This method does not work on iOS 12 - entitlement required
There is a way to find if a specific application is installed, its not a list of all apps like allInstalledApplications
returned but its useful to query for a specific bundle id
Here is an example, the method receives bundle id and return true if it's installed on the device:
- (BOOL)checkIfAppInstalled: (NSString*)bundleID {
dlopen("/System/Library/PrivateFrameworks/MobileContainerManager.framework/MobileContainerManager",RTLD_NOW);
Class MBAppManager = NSClassFromString(@"MCMAppDataContainer");
NSError * error ;
id contentApp = [MBAppManager performSelector:@selector(containerWithIdentifier:error:) withObject:bundleID withObject:error];
return contentApp != nil;
}
Private API is just that—private API. Using it is completely unsupported, and as such, you cannot rely on a private API continuing to work in future versions of the OS.
In addition, I would be highly surprised if an app that used private API were able to get into the App Store, since it's one of the things Apple's reviewers scan for.
In enterprise you can use Apple Mobile Device Management (MDM) Protocol ManagedApplicationList commands to get the status of managed applications
From this post. From the comment of @ovo under the original question, it seems works.
Using MobileContainerManager.framework
it's possible to check if an app is installed by using bundle id.
//If the device is iOS11
if ([[UIDevice currentDevice].systemVersion floatValue] >= 11.0) {
NSBundle *container = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
if ([container load]) {
Class appContainer = NSClassFromString(@"MCMAppContainer");
id test = [appContainer performSelector:@selector(containerWithIdentifier:error:) withObject:bundleId withObject:nil];
NSLog(@"%@",test);
if (test) {
return YES;
} else {
return NO;
}
}
return NO;
} else {
//Usual way
}
i got same Apple Reject.
Apple Says
Your app uses or references the following non-public APIs:
LSApplicationWorkspace
The use of non-public APIs is not permitted on the App Store because
it can lead to a poor user experience should these APIs change.
Continuing to use or conceal non-public APIs in future submissions of
this app may result in the termination of your Apple Developer
account, as well as removal of all associated apps from the App Store.
Solutions
To find out which library or code is causing this problem use the below code snipped.
1-) Open the terminal in macbook (cmd+ space) and than write terminal
2-) change the project directory with the below code
cd /Users/emreg/Documents/{your project url}
3-) To search appropriate word
grep -r LSApplicationWorkspace .
grep -r allApplications .
in my case, Blesh SDK has included LSApplicationWorkspace and allApplications keyword which is not permitted by Apple. When i upteded SDK, my problem is solved.
i hope, this answer will help someone.