Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next

Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next

Opening: When HarmonyOS Meets Smart Vehicles

In the era of ubiquitous connectivity, automobiles have long transcended their role as mere transportati…


This content originally appeared on DEV Community and was authored by linzhongxue

Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next

Opening: When HarmonyOS Meets Smart Vehicles

In the era of ubiquitous connectivity, automobiles have long transcended their role as mere transportation tools. As a developer with years of experience in vehicle connectivity, I've had the privilege to participate in multiple HarmonyOS in-car application projects. Today, through a complete in-car music application case study, I'll demonstrate how to rapidly build professional-grade automotive applications using AppGallery Connect.

1. Fundamental Preparations for In-Car Application Development

1.1 Special Configuration of Development Environment

In-car application development requires special attention to the following configurations:

  1. Install the "Automotive" extension package in DevEco Studio
  2. Apply for in-car development permissions (requires enterprise developer account)
  3. Select automotive resolution (typically 1920x720) when configuring the emulator
// In-car environment detection tool
function checkAutomotiveEnvironment() {
    try {
        const systemInfo = device.getSystemInfoSync();
        if (!systemInfo.isAutomotive) {
            console.warn("Not in automotive environment, some APIs may be restricted");
            return false;
        }
        console.log("Automotive system version:", systemInfo.osVersion);
        return true;
    } catch (e) {
        console.error("Environment detection exception:", e);
        return false;
    }
}

1.2 In-Car UI Design Specifications

In-car applications must follow special interaction principles:

  • Button size no smaller than 60px
  • Text size no smaller than 24px
  • Operation hierarchy no more than 3 levels
  • Full-screen popups are prohibited

2. Developing an In-Car Music Player

2.1 Audio Service Integration

// Audio service wrapper class
class AudioService {
    private audioSession: audio.AudioSession;
    private player: audio.AudioPlayer;

    constructor() {
        this.initAudioSession();
    }

    private initAudioSession() {
        // Create dedicated automotive audio session
        this.audioSession = audio.createAudioSession({
            usage: audio.StreamUsage.MUSIC,
            device: audio.CommunicationDevice.CAR_AUDIO
        });

        // Configure audio focus policy
        this.audioSession.setInterruptionMode(
            audio.InterruptionMode.SHAREABLE
        );
    }

    // Initialize player
    async initPlayer(source: string) {
        this.player = await this.audioSession.createPlayer({
            source: {
                uri: source
            },
            loop: false
        });

        // Set automotive audio properties
        await this.player.setAudioProperties({
            speed: 1.0,
            pitch: 1.0,
            fadeTime: 500
        });
    }

    // Playback control
    async play() {
        try {
            await this.player.play();
            console.log("Playback started");
        } catch (error) {
            console.error("Playback failed:", error);
        }
    }

    // Pause playback
    async pause() {
        await this.player.pause();
    }

    // Switch audio source
    async switchSource(newSource: string) {
        await this.player.reset();
        await this.player.setSource({ uri: newSource });
        await this.play();
    }
}

2.2 Music List Component

// Dedicated in-car music list component
@Component
struct MusicList {
    @State songs: Song[] = [];
    @State currentIndex: number = -1;

    // Column width adapts to in-car display
    @StorageProp('displayMode') displayMode: string = 'single';

    build() {
        Grid() {
            ForEach(this.songs, (song, index) => {
                GridItem() {
                    Column() {
                        Image(song.cover)
                            .width(120)
                            .height(120)
                            .borderRadius(8)

                        Text(song.name)
                            .fontSize(24)
                            .margin({ top: 8 })

                        Text(song.artist)
                            .fontSize(18)
                            .opacity(0.8)
                    }
                    .padding(12)
                    .backgroundColor(
                        this.currentIndex === index ? 
                        '#333333' : 'transparent'
                    )
                    .onClick(() => {
                        this.playSelected(index);
                    })
                }
                .colSpan(this.displayMode === 'single' ? 2 : 1)
            })
        }
        .columnsTemplate(
            this.displayMode === 'single' ? 
            '1fr' : '1fr 1fr'
        )
        .onAppear(() => {
            this.loadMusicList();
        })
    }

    private async loadMusicList() {
        try {
            const response = await fetch(
                'https://api.example.com/car-music'
            );
            this.songs = await response.json();
        } catch (error) {
            console.error("Failed to fetch music list:", error);
        }
    }

    private playSelected(index: number) {
        this.currentIndex = index;
        const audioService = AudioService.getInstance();
        audioService.switchSource(this.songs[index].url);
    }
}

3. Vehicle Data Interaction Module

3.1 Vehicle Status Subscription

// Vehicle data service
class VehicleDataService {
    private static instance: VehicleDataService;
    private vehicleApi: any;

    private constructor() {
        this.initVehicleApi();
    }

    public static getInstance(): VehicleDataService {
        if (!VehicleDataService.instance) {
            VehicleDataService.instance = new VehicleDataService();
        }
        return VehicleDataService.instance;
    }

    private initVehicleApi() {
        try {
            this.vehicleApi = require('@ohos.vehicle');
        } catch (error) {
            console.error("Vehicle API unavailable:", error);
        }
    }

    // Get current speed
    getCurrentSpeed(): Promise<number> {
        return new Promise((resolve) => {
            if (!this.vehicleApi) {
                resolve(0);
                return;
            }

            this.vehicleApi.getData(
                'speed',
                (err, data) => {
                    if (!err) {
                        resolve(data.value);
                    } else {
                        resolve(0);
                    }
                }
            );
        });
    }

    // Subscribe to vehicle data changes
    subscribe(dataType: string, callback: Function) {
        if (!this.vehicleApi) return;

        this.vehicleApi.subscribe(
            dataType,
            (err, data) => {
                if (!err) {
                    callback(data.value);
                }
            }
        );
    }
}

3.2 Driving Mode Adaptation

// Driving mode awareness component
@Component
struct DrivingModeAware {
    @State drivingMode: string = 'normal';
    private vehicleService = VehicleDataService.getInstance();

    build() {
        Column() {
            // Display different UI based on driving mode
            if (this.drivingMode === 'sport') {
                SportModeView()
            } else if (this.drivingMode === 'night') {
                NightModeView()
            } else {
                NormalModeView()
            }
        }
        .onAppear(() => {
            this.setupDrivingModeListener();
        })
    }

    private setupDrivingModeListener() {
        this.vehicleService.subscribe(
            'driving_mode',
            (mode: string) => {
                this.drivingMode = mode;
            }
        );
    }
}

4. Cloud Synchronization and User Preferences

4.1 User Configuration Synchronization

// User preference management
class UserPreference {
    private cloudDB: cloud.CloudDBZone;

    constructor() {
        this.initCloudDB();
    }

    private async initCloudDB() {
        const config = {
            name: 'CarUserPrefs',
            persistenceEnabled: true,
            encryptionKey: 'user_specific_key'
        };
        this.cloudDB = await cloud.CloudDBZoneManager
            .getInstance()
            .openCloudDBZone(config);
    }

    // Save preference settings
    async savePreference(key: string, value: any) {
        const pref = {
            userId: getCurrentUserId(),
            prefKey: key,
            prefValue: JSON.stringify(value),
            updateTime: new Date().getTime()
        };

        await this.cloudDB.executeUpsert([pref]);
    }

    // Retrieve preference settings
    async getPreference(key: string): Promise<any> {
        const query = cloud.CloudDBZoneQuery
            .where('UserPreference')
            .equalTo('userId', getCurrentUserId())
            .equalTo('prefKey', key)
            .limit(1);

        const snapshot = await this.cloudDB.executeQuery(query);
        if (snapshot.hasNext()) {
            const record = snapshot.next();
            return JSON.parse(record.prefValue);
        }
        return null;
    }
}

4.2 Multi-Device Synchronization Solution

// Cross-device synchronization controller
class SyncController {
    private agcAuth = require('@hw-agconnect/auth-ohos');
    private agcCloud = require('@hw-agconnect/cloud-ohos');

    // Initialize synchronization channel
    async initSyncChannel() {
        const user = await this.agcAuth.getInstance()
            .getCurrentUser();

        if (!user) return false;

        const config = {
            syncPolicy: 'auto',
            conflictHandler: this.resolveConflict
        };

        await this.agcCloud.getInstance()
            .enableDataSync(config);

        return true;
    }

    // Conflict resolution strategy
    private resolveConflict(localData, serverData) {
        // Use data with latest timestamp
        return localData.updateTime > serverData.updateTime ? 
            localData : serverData;
    }

    // Trigger manual synchronization
    async triggerManualSync() {
        try {
            await this.agcCloud.getInstance()
                .executeSync();
            return true;
        } catch (error) {
            console.error("Synchronization failed:", error);
            return false;
        }
    }
}

5. Performance Optimization for In-Car Applications

5.1 Memory Management Techniques

// Resource monitoring component
@Component
struct ResourceMonitor {
    @State memoryUsage: number = 0;
    @State cpuUsage: number = 0;
    private timer: number = 0;

    build() {
        Column() {
            Text(`Memory usage: ${this.memoryUsage.toFixed(1)}MB`)
            Text(`CPU usage: ${this.cpuUsage.toFixed(1)}%`)
        }
        .onAppear(() => {
            this.startMonitoring();
        })
        .onDisappear(() => {
            this.stopMonitoring();
        })
    }

    private startMonitoring() {
        this.timer = setInterval(() => {
            this.updateMetrics();
        }, 2000);
    }

    private stopMonitoring() {
        clearInterval(this.timer);
    }

    private async updateMetrics() {
        const stats = await performance.getMetrics();
        this.memoryUsage = stats.memory / 1024 / 1024;
        this.cpuUsage = stats.cpu * 100;
    }
}

5.2 Efficient Rendering Strategies

// Optimized list rendering
@Component
struct OptimizedList {
    @State data: any[] = [];
    private visibleRange: number[] = [0, 10];

    build() {
        List() {
            LazyForEach(this.data.slice(
                this.visibleRange[0], 
                this.visibleRange[1]
            ), (item) => {
                ListItem() {
                    ListItemContent(item)
                }
            })
        }
        .onScroll((offset: number) => {
            this.updateVisibleRange(offset);
        })
    }

    private updateVisibleRange(offset: number) {
        const start = Math.floor(offset / 100);
        this.visibleRange = [start, start + 10];
    }
}

6. Testing and Release Process

6.1 Specialized Testing for In-Car Applications

  1. Driver distraction testing: Ensure the app doesn't interfere with normal driving
  2. Extreme environment testing: Operational stability under high/low temperatures
  3. Long-duration testing: 24-hour continuous operation to check for memory leaks
  4. Voice interaction testing: Compatibility with in-car voice systems

6.2 Application Release Checklist

  1. Pass Huawei's in-car application certification
  2. Complete all required metadata information
  3. Provide screenshots in at least 3 automotive resolutions
  4. Declare supported vehicle models
  5. Prepare automotive-specific application descriptions

Conclusion: Accelerating into the HarmonyOS Automotive Ecosystem

Developing this in-car music application has given me profound appreciation for HarmonyOS' unique advantages in the automotive field. Particularly its distributed capabilities and hardware collaboration features bring entirely new possibilities to in-car scenarios.

I recommend developers stay updated on Huawei's intelligent automotive solutions. The automotive UI component library I've accumulated during this project is now open-source—search for "harmony-auto-ui" in the open-source community. Looking forward to seeing more amazing applications in the HarmonyOS automotive ecosystem!


This content originally appeared on DEV Community and was authored by linzhongxue


Print Share Comment Cite Upload Translate Updates
APA

linzhongxue | Sciencx (2025-05-28T01:07:00+00:00) Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next. Retrieved from https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/

MLA
" » Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next." linzhongxue | Sciencx - Wednesday May 28, 2025, https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/
HARVARD
linzhongxue | Sciencx Wednesday May 28, 2025 » Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next., viewed ,<https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/>
VANCOUVER
linzhongxue | Sciencx - » Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/
CHICAGO
" » Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next." linzhongxue | Sciencx - Accessed . https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/
IEEE
" » Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next." linzhongxue | Sciencx [Online]. Available: https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/. [Accessed: ]
rf:citation
» Hands-on Development of Smart Connected Car Applications Based on HarmonyOS Next | linzhongxue | Sciencx | https://www.scien.cx/2025/05/28/hands-on-development-of-smart-connected-car-applications-based-on-harmonyos-next/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.