Visual Studio 是否可以使用Xamarin工具开发CarPlay应用程序

j1dl9f46  于 2022-11-25  发布在  其他
关注(0)|答案(3)|浏览(195)

正如标题所说,我正在尝试为我的汽车构建一个应用程序。我只在Xamarin Docs中看到了CarPlay的简短提及。
那么,有没有可能用Xamarin和Visual Studio工具开发一个CarPlay应用程序呢?
另外,我做了一些研究,虽然你可以为CarPlay开发应用程序,但苹果只允许导航和流媒体应用程序。所以这对我想做的事情来说是完全不可能的。

kxeu7u2r

kxeu7u2r1#

是的,这是可能的。我做了一个blog post和一个关于GitHub的例子。
这里的答案简单地说:
在我们的iOS项目中,我们使用CarIntegrationBridge.Init();在AppDelegate.cs中初始化代理。
代表注册如下:

public class CarIntegrationBridge : ICarIntegrationBridge
{
  public static void Init()
  {
    PlayableContentDelegate playableContentDelegate = new PlayableContentDelegate();
    MPPlayableContentManager.Shared.Delegate = playableContentDelegate;
    PlayableContentDataSource playableContentDataSource = new PlayableContentDataSource();
    MPPlayableContentManager.Shared.DataSource = playableContentDataSource;
  }
}

现在我们定义数据源。在我的示例中,我添加了带有name和url的广播电台。我们必须定义菜单项计数以及菜单项的显示方式(name、icon ...):

internal class PlayableContentDataSource : MPPlayableContentDataSource
{
  public static List<Station> Stations = new List<Station>
  {
    new Station{Name = "Rainbow radio", Url = "https://stream.rockantenne.de/rockantenne/stream/mp3"},
    new Station{Name = "Unicorn radio", Url = "http://play.rockantenne.de/heavy-metal.m3u"}
  };
  
  public override MPContentItem ContentItem(NSIndexPath indexPath)
  {
    var station = Stations[indexPath.Section];
    var item = new MPContentItem(station.Url);
    item.Title = station.Name;
    item.Playable = true;
    item.StreamingContent = true;
    var artWork = GetImageFromUrl("station.png");
    if (artWork != null)
    {
      item.Artwork = artWork;
    }
    return item;
  }
  public override nint NumberOfChildItems(NSIndexPath indexPath)
  {
    if (indexPath.GetIndexes().Length == 0)
    {
      return Stations.Count;
    }
    throw new NotImplementedException();
  }
  private MPMediaItemArtwork GetImageFromUrl(string imagePath)
  {
    MPMediaItemArtwork result = null;
    try
    {
      using (var nsUrl = new NSUrl(imagePath))
      {
        using (var data = NSData.FromUrl(nsUrl))
        {
          var image = UIImage.LoadFromData(data);
          result = new MPMediaItemArtwork(image);
        }
      }
    }
    catch
    {
      UIImage image = UIImage.FromBundle(imagePath);
      if (image != null)
      {
        result = new MPMediaItemArtwork(image);
      }
    }
    return result;
  }
}

现在我们必须决定如果一个项目被录制了,我们要做什么。模拟器有一个不同于真实的设备的行为。所以我破解了一个调用NowPlayingScene的解决方案。

internal class PlayableContentDelegate : MPPlayableContentDelegate
{
  public override void InitiatePlaybackOfContentItem(
    MPPlayableContentManager contentManager, NSIndexPath indexPath, Action<NSError> completionHandler)
  {
    Execute(contentManager, indexPath);
    completionHandler?.Invoke(null);
  }
  private void Execute(MPPlayableContentManager contentManager, NSIndexPath indexPath)
  {
    DispatchQueue.MainQueue.DispatchAsync(async () => await ItemSelectedAsync(contentManager, indexPath));
  }
  private async Task ItemSelectedAsync(MPPlayableContentManager contentManager, NSIndexPath indexPath)
  {
    // Play
    var station = PlayableContentDataSource.Stations[indexPath.Section];
    await CrossMediaManager.Current.Play(station.Url);
    // Set playing identifier
    MPContentItem item = contentManager.DataSource.ContentItem(indexPath);
    contentManager.NowPlayingIdentifiers = new[] { item.Identifier };
    // Update on simulator
    if (DeviceInfo.DeviceType == DeviceType.Virtual)
    {
      InvokeOnMainThread(() =>
      {
        UIApplication.SharedApplication.EndReceivingRemoteControlEvents();
        UIApplication.SharedApplication.BeginReceivingRemoteControlEvents();
      });
    }
  }
}

要重新加载数据(例如,如果更改站点),必须调用以下命令:

public void ReloadStations()
{
  MPPlayableContentManager.Shared?.ReloadData();
}
vlju58qv

vlju58qv2#

我设法用Xamarin构建了一个苹果CarPlay应用程序,尽管我使用了与Suplanus完全不同的方法,因为我没有创建音乐应用程序,我的方法更接近于苹果docs的方法。
首先确保您的预置配置文件具有正确的CarPlay权限。
将授权添加到Entitlements.plist文件。
在你的info.plist中,就像苹果文档中建议的那样:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UISceneConfigurations</key>
    <dict>
        <!-- Device Scene -->
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Default Configuration</string>
                <key>UISceneDelegateClassName</key>
                <string>DeviceSceneDelegate</string>
            </dict>
        </array>
        <!-- Carplay Scene -->
        <key>CPTemplateApplicationSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneClassName</key>
                <string>CPTemplateApplicationScene</string>
                <key>UISceneConfigurationName</key>
                <string>YourAppName-Car</string>
                <key>UISceneDelegateClassName</key>
                <string>YourAppName.CarPlaySceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>

然后,我使用this线程中建议的解决方案将CarPlay发送给正确的代理,并进行了以下更改:
1.在我的CarPlaySceneDelegate类上,直接从CPTemplateApplicationSceneDelegate继承。
1.请改为实作DidConnect和DidDisconnect的覆写方法。

  1. UIWindowSceneSessionRole.CarTemplateApplication现在已添加到枚举中,因此如果它是AppDelegate类的GetConfiguration重写中的CarPlay应用程序,请使用该枚举而不是签入catch。
    1.如果不是CarPlay应用程序,则返回GetConfiguration覆盖中的默认配置。
    您会注意到,苹果开发者文档中提到的所有类都可以在Xamarin.iOS中的CarPlay库中找到,因此将swift代码转换为C#以创建和显示所需的模板并不太困难。
    最后,使用此解决方案从设备场景代理启动Xamarin.Forms应用程序,而不是在打开应用程序时看到手机上的空白屏幕。
    希望这有助于一点,你不必挣扎,因为我没有得到它的工作!
c2e8gylq

c2e8gylq3#

也许这个https://forums.xamarin.com/discussion/144790/android-auto-ios-car-play回答了这个问题?
Car Play似乎是苹果公司的一个私有框架,而且XCode也没有相关的文档。
对于Android Auto,请转到github,搜索项目Xamarin_Android_Auto_Test

相关问题