У меня есть приложение Flutter — простой онлайн-плеер, который использует flutter_carplay и audio_service. Я выпускаю это приложение только для iOS.
Это точка входа приложения:
void main() async {
await App.initApp(); // basic initialization (Firebase, ...)
runApp(const App());
}
Это App виджет.
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (BuildContext context, Widget? child) {},
home: HomePage()
);
}
}
Весь код, связанный с CarPlay, можно найти в HomePage:
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FlutterCarplay _flutterCarplay = FlutterCarplay();
@override
void initState() {
super.initState();
initCarPlay();
}
@override
Widget build(BuildContext context) {
return ...;
}
void initCarPlay() {
FlutterCarplay.setRootTemplate(
rootTemplate: CPListTemplate(
sections: [
CPListSection(header: "Section 1", items: [
CPListItem(text: "Item 1"),
CPListItem(text: "Item 2"),
CPListItem(text: "Item 3"),
]),
CPListSection(header: "Section 2", items: [
CPListItem(text: "Item 4"),
CPListItem(text: "Item 5"),
CPListItem(text: "Item 6"),
])
],
showsTabBadge: false,
systemIcon: "house.fill",
),
animated: true,
);
_flutterCarplay.forceUpdateRootTemplate();
_flutterCarplay.addListenerOnConnectionChange(_onCarplayConnectionChange);
}
void _onCarplayConnectionChange(CPConnectionStatusTypes status) {
//
}
@override
void dispose() {
_flutterCarplay.removeListenerOnConnectionChange();
super.dispose();
}
}
Я пытался напрямую вызвать initCarPlay() в main(), но результат был тот же.





Во-первых, вам необходимо убедиться, что ваш метод initCarPlay вызывается даже тогда, когда приложение запускается из CarPlay.
Кроме того, обрабатывайте события жизненного цикла CarPlay-specific, чтобы правильно инициализировать интерфейс CarPlay и гарантировать, что необходимые данные и службы инициализируются в фоновом режиме, чтобы приложение было готово к запуску из CarPlay.
Измененная функция main
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await App.initApp();
runApp(const App());
}
App Виджет
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (BuildContext context, Widget? child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: child!,
);
},
home: const HomePage(),
);
}
}
Изменён HomePage Экран
Убедитесь, что initCarPlay вызывается независимо от того, как запускается приложение.
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FlutterCarplay _flutterCarplay = FlutterCarplay();
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) => initApp());
_flutterCarplay.addListenerOnConnectionChange(_onCarplayConnectionChange);
}
Future<void> initApp() async {
initCarPlay();
}
void initCarPlay() {
FlutterCarplay.setRootTemplate(
rootTemplate: CPListTemplate(
sections: [
CPListSection(header: "Section 1", items: [
CPListItem(text: "Item 1"),
CPListItem(text: "Item 2"),
CPListItem(text: "Item 3"),
]),
CPListSection(header: "Section 2", items: [
CPListItem(text: "Item 4"),
CPListItem(text: "Item 5"),
CPListItem(text: "Item 6"),
])
],
showsTabBadge: false,
systemIcon: "house.fill",
),
animated: true,
);
_flutterCarplay.forceUpdateRootTemplate();
}
void _onCarplayConnectionChange(CPConnectionStatusTypes status) {
if (status == CPConnectionStatusTypes.connected) {
initCarPlay();
}
}
@override
void dispose() {
_flutterCarplay.removeListenerOnConnectionChange();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Home Page Content'),
),
);
}
}