从 Xcode 12 CarPlay 模拟器启动时,CarPlay 停车应用程序崩溃
Posted
技术标签:
【中文标题】从 Xcode 12 CarPlay 模拟器启动时,CarPlay 停车应用程序崩溃【英文标题】:CarPlay parking app crashed when launching from Xcode 12 CarPlay simulator 【发布时间】:2020-10-06 04:08:59 【问题描述】:我们正在为 CarPlay 扩展我们的 Xamarin.ios 应用(由 Xamarin.Forms 提供)。打开 CarPlay 模拟器时,应用程序在 CarPlay 屏幕上显示,但从 CarPlay 模拟器启动时崩溃。
下面是Info.plist场景配置:
<key>UIApplicationSceneManifest</key>
<dict>
<key>UISceneConfigurations</key>
<dict>
<key>CPTemplateApplicationSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationScene</string>
<key>UISceneConfigurationName</key>
<string>ParkingPlus-Car</string>
<key>UISceneDelegateClassName</key>
<string>ParkingPlus.AppSceneDelegateImp</string>
</dict>
</array>
</dict>
</dict>
“ParkingPlus”是应用包名称!
AppSceneDelegateImp 类(在 iOS 项目的根文件夹下
public class AppSceneDelegateImp : UIResponder, ICPTemplateApplicationSceneDelegate
private CPInterfaceController _interfaceController;
public async void DidConnect(CPTemplateApplicationScene templateApplicationScene, CPInterfaceController interfaceController)
_interfaceController = interfaceController;
.....
public void DidDisconnect(CPTemplateApplicationScene templateApplicationScene, CPInterfaceController interfaceController)
_interfaceController.Dispose();
_interfaceController = null;
当我如下覆盖 AppDelegate.GetConfiguration 时
public override UISceneConfiguration GetConfiguration(UIApplication application, UISceneSession connectingSceneSession, UISceneConnectionOptions options)
...
点击 CarPlay 上的应用程序图标时,将调用该方法。但是当我检查connectingSceneSession时,我发现变量成员内部有一些异常。 “CPTemplateApplicationSceneSessionRoleApplication 在此平台上没有关联的枚举值”。
Screenshot for connectingSceneSession inspection
如果继续,则应用程序将抛出异常,这似乎表明 SceneDelegate 未正确加载: Exception
我的环境: Visual Studio for mac 版本 8.7.8 Xamarin.iOS 14.0.0 Xcode 12.0
在绑定 iOS 库时,Xamarin.ios 14 似乎缺少某些内容。任何人都有类似的问题。我做错了什么还是有什么其他方法可以通过 Xcode/swift 实现 CarPlay 部分功能,同时将移动应用程序保留在 Xamarin.Forms/Xamarin.iOS 上?
感谢任何 cmets 或帮助。
【问题讨论】:
这种崩溃只发生在 iOS 14 中吗?It seems like Xamarin.ios 14 missing something when binding the iOS library.
,如果您认为是绑定 iOS 库引起的,您可以在 Github 中使用这些信息打开问题。
@JackHua-MSFT,谢谢。在我在这里提出问题之前一周,我确实提出了一个错误。团队将修复 Xamarin.iOS 中的错误。我被告知一种方法。当我让它工作正常时,我会在这里回答。
【参考方案1】:
在 Xamarin.ios 团队的帮助下,以下是此问题的完整解决方案: https://github.com/xamarin/xamarin-macios/issues/9749
-
为两种情况(CarPlay 和手机)创建场景配置的 AppDelegate
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public extern static IntPtr IntPtr_objc_msgSend_IntPtr_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2);
public static UISceneConfiguration Create(string? name, NSString sessionRole)
global::UIKit.UIApplication.EnsureUIThread();
var nsname = NSString.CreateNative(name);
UISceneConfiguration sceneConfig;
sceneConfig = Runtime.GetNSObject<UISceneConfiguration>(IntPtr_objc_msgSend_IntPtr_IntPtr(Class.GetHandle("UISceneConfiguration"), Selector.GetHandle("configurationWithName:sessionRole:"), nsname, sessionRole.Handle));
NSString.ReleaseNative(nsname);
//Because only the CarPlay scene will be here to create a scene configuration
//We need manually assign the CarPlay scene delegate here!
sceneConfig.DelegateType = typeof(AppCarSceneDelegateImp);
return sceneConfig!;
[Export("application:configurationForConnectingSceneSession:options:")]
public UISceneConfiguration GetConfiguration(UIApplication application, UISceneSession connectingSceneSession, UISceneConnectionOptions options)
UIWindowSceneSessionRole sessionRole;
bool isCarPlaySceneSession = false;
try
//When the connecting scene is a CarPlay scene, an expected exception will be thrown
//Under this moment from Xamarin.iOS.
sessionRole = connectingSceneSession.Role;
catch (NotSupportedException ex)
if (!string.IsNullOrEmpty(ex.Message) &&
ex.Message.Contains("CPTemplateApplicationSceneSessionRoleApplication"))
isCarPlaySceneSession = true;
if (isCarPlaySceneSession && UIDevice.CurrentDevice.CheckSystemVersion(14,0))
return Create("Car", CarPlay.CPTemplateApplicationScene.SessionRoleApplication);
else
//If it is phone scene, we need the regular UIWindow scene
UISceneConfiguration phoneScene = new UISceneConfiguration("Phone", UIWindowSceneSessionRole.Application);
//And assign the scene delegate here.
phoneScene.DelegateType = typeof(AppWindowSceneDelegateImp);
return phoneScene;
-
创建一个 UIWindowScene 委托来处理常规的移动场景窗口
public class AppWindowSceneDelegateImp : UISceneDelegate
public override void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
var windowScene = scene as UIWindowScene;
if (windowScene != null)
//Assign the Xamarin.iOS app window to this scene
UIApplication.SharedApplication.KeyWindow.WindowScene = windowScene;
UIApplication.SharedApplication.KeyWindow.MakeKeyAndVisible();
【讨论】:
太棒了 +1,您能否展示两个 AppDelegate(电话/汽车)以及 Xamarin 如何加载“主”AppDelegate 来决定加载哪个 AppDelegate? @Suplanus,将调用 AppDelegate.GetConfiguration() 并确定将加载相应的 UIScene(CarPlay 或 Phone)并返回 UISceneConfiguration。在返回 UISceneConfiguration 之前的该方法中,您必须分配场景委托实现。这就是你需要做的。上面的代码 sn -p 包含了所有必要的代码。 谢谢。我在这个 repo 中做了一些测试:github.com/Suplanus/Xamarin.Demo.Carplay/tree/dev 但它没有按预期工作。 @Suplanus,您在 info.plist 文件中是否有正确的 CarPlay 权利和设置? 我想是的,你可以在 repo 中看到它。我也认为模拟器不需要应用程序的权利(只有设备需要这个)。以上是关于从 Xcode 12 CarPlay 模拟器启动时,CarPlay 停车应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
将 CarPlay 模拟器添加到我的 React Native 应用程序
MPPlayableContentDataSource 调用不一致
从 Xcode 启动 iOS 模拟器并得到黑屏,然后 Xcode 挂起并且无法停止任务