CarPlay停车应用程序在从Xcode 12 CarPlay模拟器启动时崩溃



我们正在为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在此平台上没有关联的枚举值";。

连接场景会话检查的屏幕截图

如果继续,则应用程序将抛出一个异常,该异常似乎表明SceneDelegate未正确加载:异常

我的环境:Visual studio for mac 8.7.8版Xamarin.iOS 14.0.0Xcode 12.0

Xamarin.ios 14在绑定ios库时似乎缺少了一些东西。任何人都有类似的问题。我做错了什么吗?或者我有没有其他方法可以通过Xcode/swift实现CarPlay部件功能,同时将移动应用程序保留在Xamarin.Forms/Xamarin.iOS上?

感谢任何意见或帮助。

在Xamarin.ios团队的帮助下,以下是该问题的完整解决方案:https://github.com/xamarin/xamarin-macios/issues/9749

  1. AppDelegate为两种情况(CarPlay和phone(创建场景配置

[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;
}
}
  1. 创建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();
}
}
}

最新更新