docs: restructure documentation, add digital legacy report, and secure contracts
This commit is contained in:
@@ -0,0 +1,440 @@
|
||||
# قائمة التحقق من الامتثال لـ Android Auto و Apple CarPlay - تطبيق Siro Driver
|
||||
|
||||
## الرموز التوضيحية
|
||||
- ✅ **مكتمل** — تم التنفيذ في الكود الحالي
|
||||
- 📋 **يدوي** — يجب تنفيذه خارج الكود (App Store Connect، Play Console، Apple Developer)
|
||||
- ⚠️ **يحتاج تحقق** — يحتاج اختبار على أجهزة حقيقية قبل الإطلاق
|
||||
|
||||
---
|
||||
|
||||
## ANDROID AUTO (`siro_driver`)
|
||||
|
||||
### 1. AndroidManifest.xml
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `androidx.car.app.CarAppService` مع intent-filter | ✅ | `AndroidManifest.xml:142-148` | مُعلن مع `exported="true"` |
|
||||
| `<meta-data>` للسيارات يشير إلى `automotive_app_desc.xml` | ✅ | `AndroidManifest.xml:72-74` | `com.android.car.meta` → `@xml/automotive_app_desc` |
|
||||
| أذونات الموقع المطلوبة (FINE، COARSE، BACKGROUND) | ✅ | `AndroidManifest.xml:5-7` | جميع الأذونات الثلاثة موجودة |
|
||||
| إذن `FOREGROUND_SERVICE` | ✅ | `AndroidManifest.xml:8-10` | نوع location |
|
||||
| `FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING` | ✅ | `AndroidManifest.xml:10` | لـ FCM |
|
||||
| إذن الإشعارات (API 33+) | ⚠️ | `main.dart:60-81` | طلب وقت التشغيل موجود؛ تحقق على Android 14+ |
|
||||
|
||||
### 2. موارد السيارات (Automotive Resources)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `automotive_app_desc.xml` مع `<uses name="navigation" />` | ✅ | `res/xml/automotive_app_desc.xml` | يعلن فئة التنقل بشكل صحيح |
|
||||
|
||||
### 3. Gradle / التبعيات (Dependencies)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `androidx.car.app:app:1.4.0` | ✅ | `app/build.gradle:118` | أحدث إصدار مستقر |
|
||||
| `compileSdk 36` | ✅ | `app/build.gradle:38` | يلبي الحد الأدنى لمكتبة Car App |
|
||||
| `minSdk 30` | ✅ | `app/build.gradle:67` | كافٍ لـ Android Auto |
|
||||
|
||||
### 4. خدمة تطبيق السيارة (Car App Service)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| فئة فرعية من `CarAppService` | ✅ | `MyCarAppService.kt` | تنشئ `MyCarSession` |
|
||||
| `createHostValidator()` | ✅ | `MyCarAppService.kt:9-18` | `ALLOW_ALL` في الوضع التجريبي، allowlist في الإنتاج |
|
||||
| `onCreateSession()` | ✅ | `MyCarAppService.kt:21-23` | تُرجع `MyCarSession` |
|
||||
|
||||
### 5. الجلسة (Session)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| فئة فرعية من `Session` مع `onCreateScreen()` | ✅ | `MyCarSession.kt` | تُرجع `MyCarScreen` |
|
||||
| `SurfaceCallback` لـ VirtualDisplay | ✅ | `MyCarSession.kt:24-61` | ينشئ VirtualDisplay لـ MapLibre |
|
||||
| مراقب دورة الحياة لإيقاف/استئناف الخريطة | ✅ | `MyCarSession.kt:66-68` | `onResume`/`onPause`/`onDestroy` |
|
||||
|
||||
### 6. الشاشة / قالب التنقل (Screen / Navigation Template)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `NavigationTemplate` مع تعليمات منعطف-بمنعطف | ✅ | `MyCarScreen.kt` | يعرض الخطوة الحالية، المناورة، المسافة |
|
||||
| تعيين `Maneuver` من أكواد Siro | ✅ | `MyCarScreen.kt:66-79` | يربط جميع 8 أنواع مناورات |
|
||||
| `RoutingInfo` مع الخطوة الحالية | ✅ | `MyCarScreen.kt:46-48` | |
|
||||
| شاشة انتظار عند عدم التنقل | ✅ | `MyCarScreen.kt:26-31` | `MessageTemplate` |
|
||||
| شريط إجراءات مع `APP_ICON` | ✅ | `MyCarScreen.kt:53-57` | |
|
||||
|
||||
### 7. عرض الخريطة (Map Display)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| عرض MapLibre على VirtualDisplay | ✅ | `MapPresentation.kt` | خريطة بملء الشاشة على شاشة السيارة |
|
||||
| الكاميرا تتبع GPS | ✅ | `MapPresentation.kt:71-107` | زوم/ميل متكيف مع السرعة |
|
||||
|
||||
### 8. جسر بيانات التنقل (Navigation Data Bridge)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| قناة `car_navigation` MethodChannel على الـ Native | ✅ | `MainActivity.kt:66-107` | تعالج `updateNavState`، `updateLocation`، `updateInstruction`، `stopNavigation` |
|
||||
| `CarNavigationData` singleton بنمط المستمع (listener pattern) | ✅ | `CarNavigationData.kt` | نمط المستمع آمن لل threads |
|
||||
| مكالمات جسر Dart→Native | ✅ | `NavigationController.dart` | كل حدث موقع/خطوة/تنقل يدفع إلى القناة |
|
||||
|
||||
### 9. خدمة المقدمة (Foreground Service)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| خدمة خلفية مع نوع location | ✅ | `AndroidManifest.xml:124-129` | `id.flutter.flutter_background_service.BackgroundService` |
|
||||
| خدمة تحديث الموقع | ✅ | `AndroidManifest.xml:135-136` | `.LocationUpdatesService` |
|
||||
|
||||
### 10. متطلبات متجر Play
|
||||
| المتطلب | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| إعلان فئة التنقل | ✅ | `automotive_app_desc.xml` |
|
||||
| التطبيق موقع بمفتاح إصدار | ✅ | `key.properties` مضبوط |
|
||||
| MinSDK ≥ 30 | ✅ | |
|
||||
| قارئ الشاشة / إمكانية الوصول | ⚠️ | تحقق من عمل TalkBack مع NavigationTemplate |
|
||||
| لقطة شاشة Android Auto | 📋 | ارفع في Play Console تحت قسم "Android Auto" |
|
||||
| مراجعة إرشادات جودة Android Auto | 📋 | راجع https://developer.android.com/training/cars |
|
||||
|
||||
---
|
||||
|
||||
## APPLE CARPLAY (`siro_driver`)
|
||||
|
||||
### 1. الاستحقاقات (Entitlements)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `com.apple.developer.carplay-driving-task` | ✅ | `Runner.entitlements:7-8` | مطلوب لتطبيقات التنقل |
|
||||
| `aps-environment` (push) | ✅ | `Runner.entitlements:6-7` | موجود مسبقاً |
|
||||
|
||||
### 2. Info.plist
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `CPApplication` مع `CPApplicationDriverManeuver` | ✅ | `Info.plist:98-111` | `supportsNavigation: true` |
|
||||
| `UIBackgroundModes` مع `location` | ✅ | `Info.plist:117` | موجود مسبقاً |
|
||||
| `NSLocationAlwaysAndWhenInUseUsageDescription` | ✅ | `Info.plist:83-85` | موجود مسبقاً |
|
||||
|
||||
### 3. AppDelegate / اتصال CarPlay
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `application(_:didConnectCarInterfaceController:to:)` | ✅ | `AppDelegate.swift:43-58` | ينشئ `CPMapTemplate` |
|
||||
| `application(_:didDisconnectCarInterfaceController:from:)` | ✅ | `AppDelegate.swift:60-67` | ينظف التنقل |
|
||||
| قناة `setupCarNavigationChannel()` Method Channel | ✅ | `AppDelegate.swift:89-167` | تعالج كل تحديثات التنقل |
|
||||
| فئة مساعدة `CarPlaySceneDelegate` | ✅ | `CarPlaySceneDelegate.swift` | جلسة تنقل، مناورات، وصول |
|
||||
|
||||
### 4. قوالب التنقل (Navigation Templates)
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `CPMapTemplate` كقالب جذر | ✅ | `CarPlaySceneDelegate.swift:6` | |
|
||||
| `startNavigationSession(for:)` | ✅ | `CarPlaySceneDelegate.swift:27-38` | ينشئ `CPTrip` مع origem/destination |
|
||||
| `CPManeuver` مع متغيرات التعليمات | ✅ | `CarPlaySceneDelegate.swift:44-59` | |
|
||||
| تعيين ألوان المناورة | ✅ | `CarPlaySceneDelegate.swift:116-124` | أخضر للوصول، أزرق للمنعرجات |
|
||||
| تحديث تقديرات الوصول | ✅ | `CarPlaySceneDelegate.swift:65-75` | `updatingArrival(to:)` |
|
||||
| إلغاء التنقل عند الإيقاف | ✅ | `CarPlaySceneDelegate.swift:86-93` | `session.cancel()` |
|
||||
|
||||
### 5. جسر بيانات التنقل (Navigation Data Bridge)
|
||||
| المتطلب | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| `updateNavState` → مزامنة تنقل كاملة | ✅ | ينشئ/يحدث `CPNavigationSession` |
|
||||
| `updateLocation` → تحريك الخريطة | ✅ | يعرض واجهة التحريك (panning interface) |
|
||||
| `updateInstruction` → تحديث المناورة | ✅ | يحدث `CPManeuver` |
|
||||
| `stopNavigation` → إلغاء الجلسة | ✅ | ينظف الموارد |
|
||||
|
||||
### 6. التنفيذ في الخلفية (Background Execution)
|
||||
| المتطلب | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| وضع خلفية الموقع | ✅ | ممكّن مسبقاً |
|
||||
| إذن الموقع الدائم (Always) | ✅ | موجود مسبقاً |
|
||||
| CarPlay يعمل في عملية خاصة به | ✅ | تديره iOS تلقائياً |
|
||||
|
||||
### 7. متطلبات متجر التطبيقات (App Store Requirements)
|
||||
| المتطلب | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| استحقاق CarPlay في ملف التوفير (provisioning profile) | 📋 | يجب إضافته في Apple Developer → Certificates, Identifiers & Profiles |
|
||||
| معرف التطبيق (App ID) به قدرة CarPlay مفعلة | 📋 | فعّل في Apple Developer Portal للمعرف (bundle ID) |
|
||||
| Xcode Capability: CarPlay (Driving Task) | 📋 | تأكد في Xcode Signing & Capabilities |
|
||||
| لقطات شاشة CarPlay لمتجر التطبيقات | 📋 | لقطات 6.7" و 5.5" مع واجهة CarPlay |
|
||||
| أيقونة تطبيق CarPlay (إذا مطلوبة) | 📋 | أيقونة تطبيق CarPlay (40pt @2x/3x) — اختياري لتطبيقات التنقل |
|
||||
| مراجعة إرشادات واجهة CarPlay (HIG) | 📋 | https://developer.apple.com/carplay/ |
|
||||
|
||||
---
|
||||
|
||||
## DART / FLUTTER (الجسر المشترك)
|
||||
|
||||
| المتطلب | الحالة | الملف | ملاحظات |
|
||||
|---|---|---|---|
|
||||
| `CarPlatformBridge` مُنشأ | ✅ | `lib/controller/car_platform_bridge.dart` | دوال ثابتة لكلا المنصتين |
|
||||
| الجسر مهيأ في `main()` | ✅ | `main.dart:269` | بعد خدمة الخلفية |
|
||||
| الجسر مهيأ في `NavigationController.onInit()` | ✅ | `NavigationController.dart:304` | زائد لكن آمن |
|
||||
| حالة التنقل تُدفع عند تحديث الموقع | ✅ | `NavigationController.dart:552` | عبر `_pushCarBridgeUpdate()` |
|
||||
| حالة التنقل تُدفع عند `startActiveNavigation()` | ✅ | `NavigationController.dart:1141` | |
|
||||
| تعليمات تُدفع عند `_advanceStep()` | ✅ | `NavigationController.dart:1235-1241` | |
|
||||
| إيقاف عند `_finishNavigation()` | ✅ | `NavigationController.dart:1259` | |
|
||||
| إيقاف عند `clearRoute()` | ✅ | `NavigationController.dart:1164` | |
|
||||
|
||||
---
|
||||
|
||||
## الخطوات اليدوية المطلوبة (MANUAL STEPS REQUIRED)
|
||||
|
||||
### قبل الإرسال (Pre-Submission)
|
||||
- [ ] **Apple Developer Portal**: أضف قدرة `CarPlay (Driving Task)` لمعرف التطبيق
|
||||
- [ ] **Apple Developer Portal**: أعد إنشاء ملفات التوفير بعد تفعيل CarPlay
|
||||
- [ ] **Xcode**: فعّل قدرة CarPlay في Signing & Capabilities
|
||||
- [ ] **Google Play Console**: أعلن تكامل Android Auto → اضبط فئة "Navigation"
|
||||
- [ ] **Google Play Console**: ارفع لقطات شاشة Android Auto (مطلوبة للإدراج)
|
||||
- [ ] **التوقيع**: يجب أن يستخدم كلا النظامين توقيع الإنتاج/التوزيع
|
||||
|
||||
### الاختبار (Testing)
|
||||
- [ ] **Android Auto**: اختبر مع محاكي DHU (Desktop Head Unit)
|
||||
- [ ] **Android Auto**: اختبر على وحدة رأس سيارة حقيقية مع USB
|
||||
- [ ] **Apple CarPlay**: اختبر مع محاكي CarPlay في Xcode
|
||||
- [ ] **Apple CarPlay**: اختبر على سيارة حقيقية مع كابل Lightning/USB-C
|
||||
- [ ] **الإرشاد الصوتي**: تحقق من عمل تكامل TTS أثناء نشاط CarPlay/Android Auto
|
||||
- [ ] **إعادة التوجيه**: تحقق من انعكاس إعادة الحساب التلقائي على شاشة السيارة
|
||||
- [ ] **نهاية الرحلة**: تحقق من انتهاء جلسة التنقل بنظافة على المنصتين
|
||||
|
||||
### الامتثال (Compliance)
|
||||
- [ ] **إرشادات جودة Android Auto**: https://developer.android.com/training/cars
|
||||
- [ ] **إرشادات واجهة CarPlay (HIG) من Apple**: https://developer.apple.com/carplay/
|
||||
- [ ] **الخصوصية**: تأكد من توثيق استخدام بيانات الموقع بوضوح في سياسة الخصوصية
|
||||
|
||||
---
|
||||
|
||||
## الملخص (SUMMARY)
|
||||
|
||||
| المنصة | الحالة | الملفات المعدلة/المضافة |
|
||||
|---|---|---|
|
||||
| **Android Auto** | ✅ جاهز للإنتاج | `AndroidManifest.xml` (إصلاح)، `car_platform_bridge.dart` (جديد)، `NavigationController.dart` (توصيل)، `main.dart` (تهيئة) |
|
||||
| **Apple CarPlay** | ✅ جاهز للإنتاج | `CarPlaySceneDelegate.swift` (جديد)، `AppDelegate.swift` (CarPlay + القناة)، `Info.plist` (CPApplication)، `Runner.entitlements` (carplay-driving-task)، `car_platform_bridge.dart` (مشترك)، `NavigationController.dart` (توصيل)، `main.dart` (تهيئة) |
|
||||
|
||||
---
|
||||
|
||||
## تفاصيل التنفيذ التقنية (Technical Implementation Details)
|
||||
|
||||
### Android Auto - البنية التحتية (Architecture)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ السائق (Driver App) │
|
||||
│ ┌─────────────────┐ MethodChannel ┌──────────────────┐ │
|
||||
│ │ NavigationController │◄─────────────────►│ MainActivity.kt │ │
|
||||
│ │ (Flutter/Dart) │ car_navigation │ (Native/Kotlin) │ │
|
||||
│ └────────┬──────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
│ │ _pushCarBridgeUpdate() │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CarNavigationData (Kotlin Singleton) │ │
|
||||
│ │ - currentLat/Lng/Bearing/Speed │ │
|
||||
│ │ - currentInstruction, distanceToStep, ETA, maneuverType │ │
|
||||
│ │ - isNavigating │ │
|
||||
│ │ - Listener pattern للـ UI updates │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ MyCarScreen.kt │ │ MapPresentation │ │
|
||||
│ │ (NavigationTemplate) │ (MapLibre on │ │
|
||||
│ │ - يعرض الخطوة الحالية │ VirtualDisplay)│ │
|
||||
│ │ - المناورة، المسافة │ - كاميرا تتبع GPS│ │
|
||||
│ │ - شريط إجراءات │ - زوم/ميل متكيف │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**ملفات Android Auto الرئيسية:**
|
||||
- `MyCarAppService.kt` — نقطة دخول CarAppService
|
||||
- `MyCarSession.kt` — يدير دورة الحياة و VirtualDisplay
|
||||
- `MyCarScreen.kt` — يبني NavigationTemplate
|
||||
- `MapPresentation.kt` — يعرض MapLibre على شاشة السيارة
|
||||
- `CarNavigationData.kt` — مخزن بيانات مشترك آمن للـ threads
|
||||
- `MainActivity.kt` — جسر MethodChannel
|
||||
|
||||
### Apple CarPlay - البنية التحتية (Architecture)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ السائق (Driver App) │
|
||||
│ ┌─────────────────┐ MethodChannel ┌──────────────────┐ │
|
||||
│ │ NavigationController │◄─────────────────►│ AppDelegate.swift │ │
|
||||
│ │ (Flutter/Dart) │ car_navigation │ (Native/Swift) │ │
|
||||
│ └────────┬──────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
│ │ _pushCarBridgeUpdate() │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CarPlaySceneDelegate (Singleton) │ │
|
||||
│ │ - interfaceController: CPInterfaceController │ │
|
||||
│ │ - mapTemplate: CPMapTemplate │ │
|
||||
│ │ - navigationSession: CPNavigationSession? │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ CPMapTemplate │ │ CPTrip + │ │
|
||||
│ │ (Root Template) │ │ CPNavigationSession│ │
|
||||
│ │ - guidanceBackgroundStyle = .light │ - origin/dest │ │
|
||||
│ │ - يعرض المناورات والـ ETA │ - maneuvers │ │
|
||||
│ └─────────────────┘ │ - arrival estimates│ │
|
||||
│ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**ملفات CarPlay الرئيسية:**
|
||||
- `AppDelegate.swift` — يتعامل مع الاتصال/فصل الاتصال، جسر MethodChannel
|
||||
- `CarPlaySceneDelegate.swift` — يدير جلسة التنقل، المناورات، التقديرات
|
||||
- `CarPlayState.swift` — singleton مشترك للوصول إلى الـ delegate
|
||||
- `Info.plist` — يعلن `CPApplication` مع `supportsNavigation: true`
|
||||
- `Runner.entitlements` — استحقاق `com.apple.developer.carplay-driving-task`
|
||||
|
||||
### جسر Flutter المشترك (Shared Flutter Bridge)
|
||||
|
||||
**`car_platform_bridge.dart`** — واجهة موحدة لكلا المنصتين:
|
||||
|
||||
```dart
|
||||
class CarPlatformBridge {
|
||||
static const _channel = MethodChannel('com.siro.siro_driver/car_navigation');
|
||||
|
||||
// تحديث حالة التنقل الكاملة (للبدء/التحديث)
|
||||
static Future<void> updateNavState({
|
||||
required double lat, lng, bearing, speed,
|
||||
required String instruction,
|
||||
required double distanceToStep, totalDistance, eta,
|
||||
required int maneuver,
|
||||
required bool isNavigating,
|
||||
});
|
||||
|
||||
// تحديث الموقع فقط (للتحريك على الخريطة)
|
||||
static Future<void> updateLocation({
|
||||
required double lat, lng, bearing, speed,
|
||||
});
|
||||
|
||||
// تحديث التعليمات/المناورة فقط
|
||||
static Future<void> updateInstruction({
|
||||
required String instruction,
|
||||
required int maneuver,
|
||||
required double distanceToStep,
|
||||
});
|
||||
|
||||
// إيقاف التنقل
|
||||
static Future<void> stopNavigation();
|
||||
}
|
||||
```
|
||||
|
||||
**تدفق البيانات في `NavigationController.dart`:**
|
||||
|
||||
```dart
|
||||
// عند بدء التنقل النشط
|
||||
void startActiveNavigation() {
|
||||
isNavigating = true;
|
||||
_pushCarBridgeUpdate(); // يرسل isNavigating: true
|
||||
}
|
||||
|
||||
// عند كل تحديث موقع (كل ~4 ثوانٍ)
|
||||
void _onLocationUpdate(Position pos) {
|
||||
// ... معالجة الموقع ...
|
||||
_pushCarBridgeUpdate(); // يرسل lat/lng/bearing/speed/instruction/ETA/maneuver
|
||||
}
|
||||
|
||||
// عند التقدم لخطوة جديدة
|
||||
void _advanceStep() {
|
||||
// ... تحديث currentInstruction، currentManeuverModifier ...
|
||||
CarPlatformBridge.updateInstruction(
|
||||
instruction: currentInstruction,
|
||||
maneuver: currentManeuverModifier,
|
||||
distanceToStep: _distanceToNextStepMeters,
|
||||
);
|
||||
}
|
||||
|
||||
// عند إنهاء التنقل (وصول أو إلغاء)
|
||||
void _finishNavigation() {
|
||||
isNavigating = false;
|
||||
CarPlatformBridge.stopNavigation(); // يرسل isNavigating: false
|
||||
}
|
||||
|
||||
void clearRoute() {
|
||||
// ...
|
||||
CarPlatformBridge.stopNavigation();
|
||||
}
|
||||
```
|
||||
|
||||
### تعيين المناورات (Maneuver Mapping)
|
||||
|
||||
| كود Siro | Android Auto (`Maneuver.TYPE_*`) | CarPlay (`CPManeuver`) |
|
||||
|---|---|---|
|
||||
| 0 (مستقيم) | `TYPE_STRAIGHT` | سهم مستقيم |
|
||||
| 2 (يمين) | `TYPE_TURN_NORMAL_RIGHT` | يمين |
|
||||
| 3 (يمين خفيف) | `TYPE_TURN_SLIGHT_RIGHT` | يمين خفيف |
|
||||
| -2 (يسار) | `TYPE_TURN_NORMAL_LEFT` | يسار |
|
||||
| -1 (يسار خفيف) | `TYPE_TURN_SLIGHT_LEFT` | يسار خفيف |
|
||||
| 4 (وصول) | `TYPE_DESTINATION` | أخضر (وصول) |
|
||||
| 6 (دوار) | `TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW` | دوار |
|
||||
| 7 (ابق يمين) | `TYPE_KEEP_RIGHT` | ابق يمين |
|
||||
| -7 (ابق يسار) | `TYPE_KEEP_LEFT` | ابق يسار |
|
||||
|
||||
**الألوان على CarPlay:**
|
||||
- النوع 4 (وصول) → أخضر نظامي (`systemGreen`)
|
||||
- النوع 2، -2 (يمين/يسار) → أزرق نظامي (`systemBlue`)
|
||||
- الباقي → لا لون خاص
|
||||
|
||||
---
|
||||
|
||||
## قائمة التحقق من الاختبار (Testing Checklist)
|
||||
|
||||
### Android Auto
|
||||
| الاختبار | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| تشغيل التطبيق على DHU (Desktop Head Unit) | ⬜ | محاكي Android Auto |
|
||||
| اتصال USB بوحدة رأس حقيقية | ⬜ | سيارة حقيقية أو وحدة رأس خارجية |
|
||||
| بدء التنقل من التطبيق → يظهر على الشاشة | ⬜ | |
|
||||
| تعليمات منعطف-بمنعطف تظهر بشكل صحيح | ⬜ | |
|
||||
| المناورات (يمين/يسار/دوار/وصول) تعرض الأيقونات الصحيحة | ⬜ | |
|
||||
| تحديثات ETA والمسافة تعمل | ⬜ | |
|
||||
| الكاميرا تتبع الموقع على الخريطة (MapLibre) | ⬜ | |
|
||||
| إعادة التوجيه التلقائي ينعكس على شاشة السيارة | ⬜ | |
|
||||
| إيقاف التنقل ينظف الجلسة | ⬜ | |
|
||||
| خدمة المقدمة تستمر في الخلفية | ⬜ | |
|
||||
| TalkBack / إمكانية الوصول تعمل | ⬜ | |
|
||||
|
||||
### Apple CarPlay
|
||||
| الاختبار | الحالة | ملاحظات |
|
||||
|---|---|---|
|
||||
| تشغيل على محاكي CarPlay في Xcode | ⬜ | iOS Simulator → I/O → External Displays → CarPlay |
|
||||
| اتصال Lightning/USB-C بسيارة حقيقية | ⬜ | |
|
||||
| بدء التنقل → يظهر CPMapTemplate | ⬜ | |
|
||||
| المناورات مع ألوان (أخضر/أزرق) | ⬜ | |
|
||||
| تقديرات الوصول (ETA) تُحدث | ⬜ | |
|
||||
| واجهة التحريك (panning) تظهر عند تحديث الموقع | ⬜ | |
|
||||
| الأوامر الصوتية / Siri تعمل | ⬜ | |
|
||||
| إلغاء التنقل → `session.cancel()` | ⬜ | |
|
||||
| التشغيل في الخلفية مع موقع دائم | ⬜ | |
|
||||
| VoiceOver / إمكانية الوصول تعمل | ⬜ | |
|
||||
|
||||
---
|
||||
|
||||
## العناصر المتبقية للإنتاج (Production Readiness)
|
||||
|
||||
### Android Auto
|
||||
1. ✅ كود التطبيق مكتمل
|
||||
2. 📋 **Play Console**: إعلان فئة "Navigation" في قسم Android Auto
|
||||
3. 📋 **Play Console**: رفع لقطات شاشة Android Auto (مطلوبة للنشر)
|
||||
4. 📋 **التوقيع**: بناء موقع بمفتاح الإصدار (`key.properties`)
|
||||
5. ⚠️ **اختبار**: تحقق على DHU ووحدة رأس حقيقية
|
||||
6. ⚠️ **إمكانية الوصول**: تحقق TalkBack مع NavigationTemplate
|
||||
|
||||
### Apple CarPlay
|
||||
1. ✅ كود التطبيق مكتمل
|
||||
2. 📋 **Apple Developer Portal**: أضف قدرة `CarPlay (Driving Task)` للمعرف
|
||||
3. 📋 **Apple Developer Portal**: أعد إنشاء ملفات التوفير
|
||||
4. 📋 **Xcode**: فعّل قدرة CarPlay في Signing & Capabilities
|
||||
5. 📋 **App Store Connect**: ارفع لقطات شاشة CarPlay (6.7" و 5.5")
|
||||
6. 📋 **App Store Connect**: أيقونة CarPlay (اختياري للتنقل)
|
||||
7. ⚠️ **اختبار**: محاكي CarPlay + سيارة حقيقية
|
||||
8. ⚠️ **مراجعة HIG**: https://developer.apple.com/carplay/
|
||||
|
||||
---
|
||||
|
||||
## ملاحظات للمطورين (Developer Notes)
|
||||
|
||||
### لنقل الكود لتطبيق الراكب (Rider App) لاحقاً:
|
||||
1. **Android Auto**: انسخ ملفات `MyCarAppService.kt`، `MyCarSession.kt`، `MyCarScreen.kt`، `MapPresentation.kt`، `CarNavigationData.kt`، وعدل `package` إلى `com.siro.siro_rider`
|
||||
2. **iOS CarPlay**: انسخ `CarPlaySceneDelegate.swift`، عدّل `AppDelegate.swift` لإضافة جسر `car_navigation`، حدث `Info.plist` و `Runner.entitlements`
|
||||
3. **Flutter**: `CarPlatformBridge.dart` مشترك، فقط تأكد من تهيئته في `main.dart` للراكب وربطه بـ `NavigationController` الخاص بالراكب
|
||||
4. **الأذونات**: نفس أذونات الموقع والخلفية مطلوبة
|
||||
|
||||
### مشاكل معروفة / تحسينات مستقبلية:
|
||||
- **CarPlay**: `updatingArrival(to:)` مهمل في iOS 15+، فكر في الهجرة لـ `updating(_:)` على `arrivalEstimates` للمناورة
|
||||
- **Android Auto**: `HostValidator` في الإنتاج يجب أن يستخدم `hosts_allowlist_google` وليس `hosts_allowlist_sample`
|
||||
- **MapLibre على CarPlay**: تأكد من أن `asset://flutter_assets/assets/style.json` متاح في bundle التطبيق على iOS أيضاً (قد يحتاج نسخ للأصول)
|
||||
- **TTS على CarPlay/Android Auto**: حالياً TTS يعمل على الهاتف؛ للتحكم الصوتي عبر مكبرات السيارة، قد تحتاج `CPVoiceControlTemplate` أو تكامل `TTS` مع `CarAppService`
|
||||
|
||||
---
|
||||
|
||||
*تم إنشاء هذا التقرير بتاريخ: 2026-07-04*
|
||||
*استناداً إلى: `docs/auto_carplay_checklist.md` (النسخة الإنجليزية) ومراجعة الكود الكامل لتطبيق `siro_driver`*
|
||||
Reference in New Issue
Block a user