You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter集成Airoha SDK AAR文件实现与Airoha芯片耳机通信

Flutter集成Airoha AAR SDK实现耳机通信指南

一、确认AAR集成配置正确性

先检查你已完成的配置是否符合标准,避免基础配置错误:

  • 在android/app/build.gradle的dependencies块中添加本地AAR依赖:
    implementation files('libs/airoha-sdk.aar') // 替换为你的AAR文件名
    
  • 在android/build.gradle的allprojects.repositories中确保包含本地libs目录:
    allprojects {
        repositories {
            google()
            mavenCentral()
            flatDir {
                dirs 'libs'
            }
        }
    }
    

注:AGP 7.0+版本的Flutter项目,settings.gradle无需额外配置本地仓库,旧版本可能需要手动引入,可根据实际情况调整。

二、Platform Channel完整实现流程

1. Flutter端封装SDK调用方法

创建Dart工具类,统一管理与原生端的通信:

import 'package:flutter/services.dart';

class AirohaHeadphoneManager {
  static const MethodChannel _channel = MethodChannel('airoha_headphone_channel');

  // 初始化Airoha SDK
  static Future<bool> initSdk() async {
    try {
      return await _channel.invokeMethod('initSdk');
    } on PlatformException catch (e) {
      print('初始化失败: ${e.message}');
      return false;
    }
  }

  // 扫描附近的Airoha耳机
  static Future<List<dynamic>> scanHeadphones() async {
    try {
      return await _channel.invokeMethod('scanHeadphones');
    } on PlatformException catch (e) {
      print('扫描失败: ${e.message}');
      return [];
    }
  }

  // 连接指定耳机
  static Future<bool> connectHeadphone(String deviceId) async {
    try {
      return await _channel.invokeMethod('connectHeadphone', {'deviceId': deviceId});
    } on PlatformException catch (e) {
      print('连接失败: ${e.message}');
      return false;
    }
  }

  // 获取耳机电量
  static Future<int> getBatteryLevel() async {
    try {
      return await _channel.invokeMethod('getBatteryLevel');
    } on PlatformException catch (e) {
      print('获取电量失败: ${e.message}');
      return -1;
    }
  }
}

2. Android端实现Channel处理逻辑

在MainActivity.kt(或Java)中对接Airoha SDK的核心功能,处理Flutter端的方法调用:

Kotlin版本:

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import com.airoha.sdk.AirohaSdk // 替换为AAR实际包路径

class MainActivity : FlutterActivity() {
    private val CHANNEL = "airoha_headphone_channel"
    private lateinit var airohaSdk: AirohaSdk

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // 初始化Airoha SDK
        airohaSdk = AirohaSdk(applicationContext)
        
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "initSdk" -> {
                    val isSuccess = airohaSdk.init()
                    result.success(isSuccess)
                }
                "scanHeadphones" -> {
                    // 处理SDK异步扫描逻辑,通过回调返回结果给Flutter
                    val devices = mutableListOf<Map<String, Any>>()
                    airohaSdk.startScan(object : AirohaSdk.ScanCallback {
                        override fun onDeviceFound(deviceId: String, deviceName: String) {
                            devices.add(mapOf("deviceId" to deviceId, "deviceName" to deviceName))
                        }

                        override fun onScanFinish() {
                            result.success(devices)
                        }
                    })
                }
                "connectHeadphone" -> {
                    val deviceId = call.argument<String>("deviceId") ?: ""
                    val isConnected = airohaSdk.connect(deviceId)
                    result.success(isConnected)
                }
                "getBatteryLevel" -> {
                    val batteryLevel = airohaSdk.getBatteryLevel()
                    result.success(batteryLevel)
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 释放SDK资源,避免内存泄漏
        airohaSdk.release()
    }
}

三、关键注意事项

  • 权限配置:在android/app/src/main/AndroidManifest.xml中添加蓝牙相关权限,适配不同Android版本:
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 10+ 扫描需要 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <!-- Android 12+ -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 12+ -->
    
  • 异步操作处理:Airoha SDK的扫描、连接等核心操作多为异步回调模式,Android端必须通过回调将结果返回给Flutter,不能直接同步返回。
  • SDK包路径验证:若导入SDK类时出现报错,可解压AAR文件查看classes.jar中的包结构,确认正确的导入路径。
  • 生命周期管理:在Activity的onDestroy方法中调用SDK的资源释放方法,避免内存泄漏。

四、Flutter端调用示例

在页面中调用封装好的方法,实现耳机扫描、连接功能:

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

class HeadphoneScreen extends StatefulWidget {
  const HeadphoneScreen({super.key});

  @override
  State<HeadphoneScreen> createState() => _HeadphoneScreenState();
}

class _HeadphoneScreenState extends State<HeadphoneScreen> {
  List<dynamic> _devices = [];
  int _batteryLevel = -1;

  @override
  void initState() {
    super.initState();
    _initSdk();
  }

  Future<void> _initSdk() async {
    bool success = await AirohaHeadphoneManager.initSdk();
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(success ? "SDK初始化成功" : "SDK初始化失败")),
    );
  }

  Future<void> _scanDevices() async {
    List<dynamic> devices = await AirohaHeadphoneManager.scanHeadphones();
    setState(() => _devices = devices);
  }

  Future<void> _connectDevice(String deviceId) async {
    bool connected = await AirohaHeadphoneManager.connectHeadphone(deviceId);
    if (connected) {
      int battery = await AirohaHeadphoneManager.getBatteryLevel();
      setState(() => _batteryLevel = battery);
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("耳机连接成功")));
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("耳机连接失败")));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Airoha耳机管理")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            ElevatedButton(onPressed: _scanDevices, child: const Text("扫描耳机")),
            const SizedBox(height: 16),
            Expanded(
              child: ListView.builder(
                itemCount: _devices.length,
                itemBuilder: (context, index) {
                  var device = _devices[index];
                  return ListTile(
                    title: Text(device['deviceName']),
                    subtitle: Text(device['deviceId']),
                    trailing: ElevatedButton(
                      onPressed: () => _connectDevice(device['deviceId']),
                      child: const Text("连接"),
                    ),
                  );
                },
              ),
            ),
            if (_batteryLevel != -1)
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text("当前耳机电量: $_batteryLevel%"),
              ),
          ],
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者RRR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 18:20:02