Camera_API - boostcampwm-2024/and04-Nature-Album GitHub Wiki

Camera API ์กฐ์‚ฌ


https://developer.android.com/media/camera/choose-camera-library?hl=ko

๊ณต์‹๋ฌธ์„œ์—๋„ ๋‚˜์™€์žˆ๋“ฏ์ด CameraX๋Š” Camera2 ํŒจํ‚ค์ง€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋นŒ๋“œ๋œ๋‹ค.

Camera2๋Š” ๋ณต์žกํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ํ•˜์œ„ ์ˆ˜์ค€์˜ ์นด๋ฉ”๋ผ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฌธ์ œ๋Š” Camera2์˜ API๋Š” CameraX๋ณด๋‹ค ๋” ๋ณต์žกํ•˜๋‹ค.

๊ณต์‹๋ฌธ์„œ์—๋„ ๋‚˜์™€ ์žˆ๋“ฏ์ด ํ•˜์œ„ ์ˆ˜์ค€์˜ ์นด๋ฉ”๋ผ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹Œ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ CameraX์˜ ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋œ๋‹ค๊ณ  ๋‚˜์™€์žˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์„ ํƒ์ง€๋Š” ๊ทธ๋Ÿผ 2๊ฐ€์ง€์ด๋‹ค.

  1. Intent๋ฅผ ํ†ตํ•ด ๋‚ด์žฅ ์นด๋ฉ”๋ผ ๊ธฐ๋Šฅ ์‚ฌ์šฉ
  2. CameraX๋ฅผ ํ†ตํ•ด ์ปค์Šคํ…€

Q. ์šฐ๋ฆฌ ์•ฑ์—์„œ๋Š” ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ?

  1. Intent๋ฅผ ํ†ตํ•œ ๋‚ด์žฅ ์นด๋ฉ”๋ผ ๊ธฐ๋Šฅ ์‚ฌ์šฉ
    • Intent๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋‹ค๋งŒ, ๋‚ด์žฅ ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ฐ์€ ์‚ฌ์ง„์ด ๊ธฐ๊ธฐ ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅ๋˜๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.
      • ์šฐ๋ฆฌ๊ฐ€ ์ƒ๊ฐํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ์•ฑ ๋‚ด ๋„๊ฐ์—๋งŒ ์ €์žฅํ•˜๋Š” ๊ฒƒ.
      • ๋˜ ์ฐพ์•„๋ณด๋‹ˆ ๋ฌด์กฐ๊ฑด ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์—ˆ์Œ!!! ์•„๋งˆ๋‘,,,
      • ์–ด๋””์— ์ €์žฅ๋˜๋Š” ๊ฑด์ง€ ์ง์ ‘ ํ•ด๋ด์•ผํ•  ๊ฒƒ ๊ฐ™๋‹ค
  2. CameraX๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ๊ตฌํ˜„์ด ์กฐ๊ธˆ ๋ณต์žกํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋‹ค๋งŒ CameraX๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์–ป๋Š” ์ด์ ์ด ์žˆ๋‹ค.
      • ์‚ฌ์ง„ ์ดฌ์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋„ ์ž๋™์œผ๋กœ ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ƒ๊ฐํ–ˆ๋˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ์šฐ๋ฆฌ๊ฐ€ ํšŒ์˜์—์„œ ์ƒ๊ฐํ•œ GPS ๊ด€๋ จ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.
        • ์ฆ‰, ์นด๋ฉ”๋ผ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ, ๋ผ๋ฒจ์„ ์ง€์ •ํ•  ๋•Œ ๋‘ ๋ฒˆ ํ™•์ธํ•˜๋Š” ์ž‘์—…์„ ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค.
        • ๊ทธ๋ƒฅ ์นด๋ฉ”๋ผ ์ดฌ์˜ํ™”๋ฉด์—์„œ ๋„คํŠธ์›Œํฌ๊ฐ€ ๋Š๊ฒผ์„ ๋•Œ์ฒ˜๋Ÿผ ์ƒ๋‹จ์— [GPS๊ฐ€ ๊บผ์ ธ์žˆ์Šต๋‹ˆ๋‹ค] ์™€ ๊ฐ™์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ณ  ์‚ฌ์ง„ ์ดฌ์˜ ๋ฒ„ํŠผ์„ ๋ง‰์œผ๋ฉด ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

CameraX ์‹œ์ž‘ํ•˜๊ธฐ

https://developer.android.com/codelabs/camerax-getting-started?hl=ko#0

https://developer.android.com/media/camera/camerax/preview?hl=ko

CameraX๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” PreviewView ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์ฆ‰, XML ์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

์นด๋ฉ”๋ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

  1. PreviewView๋ฅผ ๋ ˆ์ด์•„์›ƒ์— ์ถ”๊ฐ€
  2. CameraProvider ์š”์ฒญ
  3. CameraProvider ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ

์ด๋ฏธ์ง€ ์บก์ณ โ†’ ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ๊ณผ์ •

  1. ImageCapture ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ฐธ์กฐ ๊ฐ€์ ธ์˜ค๊ธฐ
  2. ์ด๋ฏธ์ง€๋ฅผ ๋ณด๊ด€ํ•  MediaStore ์ฝ˜ํ…์ธ  ๊ฐ’์„ ๋งŒ๋“ค๊ธฐ
  3. OutputFileOptions ๊ฐ์ฒด ๋งŒ๋“ค์–ด์„œ ์ถœ๋ ฅ์„ MediaStore์— ์ €์žฅํ•˜์—ฌ ๋‹ค๋ฅธ ์•ฑ์—์„œ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก MediaStore ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€

์œ„ ๊ณผ์ •์—์„œ 2๋ฒˆ, 3๋ฒˆ ๊ณผ์ •์„ ํ•˜์ง€ ์•Š๊ณ  1๋ฒˆ ๊ณผ์ •์—์„œ์˜ ๊ฒฐ๊ณผ๋ฌผ๋งŒ ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค.

1๋ฒˆ ๊ณผ์ •์˜ ๊ฒฐ๊ณผ๋ฌผ์€ ImageProxy ์ด๊ณ , ์ด๊ฒƒ์„ ๋น„ํŠธ๋งต์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•  ๊ฒƒ ๊ฐ™๋‹ค.

1๋ฒˆ ๊ณผ์ •์—์„œ ์ด๋ฏธ์ง€ ๊ฒฐ๊ณผ๋ฌผ ๊ฐ€์ ธ์˜ค๊ธฐ

https://developer.android.com/reference/androidx/camera/core/ImageCapture.OnImageCapturedCallback

ImageCapture.OnImageCapturedCallback ์—์„œ onCaptureSuccess ์ฝœ๋ฐฑ ์ด์šฉํ•˜๊ธฐ

  • ๊ด€๋ จ ์ด๋ฏธ์ง€

    image.png

๋‹จ, ImageProxy ๋ฅผ ๋น„ํŠธ๋งต์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ถ”๊ฐ€ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

Q. Compose๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ• ๊นŒ?

  • ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋Š” ์•Š์€ ๊ฒƒ ๊ฐ™๋‹ค.

  • val previewView = remember { mutableStateOf<PreviewView>() } ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

Q. AndroidView???

https://developer.android.com/develop/ui/compose/migrate/interoperability-apis/views-in-compose?hl=ko

  • Compose UI ๋‚ด์— ๊ธฐ์กด Android View๋ฅผ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ปดํฌ์ €๋ธ”
    • Compose์—์„œ ์•„์ง ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” UI ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ํŠนํžˆ ์œ ์šฉ

Q. ๊ทธ๋ ‡๋‹ค๋ฉด NaverMap API์„ Compose์—์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ• ๊นŒ?

A. ๊ฐ€๋Šฅํ•˜๋‹ค..! โ† ๋ฌผ๋ก  ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์›€โ€ฆ ์•ˆ๊ทธ๋ž˜๋„ ๋ณต์žกํ•œ map api๋ฅผ 4์ฃผ์•ˆ์— ์ปดํฌ์ฆˆ๋กœ ๊ตฌํ˜„๊ฐ€๋Šฅํ•  ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š๋‹ค.

  • ์‹ค์ œ๋กœ ํšŒ์˜์—์„œ ์ด์•ผ๊ธฐ๋‚˜์˜จ https://github.com/fornewid/naver-map-compose ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ AndroidView๋ฅผ ํ™œ์šฉํ•œ ๊ฒƒ

  • ์œ„์—์„œ๋„ ๋งํ–ˆ๋˜ val mapView = remember { MapView(context, NaverMapOptions()) } ๋ฐฉ์‹์œผ๋กœ MapView๋ฅผ ๋ฐ›์•„์™€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

  • ์ฐธ๊ณ  ์ด๋ฏธ์ง€

    image.png

    image.png

๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ๊ฒฐ๋ก !

์‹œ๊ฐ„์ด ๋œ๋‹ค๋ฉด CameraX ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์ง€ ์•Š์„๊นŒ?

์ด์œ 

  • GPS ๊ถŒํ•œ ํ˜น์€ GPS ์ผœ์ง/๊บผ์ง ์— ๊ด€ํ•œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์šฉ์ดํ•  ๊ฒƒ ๊ฐ™๋‹ค.
    • ์นด๋ฉ”๋ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์—์„œ GPS๊ฐ€ ๊บผ์ ธ์žˆ๋‹ค๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ๊ณผ ๋™์‹œ์— ์ดฌ์˜ ๋ฒ„ํŠผ ๋น„ํ™œ์„ฑํ™”
    • ์ด ์™ธ์—๋„ ์ดฌ์˜๋œ ์‚ฌ์ง„์„ ๊ฐค๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹˜ ์šฐ๋ฆฌ ์•ฑ ๋‚ด ๋„๊ฐ์—๋งŒ ์ €์žฅํ•˜๊ธฐ.
  • ์ดํ›„ AI ๋„์ž…์„ ์ƒ๊ฐํ•œ๋‹ค๋ฉด CameraX ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๋‹ค.
    • ๊ณต์‹๋ฌธ์„œ์— ML Kit๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฒ„ํผ์— ์›ํ™œํ•˜๊ฒŒ ์•ก์„ธ์Šคํ•œ๋‹ค๊ณ  ๋‚˜์™€์žˆ๋‹ค!

๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒโ€ฆ ๊ทธ๋ƒฅ ๋‚ด์žฅ ์นด๋ฉ”๋ผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ๊ฒƒ ๊ฐ™๊ธฐ๋„ ํ•˜๋‹คโ€ฆ

https://developer.android.com/media/camera/camera-intents?hl=ko

๊ทผ๋ฐ ์›ƒ๊ธด๊ฒŒ ๊ณต์‹๋ฌธ์„œ ์ฝ”๋“œ๊ฐ€ deprecated ๋œ ์ฝ”๋“œ์ด๋‹ค ์—ฅ..

startActivityForResult โ†’ registerForActivityResult ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ด€๋ จ

1. CameraX๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด

๋งŒ์•ฝ CameraX๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

์šฐ์„  ์‚ฌ์ง„ ์ดฌ์˜ ํ›„ ๋ฐ˜ํ™˜๊ฐ’์€ ImageProxy ์ด๋‹ค.

์ด๊ฒƒ์„ ๋น„ํŠธ๋งต์œผ๋กœ ์ „ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด Firebase์„œ๋ฒ„์— (๋น„ํŠธ๋งต, ์œ„์น˜, ์‹œ๊ฐ„, ์‚ฌ์ง„ ์ œ๋ชฉ)์„ ์ €์žฅํ•ด์•ผ ํ•˜๋ฉฐ,

์ดํ›„์— ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ๋น„ํŠธ๋งต์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ๊ฒƒ.

์—์ดˆ์— ๋น„ํŠธ๋งต์—๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์—†์Œ.

๋น„ํŠธ๋งต : ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด

๋น„ํŠธ๋งต์€ ํ”ฝ์…€ ์ •๋ณด๋ฅผ ๋‹ค ์ €์žฅํ•ด์•ผ ํ•˜๊ธฐ์— ์šฉ๋Ÿ‰์ด ํฌ๊ณ  ์ฒ˜๋ฆฌ ์†๋„๊ฐ€ ๋А๋ฆฌ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ์••์ถ•ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ?

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” jpeg, jpg๊ฐ™์€ ํŒŒ์ผ์˜ ํ—ค๋” ๋ถ€๋ถ„์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ๋ณ„๋„๋กœ ExifInterface ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฐค๋Ÿฌ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

2. Intent ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด?

GPS๊ฐ€ ์ผœ์ ธ์žˆ์–ด์•ผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์œ„์น˜ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

๊ทผ๋ฐ ์–ด์ฉŒํ”ผ ์นœ๊ตฌ ์ด๋ฏธ์ง€ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด ๋น„ํŠธ๋งต์œผ๋กœ ์ €์žฅํ•ด์•ผํ•˜์ง€ ์•Š๋‚˜? ์•„๋‹ˆ๋ฉด ์ด๋ฏธ์ง€๋ฅผ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๊ณ  ํ•ด๋‹น uri๋ฅผ firestore์— ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ•˜๊ฑฐ๋‚˜.

์•„๋ฌดํŠผโ€ฆ ์•ฑ ๋‚ด๋ถ€ ์ €์žฅ์†Œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ฐค๋Ÿฌ๋ฆฌ์— ํ‘œ์‹œ๋˜์ง€ ์•Š๊ณ ๋„ Uri๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค?

(์ข€ ๋” ์กฐ์‚ฌ ํ•„์š”)

  1. MediaStore๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€ uri ๊ฐ€์ ธ์˜ค๊ธฐ
  2. ExifInterface ๋ฅผ ํ†ตํ•ด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ.

CameraX vs ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ

  • CameraX

CameraX ๋ฌธ์„œ์— GPS์— ๊ด€ํ•œ ๊ธ€์ด ์—†๋‹ค.

gpt๊ฐ€ CameraX๋กœ ์ฐ์€ ์‚ฌ์ง„์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— gps๊ฐ€ ์—†๋‹ค๊ณ  ํ–ˆ๋‹ค.

๊ทธ๋ž˜๋„ ํ˜น์‹œ๋‚˜ํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ  ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— gps๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ดค๋Š”๋ฐ ์•ˆ๋‚˜์™”๋‹ค.

image

์‚ฌ์ง„ ์ฐ๊ณ  ์œ„์น˜ ๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผ ํ• ๋“ฏ..?

  • ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ

๊ธฐ๋ณธ ์นด๋ฉ”๋ผ๋ฅผ ์ผœ์„œ ์œ„์น˜ ํƒœํฌ๋ฅผ ํ™œ์„ฑํ™” ํ•ด์ฃผ๋ฉด ์‚ฌ์ง„์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— gps ์ •๋ณด๊ฐ€ ์žˆ๋‹ค.

์ฐธ๊ณ ) ์นดํ†ก, ์Šฌ๋ ‰ โ†’ ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ๋กœ ์—ฐ๊ฒฐ

์žฅ๋‹จ์  ์ •๋ฆฌ

  • CameraX
    • ์žฅ์ 
      • ์•ฑ ๋‚ด์—์„œ ์‹ค์‹œ๊ฐ„ ์นด๋ฉ”๋ผ ํ™”๋ฉด์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ‰๋‹ค๋ฅธ ux ์ œ๊ณต
      • ์ปค์Šคํ…€ ๊ฐ€๋Šฅ
      • ๋‚˜์ค‘์— ๊ฐ์ฒด ์ธ์‹ํ•  ๋•Œ ๋„์›€์ด ๋  ์ˆ˜๋„
    • ๋‹จ์ 
      • ๊ธธ์–ด์ง€๋Š” ์ฝ”๋“œ ์ˆ˜โ€ฆ.
      • ์œ„์น˜ ์ •๋ณด๋ฅผ ์ง์ ‘ ๋„ฃ์–ด์ค˜์•ผ ํ•จ
  • ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ
    • ์žฅ์ 
      • ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„
      • ์œ„์น˜ ํƒœ๊ทธ๋ฅผ ํ™œ์„ฑํ™” ํ•˜๊ณ  ์ฐ์œผ๋ฉด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์œ„์น˜ ์ •๋ณด๊ฐ€ ์žˆ์Œ
    • ๋‹จ์ 
      • ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์œ„์น˜ ํƒœ๊ทธ๋ฅผ ํ™œ์„ฑํ™” ํ•ด์•ผํ•จ

extension๊ธฐ๋Šฅ(์นด๋ฉ”๋ผ ๋ชจ๋“œ: Auto, Bokeh, Face Retouch, HDR, Night)์€ sdk31|32์ด์ƒ ์ง€์›

Camera2/x ๊ฐ๊ฐ์€ sdk 21์ด์ƒ

Intent ์นด๋ฉ”๋ผ : ์•ฑ ์ž์ฒด์˜ GPS๊ถŒํ•œ์ด ๊บผ์ ธ ์žˆ์„ ๋•Œ ์œ„์น˜ํƒœ๊ทธ ์„ค์ • ๋ถˆ๊ฐ€

![image](https://github.com/user-attachments/assets/c82b657a-e39d-497a-af05-1ebb9860ac01)

๋‚ด๋ถ€ ์ €์žฅ(โ‰ DB)

![image](https://github.com/user-attachments/assets/902ef588-1406-4667-9a86-77a222b8599c)

~~์™ธ๋ถ€ ์ €์žฅ์†Œ์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๋‚ด๋ถ€ ์ €์žฅ์†Œ์— ์ €์žฅ ๊ฐ€๋Šฅ. BUT, Bitmap๋งŒ์„ Intent๋กœ ๋ฐ›์•„์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐx~~

~~โ‡’ Intent๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด~~

1. ~~์™ธ๋ถ€ ์ €์žฅ์†Œ์— ์‚ฌ์ง„(+๋ฉ”ํƒ€๋ฐ์ดํ„ฐ) ์ €์žฅํ›„ Bundle๋กœ URI๋ฅผ ๋ฐ›์•„์™€ ์•ฑ ๋‚ด๋ถ€์—์„œ ํŒŒ์ผ ์ฝ๊ธฐ~~
2. ~~Bundle๋กœ Bitmap์„ ๋ฐ›์•„์˜ค๊ณ , ์‹œ๊ฐ„/์œ„์น˜ ์ •๋ณด๋Š” ์•ฑ ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑ ๋ฐ ์ €์žฅ~~

~~์ถ”๊ฐ€๋กœ ๊ณ ๋ฏผํ•  ๋ถ€๋ถ„~~

- ~~DB์— Bitmap์œผ๋กœ ์ €์žฅ? โ†’ ์••์ถ•x, ์šฉ๋Ÿ‰ ์ปค์ง, ๋น„ํŠธ๋งต์„ ๋ฐ”๋กœ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Œ~~
- ~~๋‚ด๋ถ€ ์ €์žฅ์†Œ์— JPEG๋กœ ์ €์žฅ? โ†’ ์••์ถ•o, ์šฉ๋Ÿ‰ ์ค„์–ด๋“ฌ, DB์— URI๋ฅผ ์ €์žฅํ•ด ๋ถˆ๋Ÿฌ์˜ฌ๋•Œ ํ•œ๋‹จ๊ณ„๋ฅผ ๋” ๊ฑฐ์นจ~~

![image](https://github.com/user-attachments/assets/077beddb-889c-4b7f-8c18-9e111065d4de)

๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ ํฌํ•จํ•ด ์‚ฌ์ง„ ์ €์žฅ ๊ฐ€๋Šฅ!!!!!!!!!

API | ์ง€์› ์‹œ์ž‘ ๋ฒ„์ „ | ํ˜„์žฌ ์ƒํƒœ | ์ฃผ์š” ํŠน์ง• | ๊ถŒ์žฅ ์‚ฌ์šฉ ์—ฌ๋ถ€ -- | -- | -- | -- | -- ๋‚ด์žฅ ์นด๋ฉ”๋ผ | ๋ชจ๋“  ๋ฒ„์ „ | ํ™œ์„ฑ | ์‹œ์Šคํ…œ ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ ์•ฑ์„ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์ง„ ๋˜๋Š” ๋™์˜์ƒ์„ ์ดฌ์˜ํ•จ. | ํŠน์ • ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ Camera1 | API ๋ ˆ๋ฒจ 1 | ์‚ฌ์šฉ ์ค‘๋‹จ๋จ | ์ดˆ๊ธฐ ์นด๋ฉ”๋ผ API๋กœ, ์ œํ•œ๋œ ๊ธฐ๋Šฅ๊ณผ ๋ณต์žกํ•œ ์‚ฌ์šฉ๋ฒ•์„ ๊ฐ€์ง. | ์‚ฌ์šฉ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Œ Camera2 | API ๋ ˆ๋ฒจ 21 | ํ™œ์„ฑ | ํ–ฅ์ƒ๋œ ๊ธฐ๋Šฅ๊ณผ ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ๊ตฌํ˜„์ด ๋ณต์žกํ•จ. | ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ํ•„์š” ์‹œ ์‚ฌ์šฉ CameraX | API ๋ ˆ๋ฒจ 21 | ํ™œ์„ฑ | Camera2๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ Jetpack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ์‚ฌ์šฉ์ด ๊ฐ„ํŽธํ•˜๊ณ  ๊ธฐ๊ธฐ ํ˜ธํ™˜์„ฑ์ด ๋†’์Œ. | ์ผ๋ฐ˜์ ์œผ๋กœ ๊ถŒ์žฅ๋จ

1. ์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋จผ์ € ๋‚˜์˜ค๊ณ  ํ™•์žฅ๋˜์—ˆ๋Š”๊ฐ€?

  • Camera1์ด ๊ฐ€์žฅ ๋จผ์ € ๋„์ž…๋˜์—ˆ์œผ๋ฉฐ, ์ดํ›„ Camera2๊ฐ€ 1์„ ๋Œ€์ฒด

  • CameraX๋Š” Camera2๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ๋œ Jetpack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

    ์•ฑ์—์„œ Android 5.0(API ์ˆ˜์ค€ 21)๋ถ€ํ„ฐ ์ง€์› ์ค‘๋‹จ๋œ ์›๋ž˜ Camera ํด๋ž˜์Šค('Camera1')๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ตœ์‹  Android ์นด๋ฉ”๋ผ API๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

    https://developer.android.com/media/camera/camerax/camera1-to-camerax?hl=ko

2. ๊ณต์‹ ๋ฌธ์„œ๋Š” ์–ด๋–ค ์นด๋ฉ”๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ถŒ์žฅํ•˜๋Š”๊ฐ€?

  • ์•ˆ๋“œ๋กœ์ด๋“œ ๊ณต์‹ ๋ฌธ์„œ๋Š” CameraX ์‚ฌ์šฉ์„ ๊ถŒ์žฅ

  • ์‚ฌ์šฉ ํŽธ์˜์„ฑ, ๊ธฐ๊ธฐ ๊ฐ„ ์ผ๊ด€์„ฑ, ํ˜ธํ™˜์„ฑ ๋“ฑ์˜ ์ด์œ 

    CameraX๋Š” Android 5.0(API ์ˆ˜์ค€ 21) ์ด์ƒ์„ ์‹คํ–‰ํ•˜๋Š” ๊ธฐ๊ธฐ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ธฐ์กด Android ๊ธฐ๊ธฐ์˜ 98%๊ฐ€ ๋„˜์Šต๋‹ˆ๋‹ค.

    https://developer.android.com/media/camera/camerax/camera1-to-camerax?hl=ko

    • ๋˜ํ•œ, 1๊ณผ ๋‹ฌ๋ฆฌ X๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฐœ๋…์ ์œผ๋กœ ๋” ํŽธ๋ฆฌํ•จ
API ์ง€์› ์‹œ์ž‘ ๋ฒ„์ „ ํ˜„์žฌ ์ƒํƒœ ์ฃผ์š” ํŠน์ง• ๊ถŒ์žฅ ์‚ฌ์šฉ ์—ฌ๋ถ€
๋‚ด์žฅ ์นด๋ฉ”๋ผ ๋ชจ๋“  ๋ฒ„์ „ ํ™œ์„ฑ ์‹œ์Šคํ…œ ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ ์•ฑ์„ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์ง„ ๋˜๋Š” ๋™์˜์ƒ์„ ์ดฌ์˜ํ•จ. ํŠน์ • ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
Camera1 API ๋ ˆ๋ฒจ 1 ์‚ฌ์šฉ ์ค‘๋‹จ๋จ ์ดˆ๊ธฐ ์นด๋ฉ”๋ผ API๋กœ, ์ œํ•œ๋œ ๊ธฐ๋Šฅ๊ณผ ๋ณต์žกํ•œ ์‚ฌ์šฉ๋ฒ•์„ ๊ฐ€์ง. ์‚ฌ์šฉ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Œ
Camera2 API ๋ ˆ๋ฒจ 21 ํ™œ์„ฑ ํ–ฅ์ƒ๋œ ๊ธฐ๋Šฅ๊ณผ ์„ธ๋ฐ€ํ•œ ์ œ์–ด๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ๊ตฌํ˜„์ด ๋ณต์žกํ•จ. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ํ•„์š” ์‹œ ์‚ฌ์šฉ
CameraX API ๋ ˆ๋ฒจ 21 ํ™œ์„ฑ Camera2๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ Jetpack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ์‚ฌ์šฉ์ด ๊ฐ„ํŽธํ•˜๊ณ  ๊ธฐ๊ธฐ ํ˜ธํ™˜์„ฑ์ด ๋†’์Œ. ์ผ๋ฐ˜์ ์œผ๋กœ ๊ถŒ์žฅ๋จ

1. ์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋จผ์ € ๋‚˜์˜ค๊ณ  ํ™•์žฅ๋˜์—ˆ๋Š”๊ฐ€?

2. ๊ณต์‹ ๋ฌธ์„œ๋Š” ์–ด๋–ค ์นด๋ฉ”๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ถŒ์žฅํ•˜๋Š”๊ฐ€?

image

3. ๋‚ด์žฅ ์นด๋ฉ”๋ผ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋ฌด์—‡์ด ๋‹ค๋ฅธ๊ฐ€?

  • ๋‚ด์žฅ ์นด๋ฉ”๋ผ๋Š” ์‹œ์Šคํ…œ์˜ ๊ธฐ๋ณธ ์นด๋ฉ”๋ผ ์•ฑ์„ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์ง„์ด๋‚˜ ๋™์˜์ƒ์„ ์ดฌ์˜ํ•˜๋Š” ๋ฐฉ์‹
  • ์นด๋ฉ”๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์•ฑ ๋‚ด์—์„œ ์ง์ ‘ ์นด๋ฉ”๋ผ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Œ

3-1. ๋‚ด์žฅ ์นด๋ฉ”๋ผ๋กœ ์‚ฌ์ง„ ์ฐ๊ณ  ์ €์žฅ, ์œ„์น˜ ๊ฐ’ ์ €์žฅ ๋“ฑ์€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”๊ฐ€?

  • ๋‚ด์žฅ ์นด๋ฉ”๋ผ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Intent๋ฅผ ํ†ตํ•ด ์‹œ์Šคํ…œ์˜ ์นด๋ฉ”๋ผ ์•ฑ์„ ํ˜ธ์ถœํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์™€ ์ฒ˜๋ฆฌ
  • ์œ„์น˜ ์ •๋ณด๋Š” ๋ณ„๋„๋กœ LocationManager๋ฅผ ํ†ตํ•ด ํš๋“ํ•˜์—ฌ ์ €์žฅํ•ด์•ผ ํ•จ
    • ์•ˆ๋“œ๋กœ์ด๋“œ ์‹œ์Šคํ…œ ์นด๋ฉ”๋ผ์˜ ์‚ฌ์šฉ (https://m.blog.naver.com/kimbic_/223122736210)
    • **์•ˆ๋“œ๋กœ์ด๋“œ ์นด๋ฉ”๋ผX : ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ํ”„๋ฆฌ๋ทฐ(**https://m.blog.naver.com/kimbic_/223158937894)
      • ์นด๋ฉ”๋ผX๋Š” ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ์ด๋ฏธ์ง€๋ถ„์„, ์ด๋ฏธ์ง€์บก์ณ, ๋น„๋””์˜ค ์บก์ฒ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

Q. ๊ทผ๋ฐ ์ด์ „ LG ํ•ธ๋“œํฐ์€ ์œ„์น˜ ํƒœ๊ทธ ์žˆ์—ˆ๋‚˜?

https://www.samsungsvc.co.kr/solution/37015

3-2. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์ง„ ์ฐ๊ณ  ์ €์žฅ, ์œ„์น˜๊ฐ’ ์ €์žฅ์„ ๊ตฌํ˜„ํ•˜๋Š”๊ฐ€?

  • CameraX์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ฑ ๋‚ด์—์„œ ์ง์ ‘ ์‚ฌ์ง„ ์ดฌ์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
  • ์œ„์น˜ ์ •๋ณด๋Š” LocationManager๋ฅผ ํ†ตํ•ด ํš๋“ํ•œ ํ›„, ์ดฌ์˜ํ•œ ์ด๋ฏธ์ง€์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ €์žฅ

3-3. ๋‚ด์žฅ ์นด๋ฉ”๋ผ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”๊ฐ€?

  • ๋‚ด์žฅ ์นด๋ฉ”๋ผ๋Š” ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜์ง€๋งŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์–ด๋ ค์›€
  • ์นด๋ฉ”๋ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ฐ€๋Šฅ

4. Compose๋กœ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด ๋‚ด์žฅ ์นด๋ฉ”๋ผ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ์–ด๋– ํ•œ ๊ฒƒ์ด ์ ํ•ฉํ•œ๊ฐ€?

  1. CameraX๋กœ UI ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์–ด๋–ป๊ฒŒ ํ•˜๋‚˜?
  • CameraX๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‚ด์žฅ ์นด๋ฉ”๋ผ ์•ฑ๊ณผ ๋‹ฌ๋ฆฌ ์นด๋ฉ”๋ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ™”๋ฉด๊ณผ ์‚ฌ์ง„ ์ดฌ์˜ ๋ฒ„ํŠผ์„ ํฌํ•จํ•œ UI ์š”์†Œ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆํ•  ์ˆ˜ ์žˆ์–ด์„œ ์šฐ๋ฆฌ ์•ฑ ๋งŒ์˜ ์นด๋ฉ”๋ผ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๋“ฏํ•จ.
  • ์ดฌ์˜ ๋ฒ„ํŠผ ๋ฐ UI ์š”์†Œ์˜ ๋””์ž์ธ: ์‚ฌ์ง„ ์ดฌ์˜ ๋ฒ„ํŠผ, ๋™์˜์ƒ ๋…นํ™” ๋ฒ„ํŠผ ๋“ฑ ๋‹ค์–‘ํ•œ UI ์š”์†Œ๋ฅผ ์ง์ ‘ ๋””์ž์ธํ•˜๊ณ  ๋ฐฐ์น˜ ๊ฐ€๋Šฅํ•˜์—ฌ ์ด๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ ์•„์ด๋ดํ‹ฐํ‹ฐ์— ๋งž๋Š” ๊ณ ์œ ํ•œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๋ณด์ž„
  • ์คŒ, ํ”Œ๋ž˜์‹œ, ํ•„ํ„ฐ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ์–ดํ•  ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ํ•จ.
  • https://developer.android.com/codelabs/camerax-getting-started?hl=ko#8

image

  1. CameraX๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ง„์„ ์ดฌ์˜ํ•  ๋•Œ, ์œ„์น˜ ์ •๋ณด๋ฅผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ํฌํ•จ์‹œํ‚ค๋ ค๋ฉด?
  • ImageCapture.Metadata

    [getLocation](<https://developer.android.com/reference/androidx/camera/core/ImageCapture.Metadata#getLocation()>)()

    Gets the geographic location of the capture.

    1. ์œ„์น˜ ๊ถŒํ•œ ์š”์ฒญ ๋ฐ ์œ„์น˜ ์ •๋ณด ํš๋“:
    • ACCESS_FINE_LOCATION ๊ถŒํ•œ์„ ๋งค๋‹ˆํŽ˜์ŠคํŠธ์— ์„ ์–ธ
    • ๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ํ•ด๋‹น ๊ถŒํ•œ์„ ์š”์ฒญ
    • LocationManager ๋˜๋Š” FusedLocationProviderClient๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ
    1. ์ดฌ์˜ ์‹œ ์œ„์น˜ ์ •๋ณด ํฌํ•จ:
    • ImageCapture.OutputFileOptions.Builder๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ง„ ์ €์žฅ ์˜ต์…˜์„ ์„ค์ •ํ•  ๋•Œ, setMetadata() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์œ„์น˜ ์ •๋ณด๋ฅผ ํฌํ•จ
    • ImageCapture.Metadata ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , setLocation() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํš๋“ํ•œ ์œ„์น˜ ์ •๋ณด๋ฅผ ์„ค์ •
  1. LocationManager์™€ FusedLocationProvider์˜ ์ฐจ์ด์ 

    ํ•ญ๋ชฉ LocationManager FusedLocationProviderClient
    ์ œ๊ณต ์ฃผ์ฒด ์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๊ธฐ๋ณธ ์œ„์น˜ ์„œ๋น„์Šค Google Play ์„œ๋น„์Šค์˜ ์œ„์น˜ API
    ์œ„์น˜ ์ •๋ณด ์ˆ˜์ง‘ ๋ฐฉ์‹ GPS, ๋„คํŠธ์›Œํฌ ๋“ฑ ๊ฐœ๋ณ„ ํ”„๋กœ๋ฐ”์ด๋”๋ฅผ ํ†ตํ•ด ์ˆ˜์ง‘ GPS, Wi-Fi, ๊ฐ€์†๋„๊ณ„ ๋“ฑ ๋‹ค์–‘ํ•œ ์„ผ์„œ์™€ ์‹ ํ˜ธ๋ฅผ ์ง€๋Šฅ์ ์œผ๋กœ ๊ฒฐํ•ฉํ•˜์—ฌ ์ˆ˜์ง‘
    ์ •ํ™•๋„ ํ”„๋กœ๋ฐ”์ด๋”์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋ฉฐ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•จ ์—ฌ๋Ÿฌ ์†Œ์Šค๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ๋†’์€ ์ •ํ™•๋„์˜ ์œ„์น˜ ์ •๋ณด๋ฅผ ์ œ๊ณต
    ๋ฐฐํ„ฐ๋ฆฌ ํšจ์œจ์„ฑ ํ”„๋กœ๋ฐ”์ด๋” ์‚ฌ์šฉ์— ๋”ฐ๋ผ ๋ฐฐํ„ฐ๋ฆฌ ์†Œ๋ชจ๊ฐ€ ํด ์ˆ˜ ์žˆ์Œ ๋ฐฐํ„ฐ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ตœ์ ํ™”ํ•˜์—ฌ ํšจ์œจ์ ์ธ ์œ„์น˜ ์ •๋ณด๋ฅผ ์ œ๊ณต
    ์‚ฌ์šฉ ํŽธ์˜์„ฑ ์„ค์ •๊ณผ ๊ด€๋ฆฌ๊ฐ€ ๋ณต์žกํ•˜์—ฌ ๊ตฌํ˜„์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Œ ๊ฐ„๋‹จํ•œ API๋กœ ๊ตฌํ˜„์ด ์šฉ์ดํ•˜๋ฉฐ, ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ๋งž๋Š” ์œ„์น˜ ์š”์ฒญ ์˜ต์…˜์„ ์ œ๊ณต
    ์ง€์› ๋ฒ”์œ„ ๋ชจ๋“  ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ๊ธฐ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ Google Play ์„œ๋น„์Šค๊ฐ€ ์„ค์น˜๋œ ๊ธฐ๊ธฐ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    ์—…๋ฐ์ดํŠธ ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ์•ˆ๋“œ๋กœ์ด๋“œ OS ์—…๋ฐ์ดํŠธ๋ฅผ ํ†ตํ•ด ์œ ์ง€๋ณด์ˆ˜๋˜๋ฉฐ, ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๊ฐ€ ๋น„๊ต์  ๊น€ Google Play ์„œ๋น„์Šค ์—…๋ฐ์ดํŠธ๋ฅผ ํ†ตํ•ด ์ง€์†์ ์œผ๋กœ ๊ฐœ์„ ๋˜๋ฉฐ, ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด ๋น ๋ฅด๊ฒŒ ์ถ”๊ฐ€๋จ

    ์ตœ์‹  ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์—์„œ๋Š” FusedLocationProviderClient๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๊ถŒ์žฅ๋œ๋‹ค๊ณ  ํ•จ. ๋” ํšจ์œจ์ ์ด๊ณ  ์ •ํ™•ํ•œ ์œ„์น˜ ์ •๋ณด ๋•Œ๋ฌธ์ด๋‹ค.

โœ… CameraX๋ฅผ ์„ ํƒํ•˜๊ณ  ์‹ถ๋‹ค.

  1. ๊ฐ„ํŽธํ•œ ์‚ฌ์šฉ์„ฑ๊ณผ ๋†’์€ ํ˜ธํ™˜์„ฑ
    • CameraX๋Š” Jetpack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ Camera2์˜ ๋ณต์žกํ•จ์„ ๊ฐ„์†Œํ™”ํ•˜์—ฌ ๊ฐœ๋ฐœ์ž ์นœํ™”์ ์ธ API๋ฅผ ์ œ๊ณต
    • ์•ˆ๋“œ๋กœ์ด๋“œ 5.0(API ๋ ˆ๋ฒจ 21) ์ด์ƒ์„ ์ง€์›ํ•ด ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๊ธฐ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  2. UI ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์˜ ์šฉ์ด์„ฑ
    • CameraX๋Š” Camera2์™€ ๋‹ฌ๋ฆฌ, Jetpack Compose์™€์˜ ์—ฐ๋™์„ ํ†ตํ•ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ™”๋ฉด, ์ดฌ์˜ ๋ฒ„ํŠผ ๋“ฑ์˜ UI ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์–ด ํ”„๋กœ์ ํŠธ์˜ ๊ณ ์œ ํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณต
    • GPS ์—ฐ๊ฒฐ ์—ฌ๋ถ€๋‚˜ ๊ธฐํƒ€ ํ‘œ์‹œํ•˜๋ฉด ์ข‹์„ ๊ฒƒ๋„ UI๋กœ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•ด์„œ ํ‘œ์‹œ ๊ฐ€๋Šฅ
  3. ์œ„์น˜ ์ •๋ณด ์ €์žฅ ๊ธฐ๋Šฅ
    • CameraX๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ง„์„ ์ดฌ์˜ํ•  ๋•Œ, FusedLocationProviderClient๋กœ ํš๋“ํ•œ ์œ„์น˜ ์ •๋ณด๋ฅผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด, ์‚ฌ์ง„์— ์ดฌ์˜ ์œ„์น˜๋ฅผ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์Œ
      • FusedLocationProviderClient๋Š” GPS, Wi-Fi, ๊ฐ€์†๋„๊ณ„ ๋“ฑ ๋‹ค์–‘ํ•œ ์„ผ์„œ๋ฅผ ๊ฒฐํ•ฉํ•ด ๋†’์€ ์ •ํ™•๋„์˜ ์œ„์น˜ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ๋ฐฐํ„ฐ๋ฆฌ ํšจ์œจ์„ฑ ๋˜ํ•œ ์šฐ์ˆ˜ํ•˜๋‹ค๊ณ  ํ•จ. Google Play ์„œ๋น„์Šค์˜ ์œ„์น˜ API๋กœ ์ตœ์‹  ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ฐ˜์˜๋จ

์ฐธ๊ณ ์šฉ ์ฝ”๋“œ

```kotlin
fun getPhotoLocation(context: Context, uri: Uri): Pair<Double, Double>? {
        return try {
            // URI์—์„œ InputStream์„ ์–ป์–ด ExifInterface ์ƒ์„ฑ
            val inputStream = context.contentResolver.openInputStream(uri)
            val exif = inputStream?.let { ExifInterface(it) }
            inputStream?.close()

            // GPS ์œ„๋„์™€ ๊ฒฝ๋„ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
            val lat = exif?.getAttribute(ExifInterface.TAG_GPS_LATITUDE)
            val latRef = exif?.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF)
            val lon = exif?.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)
            val lonRef = exif?.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF)

            if (lat != null && lon != null && latRef != null && lonRef != null) {
                // ์œ„๋„ ๋ฐ ๊ฒฝ๋„ ๋ณ€ํ™˜
                val latitude = convertToDegree(lat, latRef)
                val longitude = convertToDegree(lon, lonRef)
                Log.d("GPSInfo","${latitude} - ${longitude}")
                Pair(latitude, longitude)
            } else {
                Log.d("GPSInfo", "์œ„์น˜ ์ •๋ณด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
                null
            }
        } catch (e: Exception) {
            e.printStackTrace()
            Log.d("GPSInfo","error")
            null
        }
    }
    private fun convertToDegree(value: String, ref: String): Double {
        val parts = value.split(",")

        // ๊ฐ ๋ถ€๋ถ„์„ ๋ถ„์ˆ˜ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
        val degrees = convertToDouble(parts[0].trim())
        val minutes = convertToDouble(parts[1].trim()) / 60
        val seconds = convertToDouble(parts[2].trim()) / 3600

        val result = degrees + minutes + seconds
        return if (ref == "S" || ref == "W") -result else result
    }

    private fun convertToDouble(value: String): Double {
        return if (value.contains("/")) {
            // ๋ถ„์ˆ˜ ํ˜•์‹ ์ฒ˜๋ฆฌ
            val fraction = value.split("/")
            if (fraction.size == 2) {
                fraction[0].toDouble() / fraction[1].toDouble()
            } else {
                0.0
            }
        } else {
            // ์ผ๋ฐ˜ ํ˜•์‹ ์ฒ˜๋ฆฌ
            value.toDoubleOrNull() ?: 0.0
        }
    }
โš ๏ธ **GitHub.com Fallback** โš ๏ธ