Flutter车载互联插件flutter_carplay的使用

Flutter车载互联插件flutter_carplay的使用

Flutter CarPlay插件flutter_carplay使开发者能够将Flutter应用与CarPlay集成,从而在汽车中安全地使用iPhone应用。本文档将详细介绍如何使用该插件,并提供一个完整的示例demo。

概述

flutter_carplay插件支持iOS 14.0及以上版本,允许开发者创建基于模板的用户界面。以下是插件目前支持的功能:

  • Action Sheet Template
  • Alert Template
  • Grid Template
  • List Template
  • Tab Bar Template
  • Information Template (由OSch11贡献)
  • Point of Interest Template (由OSch11贡献)

开始使用

安装步骤

  1. 设置iOS平台版本: 在ios/Podfile文件中设置iOS平台版本为14.0。

    # Uncomment this line to define a global platform for your project
    + platform :ios, '14.0'
    - # platform :ios, '9.0'
    

    更新Pod文件:

    // For Apple Silicon M1 chips:
    $ cd ios && arch -x86_64 pod install --repo-update
    
    // For Intel chips:
    $ cd ios && pod install --repo-update
    
  2. 修改AppDelegate.swift: 打开ios/Runner.xcworkspace中的AppDelegate.swift文件,删除以下代码并替换:

    import UIKit
    import Flutter
    
    [@UIApplicationMain](/user/UIApplicationMain)
    [@objc](/user/objc) class AppDelegate: FlutterAppDelegate {
      override func application( _ application: UIApplication,
                                didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    -   GeneratedPluginRegistrant.register(with: self)
    -   return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    +   return true
      }
    }
    
  3. 创建SceneDelegate.swift: 在Runner文件夹中创建SceneDelegate.swift文件,并添加以下代码:

    [@available](/user/available)(iOS 13.0, *)
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
        var window: UIWindow?
    
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            guard let windowScene = scene as? UIWindowScene else { return }
    
            window = UIWindow(windowScene: windowScene)
    
            let flutterEngine = FlutterEngine(name: "SceneDelegateEngine")
            flutterEngine.run()
            GeneratedPluginRegistrant.register(with: flutterEngine)
            let controller = FlutterViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
            window?.rootViewController = controller
            window?.makeKeyAndVisible()
        }
    }
    
  4. 配置Info.plist: 打开Info.plist文件,并添加以下内容:

    <key>UIApplicationSceneManifest</key>
    <dict>
      <key>UIApplicationSupportsMultipleScenes</key>
      <true/>
      <key>UISceneConfigurations</key>
      <dict>
        <key>CPTemplateApplicationSceneSessionRoleApplication</key>
        <array>
          <dict>
            <key>UISceneConfigurationName</key>
            <string>CarPlay Configuration</string>
            <key>UISceneDelegateClassName</key>
            <string>flutter_carplay.FlutterCarPlaySceneDelegate</string>
          </dict>
        </array>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
          <dict>
            <key>UISceneConfigurationName</key>
            <string>Default Configuration</string>
            <key>UISceneDelegateClassName</key>
            <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
            <key>UISceneStoryboardFile</key>
            <string>Main</string>
          </dict>
        </array>
      </dict>
    </dict>
    

示例Demo

以下是一个完整的Flutter应用示例,展示了如何使用flutter_carplay插件:

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:flutter_carplay/flutter_carplay.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  CPConnectionStatusTypes connectionStatus = CPConnectionStatusTypes.unknown;
  final FlutterCarplay _flutterCarplay = FlutterCarplay();

  [@override](/user/override)
  void initState() {
    super.initState();

    final List<CPListSection> section1Items = [];
    section1Items.add(CPListSection(
      items: [
        CPListItem(
          text: "Item 1",
          detailText: "Detail Text",
          onPress: (complete, self) {
            self.setDetailText("You can change the detail text.. 🚀");
            Future.delayed(const Duration(seconds: 1), () {
              self.setDetailText("Customizable Detail Text");
              complete();
            });
          },
          image: 'images/logo_flutter_1080px_clr.png',
        ),
        CPListItem(
          text: "Item 2",
          detailText: "Start progress bar",
          isPlaying: false,
          playbackProgress: 0,
          image: 'images/logo_flutter_1080px_clr.png',
          onPress: (complete, self) {
            for (var i = 1; i <= 100; i++) {
              self.setPlaybackProgress(i / 100);
              if (i == 100) {
                complete();
              }
            }
          },
        ),
      ],
      header: "First Section",
    ));

    final List<CPListSection> section2Items = [];
    section2Items.add(CPListSection(
      items: [
        CPListItem(
          text: "Alert",
          detailText: "Action template that the user can perform on an alert",
          onPress: (complete, self) {
            showAlert();
            complete();
          },
        ),
        CPListItem(
          text: "Grid Template",
          detailText: "A template that displays and manages a grid of items",
          onPress: (complete, self) {
            openGridTemplate();
            complete();
          },
        ),
      ],
      header: "Features",
    ));

    FlutterCarplay.setRootTemplate(
      rootTemplate: CPTabBarTemplate(
        templates: [
          CPListTemplate(
            sections: section1Items,
            title: "Home",
            showsTabBadge: false,
            systemIcon: "house.fill",
          ),
          CPListTemplate(
            sections: section2Items,
            title: "Features",
            showsTabBadge: true,
            systemIcon: "star.circle.fill",
          ),
        ],
      ),
      animated: true,
    );

    _flutterCarplay.addListenerOnConnectionChange(onCarplayConnectionChange);
  }

  [@override](/user/override)
  void dispose() {
    _flutterCarplay.removeListenerOnConnectionChange();
    super.dispose();
  }

  void onCarplayConnectionChange(CPConnectionStatusTypes status) {
    setState(() {
      connectionStatus = status;
    });
  }

  void showAlert() {
    FlutterCarplay.showAlert(
      template: CPAlertTemplate(
        titleVariants: ["Alert Title"],
        actions: [
          CPAlertAction(
            title: "Okay",
            style: CPAlertActionStyles.normal,
            onPress: () {
              FlutterCarplay.popModal(animated: true);
              print("Okay pressed");
            },
          ),
          CPAlertAction(
            title: "Cancel",
            style: CPAlertActionStyles.cancel,
            onPress: () {
              FlutterCarplay.popModal(animated: true);
              print("Cancel pressed");
            },
          ),
        ],
      ),
    );
  }

  void openGridTemplate() {
    FlutterCarplay.push(
      template: CPGridTemplate(
        title: "Grid Template",
        buttons: [
          for (var i = 1; i < 9; i++)
            CPGridButton(
              titleVariants: ["Item $i"],
              image: 'images/logo_flutter_1080px_clr.png',
              onPress: () {
                print("Grid Button $i pressed");
              },
            ),
        ],
      ),
      animated: true,
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Carplay'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Center(
              child: Text(
                'Carplay Status: ' + CPEnumUtils.stringFromEnum(connectionStatus),
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: () => showAlert(),
                  child: const Text('Show Alert'),
                ),
                const SizedBox(width: 15, height: 0),
                ElevatedButton(
                  onPressed: () => openGridTemplate(),
                  child: const Text('Open Grid Template'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter车载互联插件flutter_carplay的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter车载互联插件flutter_carplay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中集成并使用flutter_carplay插件进行车载互联的基本代码示例。这个示例将展示如何设置插件、连接CarPlay以及显示一些基本内容。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加flutter_carplay依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_carplay: ^最新版本号 # 请替换为实际发布的最新版本号

然后运行flutter pub get来安装依赖。

2. 配置Info.plist(iOS)

对于iOS项目,你需要在Info.plist中添加必要的配置以支持CarPlay。确保你的Info.plist包含以下条目:

<key>UISupportedExternalAccessoryProtocols</key>
<array>
    <string>com.apple.carplay.carinterface</string>
</array>

注意:实际开发中,你可能需要根据Apple的文档进行更详细的配置。

3. 初始化插件并连接CarPlay

在你的Flutter项目中,你可以按照以下步骤初始化flutter_carplay插件并尝试连接CarPlay。

import 'package:flutter/material.dart';
import 'package:flutter_carplay/flutter_carplay.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  CarplayController? _carplayController;

  @override
  void initState() {
    super.initState();
    // 初始化CarPlay控制器
    _carplayController = CarplayController();

    // 监听连接状态变化
    _carplayController!.addListener(() {
      if (_carplayController!.isConnected!) {
        // 当CarPlay连接时执行的操作
        _setupCarPlayInterface();
      } else {
        // 当CarPlay断开时执行的操作
        print('CarPlay disconnected');
      }
    });

    // 尝试连接CarPlay
    _carplayController!.connect();
  }

  @override
  void dispose() {
    _carplayController?.dispose();
    super.dispose();
  }

  void _setupCarPlayInterface() {
    // 设置CarPlay界面,例如显示一个简单的屏幕
    _carplayController!.setRootTemplate(
      CarplayTemplate.applicationTemplate(
        pages: [
          CarplayPage(
            title: 'Welcome',
            sections: [
              CarplaySection(
                rows: [
                  CarplaySimpleRow(
                    title: 'Hello, CarPlay!',
                    detail: 'This is a demo app.',
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter CarPlay Demo'),
        ),
        body: Center(
          child: Text('Checking for CarPlay connection...'),
        ),
      ),
    );
  }
}

4. 运行应用

确保你的设备或模拟器支持CarPlay,然后运行你的Flutter应用。当CarPlay设备连接时,应用应该会显示一个简单的界面。

注意事项

  • flutter_carplay插件是一个相对较新的插件,其API和功能可能会随着版本的更新而变化。
  • 在实际开发中,你可能需要处理更多的CarPlay特性,如音频播放、导航等,这通常需要更深入的插件使用和理解。
  • 请务必参考插件的官方文档和示例代码,以获取最新的使用指南和最佳实践。

这个示例提供了一个基本的起点,帮助你开始在Flutter应用中集成CarPlay功能。

回到顶部