Thread: Can anyone suggest how to include `Privacy...
# multiplatform
p
Thread: Can anyone suggest how to include
PrivacyInfo.xcprivacy
file in the framework generated by KMP for iOS ? One need to include this file if the iOS App/SDK confirms that App/SDK's functionality dealing with privacy as mentioned by Apple.
j
Does anyone have a suggestion on this?
c
I just added it per the standard instructions. What problems are you encountering?
j
I added it to my app, but it’s my understanding that every binary which uses an API which requires a disclosure needs to have its own privacy declaration file.
p
Will we have to add the
PrivacyInfo.xcprivacy
file to Android Studio and then via
build.gradle.kts
get it included in the framework/binary being generated ?
c
Here’s what mine looks like. Repo is public: https://github.com/realityexpander/FredsRoadtripStoryteller
p
@Chris Athanas Can you please tell the steps one need to incorporate the
PrivacyInfo.xcprivacy
file in KMP iOS framework? It will be helpful for others as well. Thanks
j
It seems to me, from the Apple docs, that you need to include it in every bundle that contains a binary that uses a required reason API.
For each executable or dynamic library in an app that uses a required reason API, the bundle that includes the executable or dynamic library needs to include a privacy manifest file that reports the API.
https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api
👍 1
Since the Kotlin code is compiled as a framework (unless you're statically linking) then you need to include it in the bundle.
p
That means we have to add the
PrivacyInfo.xcprivacy
inside the Android Studio project and get it copied in the framework bundle via
build.gradle.kts
if I am understanding it correctly.
j
Yes, that would seem to be the implication.
I just don't know how to do it. 🙂
🆗 1
c
You have to add the
.xcprivacy
inside XCode. All new iOS-specific files must be added inside XCode. Make a new file at the root level, look for “privacy” type, then set the options as I have shown above. Or read the documentation and check mine as an example.
m
That doesn't really help with the requirement that all frameworks must have that file and the framework for the KMP is built by gradle and doesn't contain source from Xcode. There's no Xcode project to add the file to
👍 2
j
Yup, Michael is 100% correct. Gradle builds the
.framework
file. We need some way to add resources to the framework bundle. In Xcode, you'd do this with a "Copy Bundle Resources" but we don't really have that in Gradle (to my knowledge).
c
I have a full implementation of this using KMP for iOS and Android in this project, if you need a reference. There is an xcode project embedded that’s used to create the iOS shell: https://github.com/realityexpander/FredsRoadtripStoryteller
The build happens from gradle, but the
.xcprivacy
file is specifically for xcode, and must be added inside xcode to be able to create an archive from within xcode to push to the App store.
j
If you go into the bundle for the framework, does it have a
.xcprivacy
file in it?
p
In my case, we are using cocoapod and the KMP framework is getting added as a pod. That is why I am looking for a way to include the manifest file for framework to include in framework bundle at the time when it is built via Gradle.
j
Did you find any way to include PrivacyInfo.xcprivacy file in .xcframework? In my KMM Ios library I am using OpenSSL which is listed on list of sdks that using them requires adding PrivacyInfo file https://developer.apple.com/support/third-party-SDK-requirements/ As of May 1, 2024, including PrivacyInfo.xcprivacy file will be mandatory in order to pass the App Store review, so without this file i won't be able to update mobile app. Any suggestions?
j
I'm going to guess this will require a change to the KMP Gradle plugin.
p
Anyone aware if any open ticket is there specific to KMP Gradle plugin change ?
j
I looked in YouTrack and there was only a ticket for an unrelated issue.
🆗 1
One workaround might be to turn on static linking. I don't know if Apple's static analysis has the ability to tell if you've linked an undeclared library. However, if it doesn't then it would be up to you to declare the privacy manifest through your app's main
.xcpricacy
file.
p
For any SDK whether third party or local, we can include it's privacy manifest into app's own one?
j
Xcode has this new mechanism that includes each framework's privacy manifest in the final build product, and the system then combines all of the manifests together to get the privacy profile of the app. Dynamic frameworks always include a
.framework
bundle in the app, where the
.xcprivacy
file is. Static frameworks now have the ability to include a
.bundle
bundle in the app, where its resources (including
.xcprivacy
) are located. However, I'm postulating that it might still be a workaround. 🤷‍♂️
j
I created issue: on youtrack https://youtrack.jetbrains.com/issue/KT-67210/Kotlin-multiplatform-Ios-apple-PrivacyInfo.xcprivacy-requirements-1may-2024 In my opinion there is no workaround, because in some cases there are strict rules that you need to have this file inside sdk and also signature: https://developer.apple.com/support/third-party-SDK-requirements/
👍 2
p
@Jakub Sieprawski Is above link still available? I am seeing below error while trying to open it.
👍 1
j
Hmm, I changed visibility from registered users to everyone, is it working now? @Parvez Qureshi
p
Yes it is visible, thanks @Jakub Sieprawski
j
Can you guys comment it or add any reaction?
Anyone has idea how to do it or is it even possible?
Okay, I read a lot about that and it seems that it does not have anything to do with kotlin multiplatform. To fulfil apple requirements you just have to paste privacy files into correct location of xcframework This thread explains it all: https://rhonabwy.com/2024/02/18/embedding-a-privacy-manifest-into-an-xcframework/
j
Correct, it’s nothing specific to KMP. But since KMP produces an apple framework, it’s going to have to include the manifest in the resulting framework.
p
That means we have to include the framework specific manifest through a script that will be run in
post install
phase? It is for the case when KMP iOS framework is included via a cocoapods
POD
either locally created or through a remote source, right ?
j
Yeah, pretty much. Something needs to copy the file into the framework bundle, like how Xcode build phases do it.
I started working on a potential solution for this. It could be implemented as part of the compiler, like how the Info.plist file is created. However, I don't think this is the best solution since it will be difficult to get the necessary information from Gradle to go to the compiler. There are a couple options that I see. 1. Add a DSL for specifying the privacy manifest information through Gradle. Then, have a task in the KMP Gradle plugin that produces the file in the framework directory. 2. Add a simple task that copies a file you have in your project directory after the framework is produced by the compiler. 3. Rely on Compose or MOKO Resources to copy the manifest file. Anyone have thoughts?
👏 1
r
Option 2 seems straightforward and flexible and could be implemented easily by a third-party plugin.
p
+1 for Option #2
j
Okay, here is what I landed on--it seems to work... I haven't tried to upload a build to the App Store yet, though. This will copy a
PrivacyInfo.xcprivacy
file from your shared project directory into the bundle. For me that was in
$REPO_ROOT/shared/PrivacyInfo.xcprivacy
Copy code
project.afterEvaluate {
    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink>().forEach { linkTask ->
        val frameworkDestinationDir = linkTask.outputFile
        linkTask.doLast {
            project.copy {
                val sharedDir = project.file("PrivacyInfo.xcprivacy")

                from(sharedDir)
                into(frameworkDestinationDir.get())
            }
        }
    }
}
👀 1
❤️ 2
p
@Jacob Rhoda Are we keeping the
PrivacyInfo.xcprivacy
under Android Studio project ?
j
@Parvez Qureshi You will need one under both.
👍 1
c
Quick Update: I tried adding my KMP app “Fred’s Roadtrip Storyteller” to the AppStore by placing the
PrivacyInfo.xcprivacy
into my XCode project. Everything built and verified, but I just got an app rejection notice from Apple saying the privacy info was missing. I will be trying out @Jacob Rhoda’s suggestion and submitting again to Apple. Will let this thread know my outcomes.
👀 1
1
👍 1
😢 2
Update: Build 38 of My compose-ios app “Fred’s Roadtrip Storyteller” finally passed review. I included the
.privacy
notice as a plain file inside my iOS project. I was NOT sent a notice of “Missing API declarations” for this build. I did NOT add the custom code that @Jacob Rhoda posted. Before this I was getting a notice for each build about the missing privacy notice. I don’t know if they send the notice out for each non-complying build or not. Note: I am not an iOS dev, this is only my second app I’ve put in the Apple store, and the other one is a simpler KMM project. I am primarily and Android and Web developer, so please forgive my ignorance about the Apple app-release processes.
👍 1
j
Interesting. I don't quite know how to explain that.
👍 1
c
You can check out my code and see if anything is odd. I’m kinda winging this and I’m as surprised as you that it was accepted. 😄 I do know the privacy notice is not required yet, and I do find it strange they didn’t send me a notice that I am missing it for this build. My only assumption at this point is that the file was included like I set it up, or that they haven’t sent me a non-compliance notice yet… It’s been 4 days since the app was accepted, so I’m thinking that it’s not coming at this point. I don’t know whats normal, as this is only my second rodeo, and first rodeo with the privacy notice stuff. Here’s the link to my code: https://github.com/realityexpander/FredsRoadtripStoryteller
j
Sometimes App Store Review is fickle. It makes me nervous, because what I read in the docs says you need it for every framework. But it's also a pretty aggressive requirement that not everyone will be able to satisfy by May 1.
👍 1
p
For only those 3rd party frameworks which satisfy privacy manifest requirements, we will have to update them to the version that has the
PrivacyInfo.xcprivacy
file available in it.
👍 1
j
@Chris Athanas I had a look at your code. I believe that you didn't get the rejection / warning email because your Kotlin code is linked to your iOS app statically. That means the binary of the framework is copied directly into your app's binary, and there's no bundle or indication for Apple to tell that there's a library there. But, it could also have been a fluke — I'm not 100% sure my explanation is correct.
👍 1
s
Hey, folks! We have done a technical study and now recommend describing the manifest at the application level in case of errors. We're keeping a close eye on the situation, and invite you to the documentation page, where we plan to keep in touch. You can also share your case in the comments of this ticket.
👏 1
j
@Stanislav Tsyganov Thanks for ya’lls attention to this! I’m curious regarding the claim that App Store connect doesn’t check usage in dynamic library bundles. That seems like a fairly obvious workaround for any nefarious tricksters to get around declaring the reason for the API usage and like Apple would close that loophole pretty quickly. Is this statement based off published documentation, response to a radar, or experimentation with actual apps? Thanks!
👀 1
r
If the recommendation is to handle things at the application level, should there be best practices for how KMP library authors can notify their consumers about these requirements? Especially in the case of transitive dependencies, I could see this getting confusing for end-users.
👍 3
c
@Jacob Rhoda Yes, I statically linked it, and seems to work fine. I just tested this technique with another app, and it was just accepted. For those who want to just statically link, here’s where to set the static link in XCode:
p
@Chris Athanas Are statically linked frameworks still require to contain Privacy info file looking to that the framework is embedded?
s
We carefully studied the documentation, the Apple Forum and conducted a series of experiments with passing the review. In case of static linking, the manifest put by the responsible author of the library does not help in passing the review. In this case we need to fill in the application level manifest. In case of dynamic linking, the problem does not occur even if the API is used in the dependency and there is no manifest. I think library authors should follow Apple's guidelines and explicitly add a manifest to their libraries. We are now proposing a local solution that will allow the end user to pass validation and not violate Apple's guideline. We are monitoring the situation from our side and will offer a long-term solution in the context of KMP when the situation becomes clearer.
👍 2
thank you color 2
j
@Stanislav Tsyganov Thank you!
c
@Parvez Qureshi Please restate your question
p
@Chris Athanas if you are referring about this query then it means for KMP frameworks which are linked statically we will not require adding
PrivacyInfo.xcprivacy
in the framework as the app target's corresponding
.xcprivacy
file will be taking care of it.
👍 1
c
@Parvez Qureshi I’m just statically linking using XCode, per the screenshot above.
👍 1