Upgrade to Pro — share decks privately, control downloads, hide ads and more …

카카오내비 카플레이/AndroidAuto 개발기

kakao
November 01, 2024

카카오내비 카플레이/AndroidAuto 개발기

#Carplay #Android-Auto #Navigation

카카오내비의 카플레이(CarPlay) 및 안드로이드 오토(Android Auto) 개발 과정을 다룹니다.
각 플랫폼에서의 구조적 고민, HUD 및 클러스터 기능 구현 등의 도전 과제와 개발 경험을 공유합니다.

발표자 : jin.jk, david.rx, beom.93

카카오내비 클라이언트앱 개발 담당하는 jin입니다.
카카오내비 iOS 카플레이 개발 담당하는 david 입니다.
카카오내비 Android-Auto 개발 담당하는 beom 입니다.

kakao

November 01, 2024
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. ର۝)FBE6Q%JTQMBZ )6% োز૑ਗ ֙ "OESPJE"VUP ֙ $BS1MBZ ର۝҅ӝ౸ DMVTUFS োز૑ਗ

    ֙ $BSQMBZ୹द "OESPJE"VUP୹द৘੿ ݽ߄ੌղ࠺ѱ੉࣌ࢲ࠺झ੄૓ച $BS1MBZ"OESPJE"VUP
  2. ݽ߄ੌ஠೒ۨ੉੄8JOEPX -JGF$ZDMF੄੉೧ ݫੋ ؀दࠁ٘ ௿۞झఠ ҅ӝ౸ CPTemplateApplicationSceneDelegate $18JOEPX $1*OUFSGBDF$POUSPMMFS CPTemplateApplicationDashboardSceneDelegate

    6*8JOEPX $1%BTICPBSE *OUFSGBDF$POUSPMMFS CPTemplateApplicationInstrumentClusterSceneDelegate 6*8JOEPX $1*OTUSVNFOU $MVTUFS$POUSPMMFS CPInstrumentClusterControllerDelegate
  3. ݽ߄ੌ஠೒ۨ੉੄8JOEPX -JGF$ZDMF੄੉೧ ݫੋ ؀दࠁ٘ ௿۞झఠ ҅ӝ౸ $18JOEPX $1*OUFSGBDF$POUSPMMFS 6*8JOEPX $1%BTICPBSE

    *OUFSGBDF$POUSPMMFS 6*8JOEPX $1*OTUSVNFOU $MVTUFS$POUSPMMFS UIWindow func instrumentClusterControllerDidZoom func instrumentClusterControllerDidZoomOut ... var shortcutButtons: [CPDashboardButton] func setRootTemplate ...
  4. $BS1MBZ5FNQMFUF "VEJP $PNNVOJDBUJPO /BWJHBUJPO %SJWJOHUBTL &7 DIBSHJOH GVFMJOH  QBSLJOH

    BOERVJDLGPPE PSEFSJOH "DUJPO4IFFU "MFSU (SJE -JTU 5BCCBS *OGPSNBUJPO 1PJOUPG*OUFSFTU /PX1MBZJOH $POUBDU .BQ 4FBSDI 7PJDFDPOUSPM
  5. $BS1MBZ5FNQMFUF ݫੋ $1*OUFSGBDF$POUSPMMFS let template = CPMapTemplate() template.mapDelegate = self

    template.tripEstimateStyle = .dark template.guidanceBackgroundColor = UIColor.blue interfaceController.setRootTemplate(template, animated: false, completion: nil)
  6. $BS1MBZ5FNQMFUF let menu1Button = CPGridButton(titleVariants: ["ݫ׏1"], image: menu1Icon) { button

    in } let menu2Button = CPGridButton(titleVariants: ["ݫ׏2"], image: menu2Icon) { button in } let menu3Button = CPGridButton(titleVariants: ["ݫ׏3"], image: menu3Icon) { button in } let template = CPGridTemplate( title: "Ѩ࢝", gridButtons: [menu1Button, menu2Button, menu3Button] ) interfaceController.pushTemplate(template, animated: true, completion: nil)
  7. $BS1MBZ5FNQMFUF func pushTemplate(_ templateToPush: CPTemplate, animated: Bool) async throws ->

    Bool CPInterfaceController func popTemplate(animated: Bool) async throws -> Bool 1VTI 1VTI 1VTI 1PQ5P3PPU func popToRootTemplate(animated: Bool) async throws -> Bool
  8. $BS1MBZ/BWJHBUJPO$POUSPMMFS final class CarPlayNavigationController: NSObject { private let cpInterfaceController: CPInterfaceController

    private var stacks: [CPTemplate] = [] init(cpInterfaceController: CPInterfaceController) { self.cpInterfaceController = cpInterfaceController super.init() cpInterfaceController.delegate = self } func push(_ template: CPTemplate, animate: Bool) async -> Bool { guard stacks.count < 5 else { #if DEBUG fatalError("CPInterfaceController's template is over 5 stacks.") #endif return false } guard let success = try? await self.cpInterfaceController.pushTemplate(template, animated: animate), success else { return false } self.stacks.append(template) return true } func pop(animate: Bool) async -> Bool { guard let success = try? await self.cpInterfaceController.popTemplate(animated: animate), success else { return false } let _ = self.stacks.removeLast() return true } func popToRoot(animate: Bool) async -> Bool { guard let success = try? await self.cpInterfaceController.popToRootTemplate(animated: animate), success else { return false } self.stacks.removeAll() return true } }
  9. ஠஠য়ղ࠺ݽ߄ੌ஠೒ۨ੉ҳઑ /BWJHBUJPO.BOBHFS 4%, %BUB1SPDFTTJOH#JOEJOH /BWJHBUJPO)FMQFS .PCJMF 7JFX.PEFM 6*7JFX$POUSPMMFS 4XJGU6*7JFX $PNNPO7JFX

    $BS1MBZ 6*7JFX$POUSPMMFS *OUFSGBDF$POUSPMMFS 7JFX.PEFM 7JFX.PEFM var roadSigns: [RoadSign] var isOnHighway: Bool var isOverSpeedLimit: Bool var distanceToLane: Int var isBusLaneUsable: Bool var remainRoadEvents: [RoadEvent] ... State
  10. ஠೒ۨ੉)6%ѐߊӝ 5VSO#Z5VSO 3PBE-BOF .FUB%BUB j $1/BWJHBUJPO4FTTJPO 🚘 let maneuver =

    CPManeuver() let instruction = ["౸Ү৉ ߑݶ"] maneuver.instructionVariants = instruction maneuver.symbolImage = directionImage if #available(iOS 17.4, *) { maneuver.maneuverType = CPManeuverType.rightTurn maneuver.trafficSide = .right maneuver.roadFollowingManeuverVariants = instruction } @available(iOS 17.4, *) public enum CPManeuverType : UInt, @unchecked Sendable { case noTurn = 0 case leftTurn = 1 case rightTurn = 2 case straightAhead = 3 case uTurn = 4 case followRoad = 5 ... } if #available(iOS 17.4, *) { maneuver.junctionType = .intersection maneuver.junctionExitAngle = Measurement(value: 15, unit: .degrees) }
  11. ীোѾਃ୒ CJOE4FSWJDF ഐझ౟ী؀ೠਬബࢿѨૐ 4FTTJPOё୓ܳా೧ର۝੿ࠁ  
 ௒ߔ ۄ੉೐ࢎ੉௿١ਸ੹׳  ࢤࢿ

    ௒ߔਸా೧5FNQMBUF੿ࠁ੹׳ 5FNQMBUF۪؊݂ࣻ೯ ஠஠য়ղ࠺оചݶীڵ $BS"QQ4FSWJDF *#JOEFS  ё୓੹׳ 4FTTJPO 4DSFFO 5FNQMBUF "OESPJE"VUPҳزߑध ખ؊੗ࣁ൤ ೻٘ਬ׫ীࢲ஠஠য়ղ࠺জਸ௿ܼ_୐ചݶ੉ڰӝө૑
  12. $BS"QQ4FSWJDF 4FTTJPO 4DSFFO 5FNQMBUF "OESPJE"VUPࢲ٘౵౭জѐߊ੄઱ਃஹನք౟  "OESPJE"VUP੄૓ੑ੼  ഐझ౟জҗোѾ࢚కܳҙܻೞҊ 

    
 4FTTJPOਸࢤࢿೠ׮  ର۝٣झ೒ۨ੉৬োѾغחё୓ 
 )FBE6OJJU4FTTJPO  
 $MVTUFS4FTTJPOj  4FTTJPOਸా೧ର۝٣झ೒ۨ੉৬ 
 ழޭפா੉࣌ਸೣ  5FNQMBUFਸҙܻೞӝਤೠഓ؊  "DUJWJUZ৬ਬࢎೠ৉ೡ  6*మ೒݁
  13. $BS"QQ4FSWJDF 4DSFFO 5FNQMBUF 4FTTJPO .BJO)FBE6OJU 4DSFFO 5FNQMBUF 5FNQMBUF 5FNQMBUF ,BLBP/BWJ

    "OESPJE"VUPഐझ౟জ .BJO)FBE6OJU $MVTUFS "OESPJE"VUPࢲ٘౵౭জѐߊ੄઱ਃஹನք౟ҙ҅ب 4FTTJPO $MVTUFS 4DSFFO 5FNQMBUF 5FNQMBUF 5FNQMBUF
  14. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  15. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  16. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  17. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  18. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  19. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  20. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  21. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  22. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  23. DMBTT4BNQMF4DSFFO QSJWBUFWBMDBS$POUFYU$BS$POUFYU 4DSFFO DBS$POUFYU \ PWFSSJEFGVOPO(FU5FNQMBUF 5FNQMBUF\ SFUVSO-JTU5FNQMBUF#VJMEFS TFU)FBEFS"DUJPO "DUJPO#"$,

    TFU5JUMF ࢠ೒ ఋ੉ౣ TFU4JOHMF-JTU DSFBUF*UFN-JTU CVJME ^ QSJWBUFGVODSFBUF*UFN-JTU *UFN-JTU\ SFUVSO*UFN-JTU#VJMEFS BQQMZ\ SFQFBU  \J -> UIJTBEE*UFN DSFBUF*UFN ই੉మ\J^ ^ ^CVJME ^ QSJWBUFGVODSFBUF*UFN UFYU4USJOH *UFN\ SFUVSO3PX#VJMEFS TFU5JUMF UFYU CVJME ^ ^ 5FNQMBUFҳഅрױ৘ઁ
  24. "VUPਊӡউղ 6TF$BTF ӡউղূ૓ 5FNQMBUF "VUP.BQ "DUJWJUZ "QQ7JFX.PEFM п੗ٮ۽ѐߊೠ׮ "VUPਊӡউղ 6TF$BTF

    "QQਊӡউղ 3FQPTJUPSZ $PNQPTF7JFX "QQ.BQ "QQਊӡউղ 6TF$BTF "OESPJE"VUP৬জѐߊബਯചী؀ೠҊ޹ "VUPਊӡউղ 6TF$BTF 4DSFFO "VUP7JFX.PEFM "VUPਊӡউղ 6TF$BTF "VUPਊӡউղ 3FQPTJUPSZ "VUPਊӡউղ 6TF$BTF
  25. ӡউղূ૓ ӡউղ3FQPTJUPSZ ӡউղ6TF$BTF j ҕਊ7JFX.PEFM ࠭ݽ؛۽૒ө૑э੉ࢎਊೠ׮ ӡউղ6TF$BTF ӡউղ6TF$BTF 5#57JFX.PEFM ಴૑౸7JFX.PEFM

    )6%7JFX.PEFM "OESPJE"VUP৬জѐߊബਯചী؀ೠҊ޹ $PNQPTF7JFX "QQ.BQ "DUJWJUZ 5FNQMBUF "VUP.BQ 4DSFFO "QQ7JFX.PEFM "VUP7JFX.PEFM
  26. $PNQPTF7JFX ҕਊ.BQ$POUSPMMFS j ૑ب۽૒بэ੉ࢎਊೠ׮ "QQ.BQ "DUJWJUZ "QQ.BQ$POUSPMMFS 4DSFFO "VUP.BQ$POUSPMMFS "VUP.BQ

    ݃ழ$POUSPMMFS ஠ݫۄ$POUSPMMFS ݗࣁ౴$POUSPMMFS 5FNQMBUF "OESPJE"VUP৬জѐߊബਯചী؀ೠҊ޹
  27. ƀ QSFTFOUBUJPO - OBWJ - BQQ QSFTFOUBUJPO - OBWJ -

    BVUP EBUB ӡউղ3FQPTJUPSZ*NQM ӡউղূ૓4%, ਬ੷੿ࠁ 3FQPTJUPSZ*NQM ӡউղࢸ੿ 3FQPTJUPSZ*NQM j QSFTFOUBUJPO - OBWJ - DPNNPO $PNQPOFOU7JFX.PEFMT $PNQPOFOU.BQ$POUSPMMFST ƀ j EPNBJO ӡউղद੘6TF$BTF ҃۽5#5-JTU6TF$BTF &5"6TF$BTF ಴૑౸6TF$BTF ҃۽੿ࠁ6TF$BTF ղ࠺"DUJWJUZ ղ࠺7JFX.PEFM ղ࠺4DSFFO ղ࠺7JFX.PEFM "OESPJE"VUP৬জѐߊബਯചী؀ೠҊ޹
  28. 2"