- iOS는 조도 센서/백그라운드 서비스가 불가능해서 근접센서(UIDevice proximityMonitoring) + 가이드 접근 안내로 대체 구현 (Core NFC와 마찬가지로 네이티브 플러그인 필요해서 ProximityMonitorPlugin.swift 추가) - 교사 대시보드 실시간 출석 현황: 모바일 리스트/데스크톱 표를 타일 그리드로 통일해서 한눈에 보기 쉽게 변경 - 서버를 학교 자체 서버(Cloudflare Tunnel, api.backsanhi.shop)로 이전하면서 기본 BASE_URL 갱신 - Firebase CLI 로컬 캐시(.firebase/)는 소스가 아니라 gitignore 처리 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
84 lines
3.3 KiB
Dart
84 lines
3.3 KiB
Dart
// 🌐 앱 전역 공통 설정 및 유틸 함수 모음
|
|
// (서버 주소, FCM 관련 상수/함수, 기기 UUID 조회 등 여러 화면에서 공유하는 것들)
|
|
import 'dart:io';
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
|
|
|
// 🌐 학교마다 다른 값들. 빌드할 때 --dart-define으로 안 넘기면 지금 쓰는
|
|
// 백산고 값이 그대로 기본값이 된다 (기존 빌드 명령이 안 깨지게 하기 위함).
|
|
// 예: flutter build web --dart-define=BASE_URL=https://다른학교도메인.com
|
|
const String baseUrl = String.fromEnvironment(
|
|
'BASE_URL',
|
|
defaultValue: 'https://api.backsanhi.shop',
|
|
);
|
|
|
|
// 🔑 웹에서 FCM 토큰을 받으려면 필요한 VAPID 키
|
|
// (Firebase Console > 프로젝트 설정 > Cloud Messaging > 웹 구성 > 웹 푸시 인증서에서 발급)
|
|
// 학교마다 Firebase 프로젝트가 다르므로 VAPID 키도 학교별로 --dart-define=WEB_VAPID_KEY=...로 지정.
|
|
const String webVapidKey = String.fromEnvironment(
|
|
'WEB_VAPID_KEY',
|
|
defaultValue:
|
|
'BG4LnirukBdW3cXVWxhvY9pcjevBKDhpsaq1SLZdBs2cOEiwLAFyuuZLkMqpEGp9uOuHdPOe_y3FdwdZaz3qdfk',
|
|
);
|
|
|
|
// 🏫 앱/로그인 화면에 표시할 학교 이름. --dart-define=SCHOOL_NAME=...으로 학교별 지정.
|
|
const String schoolName = String.fromEnvironment(
|
|
'SCHOOL_NAME',
|
|
defaultValue: '백산고등학교',
|
|
);
|
|
|
|
// 권한 요청 및 FCM 토큰을 가져와서 콘솔에 출력하는 함수
|
|
Future<void> printFCMToken() async {
|
|
try {
|
|
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
|
|
|
// 1. 🚨 안드로이드/iOS 알림 권한 요청 (이 코드가 핵심이야!)
|
|
print("🚨 [FCM] 알림 권한 요청 중...");
|
|
NotificationSettings settings = await messaging.requestPermission(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
|
|
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
|
|
print("🚨 [FCM] 알림 권한 허용됨! 🎉");
|
|
} else if (settings.authorizationStatus == AuthorizationStatus.denied) {
|
|
print("🚨 [FCM] 알림 권한 거부됨... 😢 (설정에서 직접 켜야 합니다)");
|
|
}
|
|
|
|
// 2. 토큰 불러오기 (웹은 VAPID 키가 필요함)
|
|
print("🚨 [FCM] 토큰을 불러오는 중...");
|
|
String? token = kIsWeb
|
|
? await messaging.getToken(vapidKey: webVapidKey)
|
|
: await messaging.getToken();
|
|
|
|
if (token != null) {
|
|
print("🚨 [FCM 토큰 발급 성공] 👉 $token");
|
|
} else {
|
|
print("🚨 [FCM 토큰] 토큰이 null입니다.");
|
|
}
|
|
} catch (e) {
|
|
print("🚨 [FCM 토큰 에러] 👉 $e");
|
|
}
|
|
}
|
|
|
|
// 📱 폰의 고유 식별 번호(UUID)를 가져오는 공통 함수
|
|
Future<String> getDeviceUuid() async {
|
|
final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
|
String uuid = "UNKNOWN_DEVICE";
|
|
|
|
try {
|
|
if (Platform.isAndroid) {
|
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
|
uuid = androidInfo.id; // 안드로이드 폰의 고유 하드웨어 ID 추출
|
|
} else if (Platform.isIOS) {
|
|
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
|
uuid = iosInfo.identifierForVendor ?? "UNKNOWN_IOS"; // iOS 고유 ID
|
|
}
|
|
} catch (e) {
|
|
print("기기 ID 추출 failed: $e");
|
|
}
|
|
return uuid;
|
|
}
|