-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Fix #160622: change containsWatchConpanion function to detect companion watch apps defined by only the project info file. #176832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #160622: change containsWatchConpanion function to detect companion watch apps defined by only the project info file. #176832
Conversation
Previously, the loop skipped the default scheme when iterating over project schemes. This commit removes that check, ensuring all schemes, including the default, are processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request modifies the containsWatchCompanion function in packages/flutter_tools/lib/src/xcode_project.dart. The change removes a condition that was skipping the defaultScheme when searching for a watchOS companion app. This allows the function to check all schemes, including the default one, which addresses an issue where companion apps defined in the default scheme were not being detected. The change is logical and well-explained in the pull request description.
|
I changed the code to check only the scheme of current flavor, so that the slow build config generation is only executed for current flavor. the build config generation is slow as much as real build, so we must remove useless generation. |
Refactors the logic to evaluate only the default scheme's build settings when verifying the watch companion app bundle identifier, instead of iterating through all schemes.
|
Removed unrequired loop |
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
|
from triage: @vashworth could you take a look since you also reviewed #172436? |
|
It appears that this PR checks for @garrettjavalia Did this solution not work for you? #172436 |
|
I did not test solution in #172436. My solution was made separately from that, and I see that solution is currently closed. please let me explain about this more. first of all, checking default(currently targeting) scheme is a valid operation in my opinion. the second part, which you might feel this code is wrong is, How it can work if it just processes xcode build configuration without specifying correct watchOS app as target. (buildSettingsForBuildInfo function and it`s call chain can specify a target to test, but current code doesn't specify one.) now we can think that the valid way to handle this problem might be by making it check only watchOS App's build configuration, and yes that is a valid point. but that is for some cases when a scheme has two or more watchOS app(like one for companion app and one for independent app, or just two companion watchOS apps in wrong configuration.) with above inspections, I suggest current PR a pretty good way to solve current situation. well, maybe I can improve the code to handle more complicated situations I mentioned above, but it would be optional for now. + I found that checking multiple schemes slow down the flutter run command a lot due to slow build config generation which is also mentioned in some code comments. |
|
I tried the #172436 and it worked but it checked different scheme.(my xcode project has a watchApp only scheme which is just used to run watchos app in simulator, So it has same INFOPLIST_KEY_WKCompanionAppBundleIdentifier value with the iOS app which is used by flutter run.) |
|
Nevermind, I just saw this comment:
The purpose of loop through of schemes that you're trying to change is to find the watchApp only scheme to find the INFOPLIST_KEY_WKCompanionAppBundleIdentifier, so I think it's an accurate positive? |
|
The target dependency and copying steps added on the host iOS app are not something i've invented, it's default behavior of Xcode when you add a watch companion app to a flutter generated iOS app project. isn't it better following convention of Xcode and other iOS apps in the world so that developers can use their contextual information for the similar works?
|
|
Sorry, I guess maybe I'm misunderstanding something... If we look at the current logic, it gets all the schemes and then gets the build settings for each scheme (except the default). If the scheme has flutter/packages/flutter_tools/lib/src/xcode_project.dart Lines 746 to 775 in f4d77a1
If I understand correctly, you think it should check the default scheme because the default scheme may be building multiple targets, one of which may be the watch target. Correct? However, one of the schemes should also be the watchApp only scheme. So it should be finding that scheme and returning true. It's not building that scheme - it's only using the scheme to determine if there is a watch companion app. I think the problem people are having is that it's failing when it tries to get the watch scheme's build settings as I explain here. Does that makes sense or am I stilling missing something? |
|
Thank you for considering my opinion/comments many times even it doesn't seems quite right at the first look. I really appreciate your effort. I tried to fix my own confusions and clear out the two possible solutions below. "If I understand correctly, you think it should check the default scheme because the default scheme may be building multiple targets, one of which may be the watch target. Correct?"
I checked deviceId solution again throughly. and found that it solves slow startup problem.(which is not existing in my solution, too. it exists only in current flutter build chain.) xcode's slow build config generation was fixed by not specifying deviceId. You mentioned that a Xcode project with companion watchOS app should have a dedicated scheme only having that watchOS app as target. The answer could be "almost certain.", not always.
things can be wrapped up like below :
what I think is option 2 is better. |
|
How about as a comprise we do both? We change it to so that it will check the default scheme but it will also check the other schemes for the watch-only scheme? final String? defaultScheme = projectInfo.schemeFor(buildInfo);
if (defaultScheme == null) {
projectInfo.reportFlavorNotFoundAndExit();
}
for (final String scheme in projectInfo.schemes) {
- // the default scheme should not be a watch scheme, so skip it
- if (scheme == defaultScheme) {
- continue;
- }
final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(
buildInfo,
- deviceId: deviceId,
scheme: scheme,
isWatch: true,
);
if (allBuildSettings != null) {
final String? fromBuild = allBuildSettings['INFOPLIST_KEY_WKCompanionAppBundleIdentifier'];
if (bundleIdentifier == fromBuild) {
return true;
}
if (fromBuild != null && fromBuild.contains(r'$')) {
final String substitutedVariable = substituteXcodeVariables(fromBuild, allBuildSettings);
if (substitutedVariable == bundleIdentifier) {
return true;
}
}
}
}
return false;
} |
|
Ok, I considered benefits of your merged approach, it seems it can handle some miss configured projects which can be produced in following steps.
(I have no idea what will happen if we actually include the wrong watch companion app in the iOS app bundle. neither for the case that multiple watch companion app is actually included in the iOS app.) So, I guess it will be good to write a defensive and robust logic. I agree with your solution and I will edit this PR to have latest flutter branch file and update it. |
Previously, only the default scheme was checked for the WKCompanionAppBundleIdentifier. This update iterates through all available schemes in the project to ensure the correct bundle identifier is found, improving robustness against scheme with multiple watchOS apps.
|
Great! I'm glad you agree! Can you ensure all tests in test/general.shard/project_test.dart pass and add an additional test that uses the default scheme? |
…h only default scheme
|
Updated existing tests and added new tests as a separated test group. |
Adds mock build settings for XcodeProjectBuildContext in two test cases to ensure correct variable substitution during plist parsing.
|
found out that 'watch companion' test group's test codes are getting host iOS app bundle name configuration with XcodeProjectBuildContext(scheme: 'Runner') refactored test codes in following ways.
|
|
I found that multi target schemes are Ok in xcode, but not in flutter code. |
…roject Detection of watch companion app without dedicated watch app target scheme requires watch companion app target included as a explicit build target of the default scheme, which causes malfunctioning of bundle identifier detection logic of flutter ios build chain which assumes default scheme will have only one explicit build target which generates it's build configuration for xcodebuild command.
|
I had to rollback code to something identical to #172436 Detection of watch companion app without dedicated watch app target scheme requires watch companion app target included as a explicit build target of the default scheme. I don't think changing the entire flow just for watch companion app will give us any visible benefit for now. |
|
@LouiseHsu Can you do a second review? |
LouiseHsu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tiny typo nit, lgtm!
…ct companion watch apps defined by only the project info file. (flutter/flutter#176832)
…ct companion watch apps defined by only the project info file. (flutter/flutter#176832)
flutter/flutter@cc14ef5...cb7b7df 2025-11-18 [email protected] Enable UIScene Migration and update create templates (flutter/flutter#178700) 2025-11-18 Minsuk Jung Fix #160622: change containsWatchConpanion function to detect companion watch apps defined by only the project info file. (flutter/flutter#176832) 2025-11-18 [email protected] Roll Skia from 614e71550fc3 to ca906091e199 (2 revisions) (flutter/flutter#178716) 2025-11-18 [email protected] Revert "[ Tool ] Don't delete `.dart_tool/widget_preview_scaffold` during `flutter clean` (#175664)" (flutter/flutter#178672) 2025-11-18 [email protected] Add missing flutter_lints dev dependencies (flutter/flutter#178105) 2025-11-18 [email protected] Roll Skia from ec2f626cdcad to 614e71550fc3 (3 revisions) (flutter/flutter#178708) 2025-11-18 [email protected] Roll Dart SDK from a8ad764281e3 to 312845b06afc (1 revision) (flutter/flutter#178704) 2025-11-18 [email protected] Roll Skia from d7268f8245f2 to ec2f626cdcad (1 revision) (flutter/flutter#178703) 2025-11-18 [email protected] Refactor SnackBar behavior selection example to use `RadioGroup` (flutter/flutter#178618) 2025-11-18 [email protected] Add framework-side hitTestBehavior support for Semantics widget and apply to ModalRoute (flutter/flutter#177570) 2025-11-18 [email protected] Fix deprecation warning in some API examples using RadioListTile (flutter/flutter#178635) 2025-11-18 [email protected] Roll Skia from 47fd0d9b1044 to d7268f8245f2 (6 revisions) (flutter/flutter#178695) 2025-11-18 [email protected] Roll Dart SDK from cf94632d94a1 to a8ad764281e3 (1 revision) (flutter/flutter#178694) 2025-11-18 [email protected] [fuchsia] Add wrapper for zx_iob_writev (flutter/flutter#178626) 2025-11-17 [email protected] Make a11y `computeChildGeometry` slightly faster (flutter/flutter#177477) 2025-11-17 [email protected] Fix DropdownMenu width when decorationBuilder provides label (flutter/flutter#178465) 2025-11-17 [email protected] Add DropdownMenuFormField.decorationBuilder (flutter/flutter#178640) 2025-11-17 [email protected] Roll Skia from 84c83c0dfb4a to 47fd0d9b1044 (4 revisions) (flutter/flutter#178673) 2025-11-17 [email protected] Small cleanup in `AndroidTouchProcessor.java` (flutter/flutter#178574) 2025-11-17 [email protected] Remove unnecessary `final` modifier in `StandardMessageCodec.java` (flutter/flutter#178598) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…companion watch apps defined by only the project info file. (flutter#176832) (Please be generous for some typos and grammar error in sentences below. English is not my mother tongue) TRDR : This patch fixes flutter run(and might be flutter build too) failure on iOS flutter apps with companion watchOS app in case the WKCompanionAppBundleIdentifier value is defined by xcode project configuration and uses different app bundle id by scheme(which happens when you do something like com.myapp.app1.dev things for scheme bundle id) This change checks default scheme (the scheme with corresponding name for the debug/release mode and selected build flavor.) in the build settings check step of containsWatchCompanion function. current code of containsWatchCompanion function works like below 1. check all default Info.plist file's content of all targets to determine if the project has watchOS companion apps. (this doesn't work well in mordern xcode settings when they use multi plist files which are selected on build time by build configuration. Sometimes, the default Info.plist file doesn't even exist in the project.) 2. check if "WKCompanionAppBundleIdentifier" is included in the xcode project info file(the ios/Runner.xcodeproj/project.pbxproj file in case of iOS project generated by flutter) 3. If "WKCompanionAppBundleIdentifier" has found in the project info file, check build configuration variables of every single scheme but the current target scheme if they have config value with key "INFOPLIST_KEY_WKCompanionAppBundleIdentifier" identical to current build configuration's bundle identifier returned by productBundleIdentifier@xcode_project.dart function. I believe The third step causes many problems reported in some issue and pr, saying iOS app with companion watchOS app fails on build or run. flutter#160622 flutter#172436 In my case, My iOS project had multiple schemes which are linked to different build configurations, but using single Runner setting per app. because we exclude current scheme for the check, we get all the INFOPLIST_KEY_WKCompanionAppBundleIdentifier values except the one which should be same with the identifier returned by productBundleIdentifier@xcode_project.dart function. that is because companion watch apps doesn't have to have same WKCompanionAppBundleIdentifier with other scheme's main app. We have to check the default scheme to see watchOS companion app`s WKCompanionAppBundleIdentifier, not other scheme. (other schemes can have slightly different or totally different bundle id. that was to support different environment systems like dev, prod in my case) as a result, flutter run gave me WatchOS app built for device target iOS/iPad, not Watch. which caused problem during installation of iOS app to a simulator because the embeded Watch App was in invalid format. I found this by inspecting Info.plist of generated watchOS app. below is part of the flutter run verbose log with failure caused by old code. [+1154 ms] An error was encountered processing the command (domain=IXUserPresentableErrorDomain, code=1): App installation failed: ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try again later" in korean) Found WatchKit 2.0 app at /Users/javalia/Library/Developer/CoreSimulator/Devices/071691B3-7901-47E5-9B38-4D5B799F3530/data/Library/Caches/com.apple.mobile.installd.staging/temp.8HZIEG/extracted/Payload/Runner.app/Watch/bora Watch App.app but it does not have a WKWatchKitApp or WKApplication key set to true in its Info.plist Underlying error (domain=IXUserPresentableErrorDomain, code=1): ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try it later" in korean) I suggest this change with two reasons : 1. I think forcing watchOS app makers split their runner configurations to support watch companion app is something not recommendable/not good to force as a convention. (Which is implied in the comment which is removed by this pr, and could be one of the valid detouring. some people in this issue flutter#160622 said that a detouring is adding of dummy WKCompanionAppBundleIdentifier configuration in iOS app, which should be in only watchOS apps in normal.) 2. The function should work as it's name implies, so I guess it should not omit default scheme during check. Matching function's behavior with it's name will be likely to reduce potential errors caused by this change while fixing problems. ## Pre-launch Checklist - [ X ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ X ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ X ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ X ] I signed the [CLA]. - [ X ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: hellohuanlin <[email protected]>
|
@vashworth could you cherry-pick this for a hotfix on stable? |
…companion watch apps defined by only the project info file. (flutter#176832) (Please be generous for some typos and grammar error in sentences below. English is not my mother tongue) TRDR : This patch fixes flutter run(and might be flutter build too) failure on iOS flutter apps with companion watchOS app in case the WKCompanionAppBundleIdentifier value is defined by xcode project configuration and uses different app bundle id by scheme(which happens when you do something like com.myapp.app1.dev things for scheme bundle id) This change checks default scheme (the scheme with corresponding name for the debug/release mode and selected build flavor.) in the build settings check step of containsWatchCompanion function. current code of containsWatchCompanion function works like below 1. check all default Info.plist file's content of all targets to determine if the project has watchOS companion apps. (this doesn't work well in mordern xcode settings when they use multi plist files which are selected on build time by build configuration. Sometimes, the default Info.plist file doesn't even exist in the project.) 2. check if "WKCompanionAppBundleIdentifier" is included in the xcode project info file(the ios/Runner.xcodeproj/project.pbxproj file in case of iOS project generated by flutter) 3. If "WKCompanionAppBundleIdentifier" has found in the project info file, check build configuration variables of every single scheme but the current target scheme if they have config value with key "INFOPLIST_KEY_WKCompanionAppBundleIdentifier" identical to current build configuration's bundle identifier returned by productBundleIdentifier@xcode_project.dart function. I believe The third step causes many problems reported in some issue and pr, saying iOS app with companion watchOS app fails on build or run. flutter#160622 flutter#172436 In my case, My iOS project had multiple schemes which are linked to different build configurations, but using single Runner setting per app. because we exclude current scheme for the check, we get all the INFOPLIST_KEY_WKCompanionAppBundleIdentifier values except the one which should be same with the identifier returned by productBundleIdentifier@xcode_project.dart function. that is because companion watch apps doesn't have to have same WKCompanionAppBundleIdentifier with other scheme's main app. We have to check the default scheme to see watchOS companion app`s WKCompanionAppBundleIdentifier, not other scheme. (other schemes can have slightly different or totally different bundle id. that was to support different environment systems like dev, prod in my case) as a result, flutter run gave me WatchOS app built for device target iOS/iPad, not Watch. which caused problem during installation of iOS app to a simulator because the embeded Watch App was in invalid format. I found this by inspecting Info.plist of generated watchOS app. below is part of the flutter run verbose log with failure caused by old code. [+1154 ms] An error was encountered processing the command (domain=IXUserPresentableErrorDomain, code=1): App installation failed: ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try again later" in korean) Found WatchKit 2.0 app at /Users/javalia/Library/Developer/CoreSimulator/Devices/071691B3-7901-47E5-9B38-4D5B799F3530/data/Library/Caches/com.apple.mobile.installd.staging/temp.8HZIEG/extracted/Payload/Runner.app/Watch/bora Watch App.app but it does not have a WKWatchKitApp or WKApplication key set to true in its Info.plist Underlying error (domain=IXUserPresentableErrorDomain, code=1): ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try it later" in korean) I suggest this change with two reasons : 1. I think forcing watchOS app makers split their runner configurations to support watch companion app is something not recommendable/not good to force as a convention. (Which is implied in the comment which is removed by this pr, and could be one of the valid detouring. some people in this issue flutter#160622 said that a detouring is adding of dummy WKCompanionAppBundleIdentifier configuration in iOS app, which should be in only watchOS apps in normal.) 2. The function should work as it's name implies, so I guess it should not omit default scheme during check. Matching function's behavior with it's name will be likely to reduce potential errors caused by this change while fixing problems. ## Pre-launch Checklist - [ X ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ X ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ X ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ X ] I signed the [CLA]. - [ X ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: hellohuanlin <[email protected]>
…companion watch apps defined by only the project info file. (flutter#176832) (Please be generous for some typos and grammar error in sentences below. English is not my mother tongue) TRDR : This patch fixes flutter run(and might be flutter build too) failure on iOS flutter apps with companion watchOS app in case the WKCompanionAppBundleIdentifier value is defined by xcode project configuration and uses different app bundle id by scheme(which happens when you do something like com.myapp.app1.dev things for scheme bundle id) This change checks default scheme (the scheme with corresponding name for the debug/release mode and selected build flavor.) in the build settings check step of containsWatchCompanion function. current code of containsWatchCompanion function works like below 1. check all default Info.plist file's content of all targets to determine if the project has watchOS companion apps. (this doesn't work well in mordern xcode settings when they use multi plist files which are selected on build time by build configuration. Sometimes, the default Info.plist file doesn't even exist in the project.) 2. check if "WKCompanionAppBundleIdentifier" is included in the xcode project info file(the ios/Runner.xcodeproj/project.pbxproj file in case of iOS project generated by flutter) 3. If "WKCompanionAppBundleIdentifier" has found in the project info file, check build configuration variables of every single scheme but the current target scheme if they have config value with key "INFOPLIST_KEY_WKCompanionAppBundleIdentifier" identical to current build configuration's bundle identifier returned by productBundleIdentifier@xcode_project.dart function. I believe The third step causes many problems reported in some issue and pr, saying iOS app with companion watchOS app fails on build or run. flutter#160622 flutter#172436 In my case, My iOS project had multiple schemes which are linked to different build configurations, but using single Runner setting per app. because we exclude current scheme for the check, we get all the INFOPLIST_KEY_WKCompanionAppBundleIdentifier values except the one which should be same with the identifier returned by productBundleIdentifier@xcode_project.dart function. that is because companion watch apps doesn't have to have same WKCompanionAppBundleIdentifier with other scheme's main app. We have to check the default scheme to see watchOS companion app`s WKCompanionAppBundleIdentifier, not other scheme. (other schemes can have slightly different or totally different bundle id. that was to support different environment systems like dev, prod in my case) as a result, flutter run gave me WatchOS app built for device target iOS/iPad, not Watch. which caused problem during installation of iOS app to a simulator because the embeded Watch App was in invalid format. I found this by inspecting Info.plist of generated watchOS app. below is part of the flutter run verbose log with failure caused by old code. [+1154 ms] An error was encountered processing the command (domain=IXUserPresentableErrorDomain, code=1): App installation failed: ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try again later" in korean) Found WatchKit 2.0 app at /Users/javalia/Library/Developer/CoreSimulator/Devices/071691B3-7901-47E5-9B38-4D5B799F3530/data/Library/Caches/com.apple.mobile.installd.staging/temp.8HZIEG/extracted/Payload/Runner.app/Watch/bora Watch App.app but it does not have a WKWatchKitApp or WKApplication key set to true in its Info.plist Underlying error (domain=IXUserPresentableErrorDomain, code=1): ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean) 나중에 다시 시도하십시오. (which says "try it later" in korean) I suggest this change with two reasons : 1. I think forcing watchOS app makers split their runner configurations to support watch companion app is something not recommendable/not good to force as a convention. (Which is implied in the comment which is removed by this pr, and could be one of the valid detouring. some people in this issue flutter#160622 said that a detouring is adding of dummy WKCompanionAppBundleIdentifier configuration in iOS app, which should be in only watchOS apps in normal.) 2. The function should work as it's name implies, so I guess it should not omit default scheme during check. Matching function's behavior with it's name will be likely to reduce potential errors caused by this change while fixing problems. ## Pre-launch Checklist - [ X ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ X ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ X ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ X ] I signed the [CLA]. - [ X ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: hellohuanlin <[email protected]>




(Please be generous for some typos and grammar error in sentences below. English is not my mother tongue)
TRDR : This patch fixes flutter run(and might be flutter build too) failure on iOS flutter apps with companion watchOS app in case the WKCompanionAppBundleIdentifier value is defined by xcode project configuration and uses different app bundle id by scheme(which happens when you do something like com.myapp.app1.dev things for scheme bundle id)
This change checks default scheme (the scheme with corresponding name for the debug/release mode and selected build flavor.) in the build settings check step of containsWatchCompanion function.
current code of containsWatchCompanion function works like below
check all default Info.plist file's content of all targets to determine if the project has watchOS companion apps.
(this doesn't work well in mordern xcode settings when they use multi plist files which are selected on build time by build configuration. Sometimes, the default Info.plist file doesn't even exist in the project.)
check if "WKCompanionAppBundleIdentifier" is included in the xcode project info file(the ios/Runner.xcodeproj/project.pbxproj file in case of iOS project generated by flutter)
If "WKCompanionAppBundleIdentifier" has found in the project info file,
check build configuration variables of every single scheme but the current target scheme if they have config value with key "INFOPLIST_KEY_WKCompanionAppBundleIdentifier" identical to current build configuration's bundle identifier returned by productBundleIdentifier@xcode_project.dart function.
I believe The third step causes many problems reported in some issue and pr, saying iOS app with companion watchOS app fails on build or run.
#160622
#172436
In my case, My iOS project had multiple schemes which are linked to different build configurations, but using single Runner setting per app.
because we exclude current scheme for the check, we get all the INFOPLIST_KEY_WKCompanionAppBundleIdentifier values except the one which should be same with the identifier returned by productBundleIdentifier@xcode_project.dart function.
that is because companion watch apps doesn't have to have same WKCompanionAppBundleIdentifier with other scheme's main app. We have to check the default scheme to see watchOS companion app`s WKCompanionAppBundleIdentifier, not other scheme. (other schemes can have slightly different or totally different bundle id. that was to support different environment systems like dev, prod in my case)
as a result, flutter run gave me WatchOS app built for device target iOS/iPad, not Watch. which caused problem during installation of iOS app to a simulator because the embeded Watch App was in invalid format. I found this by inspecting Info.plist of generated watchOS app.
below is part of the flutter run verbose log with failure caused by old code.
[+1154 ms] An error was encountered processing the command (domain=IXUserPresentableErrorDomain, code=1):
App installation failed: ‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean)
나중에 다시 시도하십시오. (which says "try again later" in korean)
Found WatchKit 2.0 app at /Users/javalia/Library/Developer/CoreSimulator/Devices/071691B3-7901-47E5-9B38-4D5B799F3530/data/Library/Caches/com.apple.mobile.installd.staging/temp.8HZIEG/extracted/Payload/Runner.app/Watch/bora Watch App.app but it does not have a WKWatchKitApp or WKApplication key set to true in its Info.plist
Underlying error (domain=IXUserPresentableErrorDomain, code=1):
‘Bora Debug-dev’을(를) 설치할 수 없음 (which says "cannot install" in korean)
나중에 다시 시도하십시오. (which says "try it later" in korean)
I suggest this change with two reasons :
I think forcing watchOS app makers split their runner configurations to support watch companion app is something not recommendable/not good to force as a convention.
(Which is implied in the comment which is removed by this pr, and could be one of the valid detouring.
some people in this issue Unable To Run Flutter App With Apple Watch Extension After Upgrading 3.27.0 #160622 said that a detouring is adding of dummy WKCompanionAppBundleIdentifier configuration in iOS app, which should be in only watchOS apps in normal.)
The function should work as it's name implies, so I guess it should not omit default scheme during check. Matching function's behavior with it's name will be likely to reduce potential errors caused by this change while fixing problems.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.