├── .github └── FUNDING.yml ├── MauiForCars ├── MauiForCars │ ├── Resources │ │ ├── Fonts │ │ │ ├── OpenSans-Regular.ttf │ │ │ └── OpenSans-Semibold.ttf │ │ ├── AppIcon │ │ │ ├── appicon.svg │ │ │ └── appiconfg.svg │ │ ├── Raw │ │ │ └── AboutAssets.txt │ │ ├── Splash │ │ │ └── splash.svg │ │ ├── Styles │ │ │ ├── Colors.xaml │ │ │ └── Styles.xaml │ │ └── Images │ │ │ └── dotnet_bot.svg │ ├── Platforms │ │ ├── Android │ │ │ ├── Resources │ │ │ │ ├── xml │ │ │ │ │ └── automotive_app_desc.xml │ │ │ │ └── values │ │ │ │ │ └── colors.xml │ │ │ ├── AndroidAuto │ │ │ │ ├── Enums │ │ │ │ │ └── AAScreen.cs │ │ │ │ ├── Sessions │ │ │ │ │ └── AASession.cs │ │ │ │ ├── Listeners │ │ │ │ │ ├── ActionOnClickListener.cs │ │ │ │ │ └── NavigationOnClickListener.cs │ │ │ │ ├── Services │ │ │ │ │ └── AACarAppService.cs │ │ │ │ └── Screens │ │ │ │ │ ├── AAScreenMessageTemplate.cs │ │ │ │ │ ├── AAScreenMenu.cs │ │ │ │ │ ├── AAScreenGridTemplate.cs │ │ │ │ │ └── AAScreenPaneTemplate.cs │ │ │ ├── MainApplication.cs │ │ │ ├── MainActivity.cs │ │ │ └── AndroidManifest.xml │ │ ├── iOS │ │ │ ├── AppDelegate.cs │ │ │ ├── Entitlements.plist │ │ │ ├── DeviceSceneDelegate.cs │ │ │ ├── Program.cs │ │ │ ├── Info.plist │ │ │ └── CarPlaySceneDelegate.cs │ │ ├── MacCatalyst │ │ │ ├── AppDelegate.cs │ │ │ ├── Program.cs │ │ │ └── Info.plist │ │ ├── Windows │ │ │ ├── App.xaml │ │ │ ├── app.manifest │ │ │ ├── App.xaml.cs │ │ │ └── Package.appxmanifest │ │ └── Tizen │ │ │ ├── Main.cs │ │ │ └── tizen-manifest.xml │ ├── AppShell.xaml.cs │ ├── Properties │ │ └── launchSettings.json │ ├── App.xaml.cs │ ├── AppShell.xaml │ ├── MainPage.xaml.cs │ ├── MauiProgram.cs │ ├── App.xaml │ ├── MainPage.xaml │ └── MauiForCars.csproj └── MauiForCars.sln ├── Scripts └── RunAndroidAuto.bat ├── README.md ├── .gitignore └── LICENSE /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: christian-strydom 2 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Resources/Fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-strydom/MauiForCars/HEAD/MauiForCars/MauiForCars/Resources/Fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Resources/Fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-strydom/MauiForCars/HEAD/MauiForCars/MauiForCars/Resources/Fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/Resources/xml/automotive_app_desc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace MauiForCars; 2 | 3 | public partial class AppShell : Shell 4 | { 5 | public AppShell() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Windows Machine": { 4 | "commandName": "MsixPackage", 5 | "nativeDebugging": false 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace MauiForCars; 2 | 3 | public partial class App : Application 4 | { 5 | public App() 6 | { 7 | InitializeComponent(); 8 | 9 | MainPage = new AppShell(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Resources/AppIcon/appicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #512BD4 4 | #2B0B98 5 | #2B0B98 6 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | 3 | namespace MauiForCars; 4 | 5 | [Register("AppDelegate")] 6 | public class AppDelegate : MauiUIApplicationDelegate 7 | { 8 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 9 | } 10 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/MacCatalyst/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | 3 | namespace MauiForCars; 4 | 5 | [Register("AppDelegate")] 6 | public class AppDelegate : MauiUIApplicationDelegate 7 | { 8 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 9 | } 10 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.carplay-driving-task 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/AndroidAuto/Enums/AAScreen.cs: -------------------------------------------------------------------------------- 1 | namespace MauiForCars.Platforms.Android.AndroidAuto.Enums 2 | { 3 | public enum AAScreen 4 | { 5 | None = 0, 6 | Menu = 1, 7 | MessageTemplate = 2, 8 | PaneTemplate = 3, 9 | GridTemplate = 4, 10 | Pop = 5, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Windows/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Scripts/RunAndroidAuto.bat: -------------------------------------------------------------------------------- 1 | : https://cvstrydom.co.za 2 | : This script forwards your ADB port and launches the Android Auto Desktop Head Unit if it's installed in the default location 3 | : Be sure to start the head unit server on your Android phone first 4 | adb forward tcp:5277 tcp:5277 5 | start "" "%USERPROFILE%\AppData\Local\Android\Sdk\extras\google\auto\desktop-head-unit.exe" -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Tizen/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Maui; 3 | using Microsoft.Maui.Hosting; 4 | 5 | namespace MauiForCars; 6 | 7 | class Program : MauiApplication 8 | { 9 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 10 | 11 | static void Main(string[] args) 12 | { 13 | var app = new Program(); 14 | app.Run(args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/iOS/DeviceSceneDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MauiCarApp.Platforms.iOS 9 | { 10 | [Register("DeviceSceneDelegate")] 11 | public class DeviceSceneDelegate : MauiUISceneDelegate 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Runtime; 3 | 4 | namespace MauiForCars; 5 | 6 | [Application] 7 | public class MainApplication : MauiApplication 8 | { 9 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 10 | : base(handle, ownership) 11 | { 12 | } 13 | 14 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 15 | } 16 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/iOS/Program.cs: -------------------------------------------------------------------------------- 1 | using ObjCRuntime; 2 | using UIKit; 3 | 4 | namespace MauiForCars; 5 | 6 | public class Program 7 | { 8 | // This is the main entry point of the application. 9 | static void Main(string[] args) 10 | { 11 | // if you want to use a different Application Delegate class from "AppDelegate" 12 | // you can specify it here. 13 | UIApplication.Main(args, null, typeof(AppDelegate)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/MacCatalyst/Program.cs: -------------------------------------------------------------------------------- 1 | using ObjCRuntime; 2 | using UIKit; 3 | 4 | namespace MauiForCars; 5 | 6 | public class Program 7 | { 8 | // This is the main entry point of the application. 9 | static void Main(string[] args) 10 | { 11 | // if you want to use a different Application Delegate class from "AppDelegate" 12 | // you can specify it here. 13 | UIApplication.Main(args, null, typeof(AppDelegate)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/AndroidAuto/Sessions/AASession.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using AndroidX.Car.App; 3 | using MauiForCars.Platforms.Android.AndroidAuto.Screens; 4 | 5 | namespace MauiForCars.Platforms.Android.AndroidAuto.Sessions 6 | { 7 | public class AASession : Session 8 | { 9 | public override Screen OnCreateScreen(Intent intent) 10 | { 11 | return new AAScreenMenu(CarContext); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.OS; 4 | 5 | namespace MauiForCars; 6 | 7 | [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] 8 | public class MainActivity : MauiAppCompatActivity 9 | { 10 | } 11 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/AppShell.xaml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace MauiForCars; 2 | 3 | public partial class MainPage : ContentPage 4 | { 5 | int count = 0; 6 | 7 | public MainPage() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | private void OnCounterClicked(object sender, EventArgs e) 13 | { 14 | count++; 15 | 16 | if (count == 1) 17 | CounterBtn.Text = $"Clicked {count} time"; 18 | else 19 | CounterBtn.Text = $"Clicked {count} times"; 20 | 21 | SemanticScreenReader.Announce(CounterBtn.Text); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/MauiProgram.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace MauiForCars; 4 | 5 | public static class MauiProgram 6 | { 7 | public static MauiApp CreateMauiApp() 8 | { 9 | var builder = MauiApp.CreateBuilder(); 10 | builder 11 | .UseMauiApp() 12 | .ConfigureFonts(fonts => 13 | { 14 | fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); 15 | fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); 16 | }); 17 | 18 | #if DEBUG 19 | builder.Logging.AddDebug(); 20 | #endif 21 | 22 | return builder.Build(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Resources/Raw/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories). Deployment of the asset to your application 3 | is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. 4 | 5 | 6 | 7 | These files will be deployed with you package and will be accessible using Essentials: 8 | 9 | async Task LoadMauiAsset() 10 | { 11 | using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); 12 | using var reader = new StreamReader(stream); 13 | 14 | var contents = reader.ReadToEnd(); 15 | } 16 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/AndroidAuto/Listeners/ActionOnClickListener.cs: -------------------------------------------------------------------------------- 1 | using AndroidX.Car.App; 2 | using AndroidX.Car.App.Model; 3 | 4 | namespace MauiForCars.Platforms.Android.AndroidAuto.Listeners 5 | { 6 | public class ActionOnClickListener : Java.Lang.Object, IOnClickListener 7 | { 8 | private readonly CarContext _carContext; 9 | private readonly string _message; 10 | 11 | public ActionOnClickListener(CarContext carContext, string message = null) 12 | { 13 | _carContext = carContext; 14 | _message = message; 15 | } 16 | 17 | public void OnClick() 18 | { 19 | CarToast.MakeText(_carContext, _message, CarToast.LengthLong).Show(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Android/AndroidAuto/Services/AACarAppService.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using AndroidX.Car.App; 3 | using AndroidX.Car.App.Validation; 4 | using MauiForCars.Platforms.Android.AndroidAuto.Sessions; 5 | 6 | namespace MauiForCars.Platforms.Android.AndroidAuto.Services 7 | { 8 | [Service(Exported = true)] 9 | [IntentFilter(new string[] { "androidx.car.app.CarAppService" }, Categories = new[] { "androidx.car.app.category.POI" })] 10 | public class AACarAppService : CarAppService 11 | { 12 | public override HostValidator CreateHostValidator() 13 | { 14 | return HostValidator.AllowAllHostsValidator; 15 | } 16 | 17 | public override Session OnCreateSession() 18 | { 19 | return new AASession(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Windows/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | true/PM 12 | PerMonitorV2, PerMonitor 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Tizen/tizen-manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | maui-appicon-placeholder 7 | 8 | 9 | 10 | 11 | http://tizen.org/privilege/internet 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/Windows/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | // To learn more about WinUI, the WinUI project structure, 4 | // and more about our project templates, see: http://aka.ms/winui-project-info. 5 | 6 | namespace MauiForCars.WinUI; 7 | 8 | /// 9 | /// Provides application-specific behavior to supplement the default Application class. 10 | /// 11 | public partial class App : MauiWinUIApplication 12 | { 13 | /// 14 | /// Initializes the singleton application object. This is the first line of authored code 15 | /// executed, and as such is the logical equivalent of main() or WinMain(). 16 | /// 17 | public App() 18 | { 19 | this.InitializeComponent(); 20 | } 21 | 22 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MauiForCars 2 | 3 | Source code to build apps for cars (Android Auto and Apple CarPlay) with .NET MAUI. 4 | 5 | This repository complements the [MAUI for cars tutorial series on YouTube](https://youtube.com/playlist?list=PL0jJqThQHxikbetR1ODplARyLG6YAPKlz) by [Christian Strydom](https://cvstrydom.co.za). 6 | 7 | [![MAUI for Cars: Android Auto Tutorial Thumbnail](https://img.youtube.com/vi/nNkVxegb2oU/0.jpg)](https://www.youtube.com/watch?v=nNkVxegb2oU) 8 | [![MAUI for Cars: Android Auto Tutorial Thumbnail](https://img.youtube.com/vi/Yg2I6NbHZp8/0.jpg)](https://www.youtube.com/watch?v=Yg2I6NbHZp8) 9 | 10 | [![YouTube Video Views](https://img.shields.io/youtube/views/nNkVxegb2oU?label=MAUI%20for%20cars%3A%20Android%20Auto&style=social)](https://youtu.be/nNkVxegb2oU) 11 | [![YouTube Video Views](https://img.shields.io/youtube/views/Yg2I6NbHZp8?label=MAUI%20for%20cars%3A%20Apple%20CarPlay&style=social)](https://youtu.be/Yg2I6NbHZp8) 12 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/Platforms/MacCatalyst/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UIRequiredDeviceCapabilities 11 | 12 | arm64 13 | 14 | UISupportedInterfaceOrientations 15 | 16 | UIInterfaceOrientationPortrait 17 | UIInterfaceOrientationLandscapeLeft 18 | UIInterfaceOrientationLandscapeRight 19 | 20 | UISupportedInterfaceOrientations~ipad 21 | 22 | UIInterfaceOrientationPortrait 23 | UIInterfaceOrientationPortraitUpsideDown 24 | UIInterfaceOrientationLandscapeLeft 25 | UIInterfaceOrientationLandscapeRight 26 | 27 | XSAppIconAssets 28 | Assets.xcassets/appicon.appiconset 29 | 30 | 31 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31611.283 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiForCars", "MauiForCars\MauiForCars.csproj", "{BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 17 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {BE58DB1C-7D8B-4165-A841-DBEE4E05D0D2}.Release|Any CPU.Deploy.0 = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ExtensibilityGlobals) = postSolution 25 | SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572} 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /MauiForCars/MauiForCars/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 17 | 18 |