This content originally appeared on DEV Community and was authored by linzhongxue
Development Guide for Smart Sports Social Apps Based on HarmonyOS Next
Foreword: Why Choose HarmonyOS for Sports App Development?
As an engineer with extensive experience in mobile development, I recently developed a basketball social app on HarmonyOS Next and gained valuable insights. Today, I'd like to share practical experiences, particularly on leveraging various AppGallery Connect services to quickly build fully functional sports applications.
1. Project Planning and Environment Setup
1.1 Defining Core App Features
Before coding, we need to clarify the core functional modules:
- User system (registration/login/profile)
- Sports venue booking
- Event management
- Sports data recording
- Social interaction (likes/comments)
1.2 Preparing the Development Environment
First, ensure your development environment is ready:
- Install the latest DevEco Studio (currently version 4.1 recommended)
- Complete real-name verification on Huawei Developer Alliance
- Create a new project in AppGallery Connect
// Tool to check environment readiness
function checkEnvironment() {
try {
const info = app.getInfo();
console.log(`Current DevEco version: ${info.version}`);
console.log(`HarmonyOS SDK version: ${info.sdkVersion}`);
return true;
} catch (e) {
console.error("Environment check failed, please install DevEco Studio first");
return false;
}
}
2. Implementing the User System
2.1 Integrating Authentication Services
AppGallery Connect's authentication service supports multiple login methods. We'll use the most common phone number + verification code approach:
// Auth module encapsulation example
class AuthService {
private static instance: AuthService;
// Singleton pattern ensures global uniqueness
private constructor() {}
public static getInstance(): AuthService {
if (!AuthService.instance) {
AuthService.instance = new AuthService();
}
return AuthService.instance;
}
// Send verification code
async sendSMSCode(phone: string): Promise<boolean> {
try {
const auth = await import('@hw-agconnect/auth-ohos');
const result = await auth.default.getInstance()
.requestPhoneVerifyCode(phone);
return result !== null;
} catch (error) {
console.error('Failed to send verification code:', error);
return false;
}
}
// Login with verification code
async loginWithCode(phone: string, code: string): Promise<User | null> {
try {
const auth = await import('@hw-agconnect/auth-ohos');
const credential = auth.PhoneAuthProvider
.credentialWithVerifyCode(phone, '', code);
const user = await auth.default.getInstance()
.signIn(credential);
return this.parseUser(user);
} catch (error) {
console.error('Login failed:', error);
return null;
}
}
private parseUser(rawUser: any): User {
return {
uid: rawUser.uid,
phone: rawUser.phone,
displayName: rawUser.displayName || 'New User'
};
}
}
2.2 User Profile Management
Use cloud database to store additional user information:
// User data model
{
"userId": "string", // Primary key, corresponds to auth service UID
"nickName": "string",
"avatar": "string", // Profile picture URL
"level": "number", // User level
"sports": "array", // Preferred sports
"createdAt": "date" // Registration time
}
3. Developing Venue Booking Features
3.1 Designing Venue Data Models
interface SportsVenue {
id: string; // Venue ID
name: string; // Venue name
location: string; // Detailed address
geoPoint: { // Geographic coordinates
latitude: number;
longitude: number;
};
images: string[]; // Venue images
facilities: string[];// Available facilities
pricePerHour: number;// Hourly rate
businessHours: { // Operating hours
open: string; // e.g., "09:00"
close: string; // e.g., "22:00"
};
}
3.2 Implementing Booking System
// Core booking service logic
class BookingService {
private cloudDB: cloud.CloudDBZone;
constructor() {
this.initCloudDB();
}
private async initCloudDB() {
const config = {
name: 'SportsVenueDB',
persistenceEnabled: true
};
this.cloudDB = await cloud.CloudDBZoneManager
.getInstance()
.openCloudDBZone(config);
}
// Query available venues
async queryVenues(criteria: VenueQuery): Promise<Venue[]> {
let query = cloud.CloudDBZoneQuery
.where('SportsVenue')
.orderByAsc('pricePerHour');
if (criteria.location) {
query = query.nearTo('geoPoint',
criteria.location.longitude,
criteria.location.latitude,
criteria.radius || 5000); // Default 5km radius
}
if (criteria.sportsType) {
query = query.contains('sportsType', criteria.sportsType);
}
const snapshot = await this.cloudDB.executeQuery(query);
const results: Venue[] = [];
while (snapshot.hasNext()) {
results.push(snapshot.next());
}
return results;
}
// Create booking
async createBooking(booking: Booking): Promise<boolean> {
try {
booking.bookingId = this.generateId(); // Generate unique ID
booking.status = 'pending'; // Initial status
await this.cloudDB.executeUpsert([booking]);
return true;
} catch (error) {
console.error('Failed to create booking:', error);
return false;
}
}
private generateId(): string {
return 'xxxx-xxxx-xxxx'.replace(/x/g, () =>
(Math.random() * 16 | 0).toString(16));
}
}
4. Event Management Module
4.1 Event Creation Feature
// Core logic for event creation page
@Entry
@Component
struct CreateEventPage {
@State event: Event = {
title: '',
sportType: 'basketball',
startTime: new Date().toISOString(),
endTime: '',
location: '',
maxParticipants: 10,
description: ''
};
@State isSubmitting: boolean = false;
build() {
Column() {
TextInput({ placeholder: 'Event title' })
.onChange((value: string) => {
this.event.title = value;
})
Picker({ range: ['Basketball', 'Soccer', 'Badminton', 'Table Tennis'] })
.onChange((index: number) => {
this.event.sportType = ['basketball', 'soccer', 'badminton', 'pingpong'][index];
})
DatePicker({ start: new Date() })
.onChange((date: Date) => {
this.event.startTime = date.toISOString();
})
TextInput({ placeholder: 'Event location' })
.onChange((value: string) => {
this.event.location = value;
})
Button('Create Event')
.onClick(() => this.submitEvent())
.disabled(this.isSubmitting)
}
}
private async submitEvent() {
this.isSubmitting = true;
try {
const success = await EventService.createEvent(this.event);
if (success) {
prompt.showToast({ message: 'Event created successfully' });
router.back();
}
} finally {
this.isSubmitting = false;
}
}
}
4.2 Event List and Details
// Event card component
@Component
struct EventCard {
private event: Event;
build() {
Column() {
Row() {
Image(this.event.coverImage || $r('app.media.default_cover'))
.width(80)
.height(80)
.borderRadius(8)
Column() {
Text(this.event.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(`${formatDate(this.event.startTime)} · ${this.event.location}`)
.fontSize(14)
.margin({ top: 4 })
}
.layoutWeight(1)
.margin({ left: 12 })
}
Divider()
.margin({ top: 8, bottom: 8 })
Row() {
ForEach(this.event.tags, (tag: string) => {
Text(tag)
.padding(4)
.backgroundColor('#f0f0f0')
.borderRadius(4)
.margin({ right: 6 })
})
Blank()
Text(`${this.event.joinedCount}/${this.event.maxParticipants}`)
}
}
.padding(12)
.borderRadius(12)
.backgroundColor(Color.White)
.shadow(2)
}
}
5. Sports Data Recording and Analysis
5.1 Health Data Integration
// Integrating system health services
class HealthDataService {
static async requestPermissions() {
try {
const health = await import('@ohos.health');
const permissions = [
'health.permission.READ_HEALTH_DATA',
'health.permission.WRITE_HEALTH_DATA'
];
const result = await abilityAccessCtrl.requestPermissionsFromUser(
getContext(),
permissions
);
return result.authResults.every(Boolean);
} catch (error) {
console.error('Permission request failed:', error);
return false;
}
}
static async getTodaySteps(): Promise<number> {
try {
const health = await import('@ohos.health');
const helper = health.createHealthHelper();
const end = new Date();
const start = new Date();
start.setHours(0, 0, 0, 0);
const options = {
startTime: start.getTime(),
endTime: end.getTime(),
dataType: 'steps'
};
const result = await helper.getStatData(options);
return result?.totalSteps || 0;
} catch (error) {
console.error('Failed to get step count:', error);
return 0;
}
}
}
5.2 Sports Data Visualization
// Sports data chart component
@Component
struct SportChart {
private data: SportRecord[];
build() {
Canvas({ context: this.ctx })
.width('100%')
.height(200)
.onReady(() => this.drawChart())
}
private drawChart() {
const ctx = this.ctx;
const width = ctx.width;
const height = ctx.height;
// Draw axes
ctx.beginPath();
ctx.moveTo(50, 30);
ctx.lineTo(50, height - 30);
ctx.lineTo(width - 30, height - 30);
ctx.stroke();
// Draw data line
const maxValue = Math.max(...this.data.map(d => d.value));
const xStep = (width - 80) / (this.data.length - 1);
ctx.beginPath();
this.data.forEach((item, index) => {
const x = 50 + index * xStep;
const y = height - 30 - (item.value / maxValue) * (height - 60);
if (index === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
// Draw data points
ctx.arc(x, y, 3, 0, Math.PI * 2);
});
ctx.strokeStyle = '#FF5722';
ctx.lineWidth = 2;
ctx.stroke();
}
}
6. App Optimization and Release
6.1 Performance Optimization Recommendations
- Lazy loading for images: Implement lazy loading for images in long lists
Image(this.item.image)
.lazyLoad(true)
.transitionEffect(TransitionEffect.NONE)
- Data caching: Use local storage wisely to reduce network requests
const storage = await import('@ohos.data.storage');
const localCache = storage.getStorage(getContext().cacheDir + '/sports_cache');
- Request batching: Combine high-frequency but non-real-time data requests
6.2 Pre-release Checklist
- Test all core functionality flows
- Verify adaptation across different device sizes
- Ensure privacy policy is complete
- Confirm app icons and splash screens meet specifications
- Prepare promotional materials required for app stores
Conclusion: Continuous Iteration and Community Collaboration
Through developing this sports app, I've deeply appreciated the power of the HarmonyOS Next ecosystem. Particularly, the backend services provided by AppGallery Connect enable individual developers to quickly build fully functional applications.
I recommend actively participating in the Huawei Developer Community to share development experiences. Several practical components I used in this project are open-source—search for "harmonyos-sports-kit" on GitHub to access them.
This content originally appeared on DEV Community and was authored by linzhongxue

linzhongxue | Sciencx (2025-05-28T00:57:11+00:00) Development Guide for Smart Sports Social Apps Based on HarmonyOS Next. Retrieved from https://www.scien.cx/2025/05/28/development-guide-for-smart-sports-social-apps-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.