플러터:마이크 입력
보이기
- 플러터:개요
- 플러터:실행
- 플러터:개념 잡기
- 권한 사용
- 위젯
- 플러터:DB연결
- 플러터:Firebase(미완)
- 플러터:MySQL(미완)
- 디자인
- 플러터:배포
- 플러터:배포(안드로이드)(미완)
- 플러터:참고자료
- 플러터:위젯
- 플러터:구글 AdMob(미완)
- 플러터:라이브러리
개요
기기에서 마이크를 사용하는 법.
사전준비 권한 설정
권한 부여
| 항목 | 설명 | 비고 |
|---|---|---|
| 안드로이드 | android/app/src/main/AndroidManifest.xml 에 넣는다. |
|
| 아이폰 | ios/Runner/Info.plist에 넣는다. | <key>NSMicrophoneUsageDescription</key>
<string>앱에서 음성 입력을 사용합니다.</string> |
| Windows,
Web |
별도 설정 불필요. 자동으로 팝업이 뜸. |
필요한 패키지 점검
| 항목 | 설명 | 비고 |
|---|---|---|
| 패키지 설치 | dependencies:
flutter: sdk: flutter permission_handler: ^11.0.0 noise_meter: ^5.0.2 |
noise_meter는 db를 읽는다.
아마 시간이 지나면 오래된 버전이라 문제가 발생할 수 있음. flutter pub get |
데시벨 측정 예시 코드
마찬가지로 패키지 버전에 따라 함수명이 달라지기도 함. 오래되면 문제가 발생할 수 있음.
Flutter 데시벨 측정기 학습 위키
프로젝트 개요
- 목표: 실시간 마이크 입력으로 데시벨 측정
- 난이도: 초급 (코드 67줄)
- 학습 시간: 1-2시간
- 플랫폼: ✅ Android / ✅ iOS / ❌ Windows / ❌ Web
필요한 패키지
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
noise_meter: ^5.0.1 # 🎤 마이크 데시벨 측정
permission_handler: ^11.3.1 # 🔒 마이크 권한 관리
권한 설정
Android
파일: android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
iOS
파일: ios/Runner/Info.plist
<key>NSMicrophoneUsageDescription</key>
<string>데시벨 측정을 위해 마이크 권한이 필요합니다.</string>
완전한 소스코드
// filepath: c:\Temp\for device\decibel_app\lib\main.dart
import 'package:flutter/material.dart';
import 'package:noise_meter/noise_meter.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '데시벨 측정기',
home: DecibelMeter(),
);
}
}
class DecibelMeter extends StatefulWidget {
@override
_DecibelMeterState createState() => _DecibelMeterState();
}
class _DecibelMeterState extends State<DecibelMeter> {
double _currentDB = 0.0;
bool _isListening = false;
StreamSubscription<NoiseReading>? _noiseSubscription;
Future<void> _startListening() async {
// 마이크 권한 요청
var status = await Permission.microphone.request();
if (status.isGranted) {
_noiseSubscription = NoiseMeter().noise.listen(
(NoiseReading noiseReading) {
setState(() {
_currentDB = noiseReading.meanDecibel;
});
},
onError: (error) {
print('오류: $error');
},
);
setState(() {
_isListening = true;
});
}
}
void _stopListening() {
_noiseSubscription?.cancel();
setState(() {
_isListening = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('데시벨 측정기'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${_currentDB.toInt()} dB',
style: TextStyle(fontSize: 48),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isListening ? _stopListening : _startListening,
child: Text(_isListening ? '정지' : '시작'),
),
],
),
),
);
}
}
코드 구조 분석
핵심 클래스들
// 📊 데시벨 읽기
NoiseMeter().noise.listen((NoiseReading reading) {
double db = reading.meanDecibel; // 평균 데시벨
});
// 🔒 권한 요청
Permission.microphone.request();
// 🎛️ 스트림 제어
StreamSubscription<NoiseReading>? subscription;
상태 관리
class _DecibelMeterState extends State<DecibelMeter> {
double _currentDB = 0.0; // 현재 데시벨 값
bool _isListening = false; // 측정 중인지 상태
StreamSubscription<NoiseReading>? _noiseSubscription; // 스트림 구독 객체
}
동작 흐름
- 앱 시작
- 마이크 권한 요청
- 권한 허용 시 NoiseMeter 시작
- 실시간 데시벨 스트림 수신
- UI 업데이트 (setState)
- 정지 버튼으로 스트림 취소
주요 학습 포인트
1. 스트림(Stream) 패턴
// 스트림 구독
_subscription = NoiseMeter().noise.listen(
(data) => setState(() => _currentDB = data.meanDecibel),
onError: (error) => print('에러: $error'),
);
// 메모리 누수 방지
_subscription?.cancel();
2. 권한 관리
Future<void> _requestPermission() async {
var status = await Permission.microphone.request();
if (status.isGranted) {
// 권한 허용됨
} else if (status.isDenied) {
// 권한 거부됨
} else if (status.isPermanentlyDenied) {
// 영구 거부됨 - 설정으로 유도
openAppSettings();
}
}
3. 생명주기 관리
@override
void dispose() {
_noiseSubscription?.cancel(); // 위젯 해제 시 스트림 정리
super.dispose();
}
데시벨 참고값
| 데시벨(dB) | 소음 수준 | 예시 |
|---|---|---|
| 0-20 | 매우 조용 | 도서관, 속삭임 |
| 20-40 | 조용 | 조용한 사무실 |
| 40-60 | 보통 | 일반 대화 |
| 60-80 | 시끄러움 | TV, 음악 |
| 80-100 | 매우 시끄러움 | 지하철, 공사장 |
| 100+ | 위험 | 콘서트, 제트기 |
UI 개선 아이디어
데시벨 수준별 색상
Color _getDecibelColor(double db) {
if (db < 40) return Colors.green; // 조용
if (db < 70) return Colors.yellow; // 보통
return Colors.red; // 시끄러움
}
프로그레스 바
LinearProgressIndicator(
value: _currentDB / 120.0, // 120dB 기준
backgroundColor: Colors.grey[300],
valueColor: AlwaysStoppedAnimation(_getDecibelColor(_currentDB)),
)
트러블슈팅
권한 문제
// 권한 상태 확인
var status = await Permission.microphone.status;
if (status.isPermanentlyDenied) {
// 사용자를 설정으로 유도
showDialog(...);
}
플랫폼별 이슈
- Android:
RECORD_AUDIO권한 필수 - iOS:
Info.plist에 사용 목적 명시 필수 - Windows/Web:
noise_meter패키지 미지원
성능 최적화
// 백그라운드에서 정지
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_stopListening(); // 배터리 절약
}
}
플랫폼 지원 현황
| 플랫폼 | 지원 여부 | 이유 |
|---|---|---|
| Android | ✅ | 완전 지원 |
| iOS | ✅ | 완전 지원 |
| Windows | ❌ | noise_meter 미지원 |
| Web | ❌ | 마이크 API 제한 |
| macOS | ❓ | 테스트 필요 |
| Linux | ❓ | 테스트 필요 |
다음 단계 학습
중급 기능
- 📈 실시간 그래프 (charts_flutter)
- 💾 측정값 저장 (shared_preferences)
- 🔔 임계값 알림 (flutter_local_notifications)
고급 기능
- 🎵 주파수 분석 (FFT)
- 📊 통계 분석 (평균, 최대, 최소)
- 🌐 데이터 공유 (Firebase)
완성된 기능
- ✅ 실시간 데시벨 측정
- ✅ 마이크 권한 관리
- ✅ 간단한 시작/정지 제어
- ✅ 크로스 플랫폼 (Android/iOS)
- ✅ 메모리 안전 (스트림 정리)
이 프로젝트로 Flutter의 스트림, 권한, 네이티브 패키지 사용법을 모두 학습할 수 있습니다! 🎉