Add Live Activity for level sensor (surfaces on CarPlay automatically)

Replaces the ActivityKit boilerplate with a real lock screen/Dynamic
Island UI driven by live pitch/roll readings, toggled from the
leveling device's detail screen. Since iOS 17 shows any running Live
Activity on CarPlay's dashboard without a dedicated CarPlay app entitlement,
this covers the requested CarPlay use case without one.

Also fixes the widget extension never being embedded into the app
(missing Embed Foundation Extensions build phase and target
dependency), which meant no widget or Live Activity could ever have
rendered regardless of code changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
fototeddy
2026-09-04 22:39:01 +02:00
co-authored by Claude Sonnet 5
parent da64b1b6bd
commit bfe2b00a5c
7 changed files with 270 additions and 40 deletions
+42
View File
@@ -22,6 +22,9 @@
9DB55BAF3048B29B00CFD174 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DB55BAE3048B29B00CFD174 /* WidgetKit.framework */; };
9DB55BB13048B29B00CFD174 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DB55BB03048B29B00CFD174 /* SwiftUI.framework */; };
AA0000000000000000000027 /* VanAligneWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000016 /* VanAligneWatch.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AA0000000000000000000047 /* VanAligneiOSWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 9DB55BAC3048B29B00CFD174 /* VanAligneiOSWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AA0000000000000000000043 /* ActivityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000042 /* ActivityKit.framework */; };
AA0000000000000000000044 /* ActivityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA0000000000000000000042 /* ActivityKit.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -32,9 +35,27 @@
remoteGlobalIDString = AA0000000000000000000022;
remoteInfo = CamperMonitorWatch;
};
AA0000000000000000000045 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = AA0000000000000000000009 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9DB55BAB3048B29B00CFD174;
remoteInfo = VanAligneiOSWidgetExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
AA0000000000000000000048 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
AA0000000000000000000047 /* VanAligneiOSWidgetExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
AA0000000000000000000026 /* Embed Watch Content */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -59,6 +80,7 @@
AA0000000000000000000001 /* VanAligne.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VanAligne.app; sourceTree = BUILT_PRODUCTS_DIR; };
AA0000000000000000000016 /* VanAligneWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VanAligneWatch.app; sourceTree = BUILT_PRODUCTS_DIR; };
AA0000000000000000000032 /* VanAligneComplication.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = VanAligneComplication.appex; sourceTree = BUILT_PRODUCTS_DIR; };
AA0000000000000000000042 /* ActivityKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActivityKit.framework; path = System/Library/Frameworks/ActivityKit.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
@@ -100,6 +122,11 @@
path = CamperMonitorComplication;
sourceTree = "<group>";
};
AA0000000000000000000041 /* SharedActivity */ = {
isa = PBXFileSystemSynchronizedRootGroup;
path = SharedActivity;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
@@ -109,6 +136,7 @@
files = (
9DB55BB13048B29B00CFD174 /* SwiftUI.framework in Frameworks */,
9DB55BAF3048B29B00CFD174 /* WidgetKit.framework in Frameworks */,
AA0000000000000000000044 /* ActivityKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -116,6 +144,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AA0000000000000000000043 /* ActivityKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -141,6 +170,7 @@
children = (
9DB55BAE3048B29B00CFD174 /* WidgetKit.framework */,
9DB55BB03048B29B00CFD174 /* SwiftUI.framework */,
AA0000000000000000000042 /* ActivityKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -152,6 +182,7 @@
AA0000000000000000000017 /* CamperMonitorWatch */,
AA0000000000000000000033 /* CamperMonitorComplication */,
AA0000000000000000000018 /* Shared */,
AA0000000000000000000041 /* SharedActivity */,
AA0000000000000000000031 /* Config */,
9DB55BB23048B29B00CFD174 /* VanAligneiOSWidget */,
9DB55BAD3048B29B00CFD174 /* Frameworks */,
@@ -198,6 +229,7 @@
);
fileSystemSynchronizedGroups = (
9DB55BB23048B29B00CFD174 /* VanAligneiOSWidget */,
AA0000000000000000000041 /* SharedActivity */,
);
name = VanAligneiOSWidgetExtension;
packageProductDependencies = (
@@ -214,15 +246,18 @@
AA0000000000000000000003 /* Frameworks */,
AA0000000000000000000008 /* Resources */,
AA0000000000000000000026 /* Embed Watch Content */,
AA0000000000000000000048 /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
AA0000000000000000000029 /* PBXTargetDependency */,
AA0000000000000000000046 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
AA0000000000000000000002 /* CamperMonitor */,
AA0000000000000000000018 /* Shared */,
AA0000000000000000000041 /* SharedActivity */,
);
name = VanAligne;
productName = CamperMonitor;
@@ -398,6 +433,11 @@
target = AA0000000000000000000022 /* VanAligneWatch */;
targetProxy = AA0000000000000000000028 /* PBXContainerItemProxy */;
};
AA0000000000000000000046 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9DB55BAB3048B29B00CFD174 /* VanAligneiOSWidgetExtension */;
targetProxy = AA0000000000000000000045 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
@@ -603,6 +643,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "VanAligne Pro";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "Zum Auslesen von Victron-Geraeten und dem Daly BMS per Bluetooth.";
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
@@ -635,6 +676,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "VanAligne Pro";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "Zum Auslesen von Victron-Geraeten und dem Daly BMS per Bluetooth.";
INFOPLIST_KEY_NSSupportsLiveActivities = YES;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";