Apple rejected our app with this message:
Guideline 2.5.1 - Performance - Software Requirements
Your app uses or references the following non-public APIs:
prefs:root="GraphicsServices.framework"
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.
Next Steps
If you are using third-party libraries, please update to the most recent version of those libraries. If you do not have access to the libraries' source, you may be able to search the compiled binary using the "strings" or "otool" command line tools. The "strings" tool can output a list of the methods that the library calls and "otool -ov" will output the Objective-C class structures and their defined methods. These tools can help you narrow down where the problematic code resides. You could also use the "nm" tool to verify if any third-party libraries are calling these APIs.
Resources
For information on the "nm" tool, please review the "nm tool" Xcode manual page.
If there are no alternatives for providing the functionality your app requires, you can file an enhancement request.
It's unclear how to fix this.
The issue was generated by https://github.com/erica/uidevice-extension
more specifically: https://github.com/erica/uidevice-extension/blob/master/UIDevice-Capabilities.m
There is even a description in the code, our app was not rejected for more than 1 year now.
/*
THIS CATEGORY IS NOT APP STORE SAFE AT THIS TIME. DO NOT USE IN PRODUCTION CODE.
YOU CAN, HOWEVER, USE THIS TO HELP BUILD YOUR OWN CUSTOM CODE TO PRE_COMPUTE CAPABILITIES.
*/
#define GRAPHICS_SERVICES_PATH "/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices"
We'll removed the use of the library.
Related
Goal
I'm building an iOS app using flutter for frontend, and C/C++ as backend. They must interoperate through FFI, which is a language binding scheme through C dynamic libraries. I intend to submit it to iOS App Store.
Problems
The Dart FFI sample on accessing C-struct works on macOS through dynamic liking and binding. Now dynamic linking is technically possible on iOS according to Xcode 9 - No option to create dylib project iOS, however, it's unclear to me how to ship the app to AppStore, because dynamic linking is not allowed according to Apple Guidelines Section 2.5.2.
2.5.2 Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they
download, install, or execute code which introduces or changes
features or functionality of the app, including other apps.
Educational apps designed to teach, develop, or allow students to test
executable code may, in limited circumstances, download code provided
that such code is not used for other purposes. Such apps must make the
source code provided by the Application completely viewable and
editable by the user.
Quite a few SO questions confirm this problem, such as:
can I use dynamic library(shared object) in my iphone app?
Will Appstore reviewers allow us to use dynamic library in iOS8?
Then official flutter documentation says
Dynamically linked libraries are automatically loaded by the dynamic
linker when the app starts. Their constituent symbols can be resolved
using DynamicLibrary.process. You can also get a handle to the library
with DynamicLibrary.open to restrict the scope of symbol resolution,
but it’s unclear how Apple’s review process handles this.
Questions
As of the date when I post this (2020), does this say that I could never ship an app using this architecture to App Store?
Is it possible that I static link my C/C++ code into a single binary of a flutter app? Take Unity as an example, their iOS plugin system recompiles the plugin into native app. If flutter has a similar mechanism, how?
The answers saying you can't use dynamic libraries on iOS date to before iOS 8, when support for user-provided dynamic libraries was added.
Nothing in 2.5.2 days you can't use dynamic libraires as long as they are shipped as part of your app. So:
As of the date when I post this (2020), does this say that I could never ship an app using this architecture to App Store?
No it doesn't, as long as "this architecture" refers to using a dynamic library that you link to at build time and bundle into your application.
Adding inputs from Reddit's FlutterDev channel
#escamoteur
As I understand it you are not allowed to load any library from
outside your installation folder. Especially not downloading something
at a later point of time. Could you make this a Stackoverflow question
and tag it with Flutter?
#airflow_matt
Since iOS 8 there can be shared libraries in the bundle, when properly
codesigned I don't see why dlopen wouldn't work. Or you can link the
library with main executable itself (just like flutter does) and
dlopen self (DynamicLibrary.process()). I think it's worth a shot.
Guideline 2.5.1 - Performance - Software Requirements
Your app uses or references the following non-public APIs:
PrivateFrameworks/Pegasus.framework (PGHostedWindow)
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.
Next Steps
If you are using third-party libraries, please update to the most
recent version of those libraries. If you do not have access to the
libraries' source, you may be able to search the compiled binary using
the "strings" or "otool" command line tools. The "strings" tool can
output a list of the methods that the library calls and "otool -ov"
will output the Objective-C class structures and their defined
methods. These tools can help you narrow down where the problematic
code resides. You could also use the "nm" tool to verify if any
third-party libraries are calling these APIs.
Can anyone please tell how I solve this error? I am not using Pegasus framework at all.
And also which apis consider as non-public?
I think you have used the private framework. The file PGHostedWindow is of Pegasus.framework and may be this file has been used in your app.
You can see the following link which show which file are available in Pegasus.framework:-
https://github.com/JaviSoto/iOS10-Runtime-Headers/tree/master/PrivateFrameworks/Pegasus.framework
You can also see the list of Private Framework on GitHub in the following link:-
https://github.com/nst/iOS-Runtime-Headers/tree/master/PrivateFrameworks
The non-public API refers to Apple API methods that are not documented and offered to the programmer.
Apple does not guarantee that this part of the API will work in future upgrades. These API can freely change this part.
Reasons Program License Agreement PLA 3.3.12
We found your app uses the iOS Advertising Identifier but does not include ad functionality. This does not comply with the terms of the iOS Developer Program License Agreement, as required by the App Store Review Guidelines.
Specifically, section 3.3.12 of the iOS Developer Program License Agreement states:
"You and Your Applications (and any third party with whom you have contracted to serve advertising) may use the Advertising Identifier, and any information obtained through the use of the Advertising Identifier, only for the purpose of serving advertising. If a user resets the Advertising Identifier, then You agree not to combine, correlate, link or otherwise associate, either directly or indirectly, the prior Advertising Identifier and any derived information with the reset Advertising Identifier."
Please check your code - including any third-party libraries - to remove any instances of:
class: ASIdentifierManager
selector: advertisingIdentifier
framework: AdSupport.framework
If you are planning to incorporate ads in a future version, please remove the Advertising Identifier from your app until you have included ad functionality.
To help locate the Advertising Identifier, use the “nm” tool. For information on the “nm” tool, open a terminal window and enter, “man nm.”
If you do not have access to the libraries source, you may be able to search the compiled binary using the "strings" or "otool" command line tools. The "strings" tool lists the methods that the library calls, and "otool -ov" will list the Objective-C class structures and their defined methods. These techniques can help you narrow down where the problematic code resides.
I checked who uses IDFA through following command:
grep -r advertisingIdentifier .
I knew that Facebook SDK (3.1.1 version) uses this.
How can I solve this?
The solution for me was that the facebook 3.20 SDK is indeed okay, but I had to remove the FBAudience framework that they include with the FacebookSDK.framework.
Once I removed the FBAudience framework, and ran
otool -L myAppName.app/myAppName
I no longer saw the AdSupport library bundled into my build, printed in the terminal like so:
/System/Library/Frameworks/AdSupport.framework/AdSupport
If you do not find a way to remove the usage of IDFA from the Facebook SDK, then another solution would be to say you're using the IDFA to attribute the installation to a previously served ad (which is actually fairly simple to enable in the Facebook SDK).
This option should be available to you when creating a new build in iTunesConnect if I remember correctly.
This issue has been taken care by Facebook in their latest versions. Update your Facebook sdk to the latest version and this will solve your problem.
I just got done reading the press hysteria around AFNetworking exposing apps to a man in the middle attack. I was surprised that sourcedna.com claims
SourceDNA analyzes the code in thousands of iOS & Android apps.
sourcedna.com even has a search engine to report whether a vendor's apps use the AFNetworking SDK.
Considering they don't have access to paid apps, how do they claim to do this? Do SDKs like AFNetworking log SDK use in some form? If so, to who?
I am curious about this too. Here is what I gather:
SourceDNA only checks whether the library is linked into the app binary. They do not check how or whether the library is actually used by the app.
Objective-C is a dynamic language and keeps a lot of metadata in the binary. You can trivially run tools like class-dump or otool -ov on any unencrypted binary and it will list the names and inheritance of all classes, and the names and signatures of all methods and instance variables in each class, among other things.
Libraries like AFNetworking have many distinctive class names that they can check for in the list of classes in the app. Each version will have some added or removed methods and/or instance variables, so by checking the class dump from the app against the class declarations from each version of the library, they can figure out the version of the library used.
However, apps downloaded from the App Store are encrypted; and the App Store is the only way that SourceDNA could have gotten these apps. It is possible to decrypt / crack encrypted apps (that is how people pirate paid apps -- they buy them, crack them, and post the unencrypted binaries on pirate websites), but the common way to do this I believe involves buying and running the app on a jailbroken device.
I assume that the SourceDNA people must have automated this process somehow, so that they can automatically report on thousands of apps.
As I replied to #janselrx, I believe it's as I suspected and they can only analyze free apps. From their website:
SourceDNA analyzes the code in thousands of iOS & Android apps. This report lets you explore recent data about the mobile SDKs and tools found in the top 500 free apps.
I read many articles about dynamic library usage including this page "Can you build dynamic library...".
As apple document said, "Frameworks for iOS. iOS developers can now create dynamic frameworks. Frameworks are a collection of code and resources to encapsulate functionality that is valuable across multiple projects. Frameworks work perfectly with extensions, sharing logic that can be used by both the main application and the bundled extensions.", see full page from here.
Taking the security issue as consideration, I got the reject reason of dynamic library before iOS8, see details from "DarkDust's answer". But, how does it "just work" in iOS8? #appstore_reviewers?
Anyway, currently I'm writing a sample demo app and try to upload it to Appstore for review, the main feature is downloading a framework from internet to client and dlopen it. Hope that really "just works"!
Besides, the deployment target is iOS7.0, not sure it could works well in it.
I didn't get a so clear understand on differences between "dynamic library" and "framework", I think they are the same and in this thread I mean "Cocoa-touch framework" which could create in Xcode 6.
Some background: I'm trying to build an iOS app which does't contain extension feature, my cocoa-touch framework is for easy expand without uploading a new version as it comes from internet....
UPDATE
I published a demo project GMDemo here, will try to upload to Appstore.
UPDATE2
I failed to dlopen my dynamic framework with invalid code signing error after many tries in iOS device. Sorry, no good news here. (Almost forgot to update this question, sorry! BTW)
App Store Review Guidelines explicitly prohibit that in 2.4.5 Apps that download code in any way or form will be rejected https://developer.apple.com/app-store/review/guidelines/
UPDATE3 just use the same code signing!!!
I have test it in ad-hoc environment!
when my dynamic library use the code signing with the same code signing,It works,
otherwise,crush!!