CameraX इस्तेमाल के केस का रोटेशन

इस विषय में, अपने ऐप्लिकेशन में CameraX के इस्तेमाल के उदाहरणों को सेट अप करने का तरीका बताया गया है. इससे, आपको घुमाव की सही जानकारी वाली इमेज मिलती हैं. भले ही, इमेज ImageAnalysis या ImageCapture के इस्तेमाल के उदाहरण से ली गई हों. इसलिए:

  • ImageAnalysis इस्तेमाल के उदाहरण के Analyzer को सही रोटेशन वाले फ़्रेम मिलेंगे.
  • ImageCapture के इस्तेमाल के उदाहरण में, सही रोटेशन के साथ फ़ोटो लेनी चाहिए.

शब्दावली

इस विषय में इन शब्दों का इस्तेमाल किया गया है. इसलिए, यह समझना ज़रूरी है कि हर शब्द का क्या मतलब है:

डिसप्ले की दिशा
इससे पता चलता है कि डिवाइस का कौनसा हिस्सा ऊपर की ओर है. इसकी चार वैल्यू हो सकती हैं: पोर्ट्रेट, लैंडस्केप, रिवर्स पोर्ट्रेट या रिवर्स लैंडस्केप.
डिसप्ले का रोटेशन
यह वैल्यू, Display.getRotation() से मिलती है. इससे पता चलता है कि डिवाइस को उसके सामान्य ओरिएंटेशन से, घड़ी की उल्टी दिशा में कितने डिग्री घुमाया गया है.
टारगेट रोटेशन
इससे पता चलता है कि डिवाइस को घड़ी की दिशा में कितने डिग्री घुमाकर, उसके सामान्य ओरिएंटेशन पर लाया जा सकता है.

टारगेट रोटेशन तय करने का तरीका

यहां दिए गए उदाहरणों में, किसी डिवाइस के नैचुरल ओरिएंटेशन के आधार पर, उसके लिए टारगेट रोटेशन तय करने का तरीका बताया गया है.

उदाहरण 1: पोर्ट्रेट का सामान्य ओरिएंटेशन

डिवाइस का उदाहरण: Pixel 3 XL

नैचुरल ओरिएंटेशन = पोर्ट्रेट
मौजूदा ओरिएंटेशन = पोर्ट्रेट

डिसप्ले रोटेशन = 0
टारगेट रोटेशन = 0

नैचुरल ओरिएंटेशन = पोर्ट्रेट
मौजूदा ओरिएंटेशन = लैंडस्केप

डिसप्ले रोटेशन = 90
टारगेट रोटेशन = 90

दूसरा उदाहरण: लैंडस्केप का सामान्य ओरिएंटेशन

डिवाइस का उदाहरण: Pixel C

नेचुरल ओरिएंटेशन = लैंडस्केप
मौजूदा ओरिएंटेशन = लैंडस्केप

डिसप्ले रोटेशन = 0
टारगेट रोटेशन = 0

नैचुरल ओरिएंटेशन = लैंडस्केप
मौजूदा ओरिएंटेशन = पोर्ट्रेट

डिसप्ले रोटेशन = 270
टारगेट रोटेशन = 270

इमेज घुमाना

कौनसा सिरा ऊपर है? Android में सेंसर ओरिएंटेशन को एक तय वैल्यू के तौर पर तय किया गया है. यह डिग्री (0, 90, 180, 270) दिखाता है, जो डिवाइस के ऊपर से सेंसर के घूमने की स्थिति को दिखाता है. डायग्राम में दिए गए सभी उदाहरणों के लिए, इमेज घुमाने की सुविधा से पता चलता है कि डेटा को सीधा दिखाने के लिए, उसे घड़ी की सुई के घूमने की दिशा में कैसे घुमाया जाना चाहिए.

नीचे दिए गए उदाहरणों से पता चलता है कि कैमरे के सेंसर के ओरिएंटेशन के आधार पर, इमेज का रोटेशन कैसा होना चाहिए. यह भी माना जाता है कि टारगेट रोटेशन, डिसप्ले रोटेशन पर सेट है.

पहला उदाहरण: सेंसर को 90 डिग्री घुमाया गया

डिवाइस का उदाहरण: Pixel 3 XL

डिसप्ले का घुमाव = 0
डिसप्ले का ओरिएंटेशन = पोर्ट्रेट
इमेज का घुमाव = 90

डिसप्ले का घुमाव = 90
डिसप्ले का ओरिएंटेशन = लैंडस्केप
इमेज का घुमाव = 0

दूसरा उदाहरण: सेंसर को 270 डिग्री घुमाया गया

डिवाइस का उदाहरण: Nexus 5X

डिसप्ले रोटेशन = 0
डिसप्ले ओरिएंटेशन = पोर्ट्रेट
इमेज रोटेशन = 270

डिसप्ले का घुमाव = 90
डिसप्ले का ओरिएंटेशन = लैंडस्केप
इमेज का घुमाव = 180

तीसरा उदाहरण: सेंसर को 0 डिग्री पर घुमाया गया

डिवाइस का उदाहरण: Pixel C (टैबलेट)

डिसप्ले का घुमाव = 0
डिसप्ले का ओरिएंटेशन = लैंडस्केप
इमेज का घुमाव = 0

डिसप्ले का घुमाव = 270
डिसप्ले का ओरिएंटेशन = पोर्ट्रेट
इमेज का घुमाव = 90

इमेज के रोटेशन का हिसाब लगाना

ImageAnalysis

ImageAnalysis के Analyzer को कैमरे से ImageProxy के तौर पर इमेज मिलती हैं. हर इमेज में रोटेशन की जानकारी होती है. इसे इनके ज़रिए ऐक्सेस किया जा सकता है:

val rotation = imageProxy.imageInfo.rotationDegrees

यह वैल्यू, घड़ी की सुई की दिशा में इमेज को घुमाने के लिए ज़रूरी डिग्री दिखाती है, ताकि वह ImageAnalysis के टारगेट रोटेशन से मैच कर सके. Android ऐप्लिकेशन के संदर्भ में, ImageAnalysis का टारगेट रोटेशन आम तौर पर स्क्रीन के ओरिएंटेशन से मेल खाएगा.

ImageCapture

कैप्चर का नतीजा तैयार होने पर सिग्नल देने के लिए, ImageCapture इंस्टेंस में कॉलबैक अटैच किया जाता है. नतीजा, कैप्चर की गई इमेज या गड़बड़ी हो सकती है.

फ़ोटो खींचते समय, दिया गया कॉलबैक इनमें से किसी एक तरह का हो सकता है:

  • OnImageCapturedCallback: इसमें ImageProxy के तौर पर, मेमोरी में मौजूद इमेज का ऐक्सेस मिलता है.
  • OnImageSavedCallback: यह तब ट्रिगर होता है, जब ImageCapture.OutputFileOptions से तय की गई जगह पर, कैप्चर की गई इमेज को सेव कर लिया जाता है. विकल्पों में File, OutputStream या MediaStore में कोई जगह शामिल हो सकती है.

कैप्चर की गई इमेज के रोटेशन का मतलब है कि उसे कितने डिग्री घुमाया गया है. भले ही, इमेज का फ़ॉर्मैट ImageProxy, File, OutputStream, MediaStore Uri में से कोई भी हो. ImageCapture के टारगेट रोटेशन से मैच करने के लिए, कैप्चर की गई इमेज को घड़ी की दिशा में घुमाया जाना चाहिए. आम तौर पर, Android ऐप्लिकेशन के संदर्भ में, यह स्क्रीन के ओरिएंटेशन से मैच करेगा.

कैप्चर की गई इमेज के रोटेशन को वापस पाने के लिए, इनमें से किसी एक तरीके का इस्तेमाल किया जा सकता है:

ImageProxy

val rotation = imageProxy.imageInfo.rotationDegrees

File

val exif = Exif.createFromFile(file)
val rotation = exif.rotation

OutputStream

val byteArray = outputStream.toByteArray()
val exif = Exif.createFromInputStream(ByteArrayInputStream(byteArray))
val rotation = exif.rotation

MediaStore uri

val inputStream = contentResolver.openInputStream(outputFileResults.savedUri)
val exif = Exif.createFromInputStream(inputStream)
val rotation = exif.rotation

इमेज के रोटेशन की पुष्टि करना

ImageAnalysis और ImageCapture के इस्तेमाल के उदाहरणों में, कैप्चर करने का अनुरोध पूरा होने के बाद, कैमरे से ImageProxy मिलते हैं. ImageProxy, इमेज और उसके बारे में जानकारी को रैप करता है. इसमें इमेज के घुमाव की जानकारी भी शामिल होती है. रोटेशन की इस जानकारी से पता चलता है कि इस्तेमाल के उदाहरण के टारगेट रोटेशन से मैच करने के लिए, इमेज को कितने डिग्री पर घुमाना होगा.

इमेज के रोटेशन की पुष्टि करने का फ़्लो

ImageCapture/ImageAnalysis टारगेट रोटेशन के लिए दिशा-निर्देश

कई डिवाइसों पर डिफ़ॉल्ट रूप से, रिवर्स पोर्ट्रेट या रिवर्स लैंडस्केप मोड में स्क्रीन नहीं घूमती. इसलिए, कुछ Android ऐप्लिकेशन इन ओरिएंटेशन में काम नहीं करते. किसी ऐप्लिकेशन के साथ इस सुविधा के काम करने या न करने से, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करने के तरीके में बदलाव होता है.

यहां दो टेबल दी गई हैं. इनमें, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को डिसप्ले रोटेशन के साथ सिंक रखने का तरीका बताया गया है. पहले उदाहरण में, चारों ओरिएंटेशन के साथ ऐसा करने का तरीका बताया गया है. वहीं, दूसरे उदाहरण में सिर्फ़ उन ओरिएंटेशन के बारे में बताया गया है जिनमें डिवाइस डिफ़ॉल्ट रूप से घूमता है.

अपने ऐप्लिकेशन में कौनसे दिशा-निर्देश अपनाने हैं, यह चुनने के लिए:

  1. पुष्टि करें कि आपके ऐप्लिकेशन के कैमरे Activity का ओरिएंटेशन लॉक है या अनलॉक है. इसके अलावा, यह भी देखें कि क्या यह ओरिएंटेशन कॉन्फ़िगरेशन में किए गए बदलावों को बदल देता है.

  2. यह तय करें कि आपके ऐप्लिकेशन के कैमरे Activity को डिवाइस के चारों ओरिएंटेशन (पोर्ट्रेट, रिवर्स पोर्ट्रेट, लैंडस्केप, और रिवर्स लैंडस्केप) में से किस ओरिएंटेशन में काम करना चाहिए या सिर्फ़ उस ओरिएंटेशन में काम करना चाहिए जो डिवाइस पर डिफ़ॉल्ट रूप से काम करता है.

सभी चार ओरिएंटेशन के साथ काम करना

इस टेबल में, उन मामलों के लिए कुछ दिशा-निर्देश दिए गए हैं जिनमें डिवाइस, रिवर्स पोर्ट्रेट मोड में नहीं घूमता. यह तरीका उन डिवाइसों पर भी लागू किया जा सकता है जो रिवर्स लैंडस्केप मोड में नहीं घूमते.

स्थिति दिशा-निर्देश सिंगल-विंडो मोड मल्टी-विंडो स्प्लिट-स्क्रीन मोड
अनलॉक किए गए डिवाइस का ओरिएंटेशन हर बार Activity बनाने पर, इस्तेमाल के उदाहरण सेट अप करें. जैसे, Activity के onCreate() कॉलबैक में.
OrientationEventListener के onOrientationChanged() का इस्तेमाल करें. कॉलबैक में, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. यह उन मामलों में काम आता है जहां ओरिएंटेशन बदलने के बाद भी, सिस्टम Activity को फिर से नहीं बनाता. जैसे, जब डिवाइस को 180 डिग्री घुमाया जाता है. यह तब भी काम करता है, जब डिसप्ले रिवर्स पोर्ट्रेट ओरिएंटेशन में हो और डिवाइस डिफ़ॉल्ट रूप से रिवर्स पोर्ट्रेट में न घूमे. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.
ज़रूरी नहीं: AndroidManifest फ़ाइल में, Activity की screenOrientation प्रॉपर्टी को fullSensor पर सेट करें. इससे डिवाइस के रिवर्स पोट्रेट मोड में होने पर, यूज़र इंटरफ़ेस (यूआई) को सही तरीके से दिखाया जा सकता है. साथ ही, डिवाइस को 90 डिग्री घुमाने पर, सिस्टम Activity को फिर से बना सकता है. जिन डिवाइसों पर डिफ़ॉल्ट रूप से रिवर्स पोर्ट्रेट मोड में स्क्रीन नहीं घूमती उन पर इसका कोई असर नहीं पड़ता. डिसप्ले के रिवर्स पोर्ट्रेट ओरिएंटेशन में, मल्टी-विंडो मोड काम नहीं करता.
लॉक किया गया ओरिएंटेशन इस्तेमाल के उदाहरणों को सिर्फ़ एक बार सेट अप करें, जब Activity पहली बार बनाया जाता है. जैसे, Activity के onCreate() कॉलबैक में.
OrientationEventListener के onOrientationChanged() का इस्तेमाल करें. कॉलबैक में, झलक के अलावा इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.
ओरिएंटेशन के कॉन्फ़िगरेशन में बदलाव किए गए इस्तेमाल के उदाहरणों को सिर्फ़ एक बार सेट अप करें, जब Activity पहली बार बनाया जाता है. जैसे, Activity के onCreate() कॉलबैक में.
OrientationEventListener के onOrientationChanged() का इस्तेमाल करें. कॉलबैक में, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.
ज़रूरी नहीं: AndroidManifest फ़ाइल में, गतिविधि की screenOrientation प्रॉपर्टी को fullSensor पर सेट करें. डिवाइस के रिवर्स पोर्ट्रेट मोड में होने पर, यूज़र इंटरफ़ेस (यूआई) को ऊपर की ओर दिखाने की सुविधा देता है. जिन डिवाइसों पर डिफ़ॉल्ट रूप से रिवर्स पोर्ट्रेट मोड चालू नहीं होता उन पर इसका कोई असर नहीं पड़ता. डिसप्ले के रिवर्स पोर्ट्रेट ओरिएंटेशन में, मल्टी-विंडो मोड काम नहीं करता.

सिर्फ़ डिवाइस पर काम करने वाले ओरिएंटेशन के साथ काम करता है

सिर्फ़ उन ओरिएंटेशन के साथ काम करें जिन पर डिवाइस डिफ़ॉल्ट रूप से काम करता है. इसमें रिवर्स पोर्ट्रेट/रिवर्स लैंडस्केप शामिल हो सकता है या नहीं.

स्थिति दिशा-निर्देश मल्टी-विंडो स्प्लिट-स्क्रीन मोड
अनलॉक किए गए डिवाइस का ओरिएंटेशन हर बार Activity बनाने पर, इस्तेमाल के उदाहरण सेट अप करें. जैसे, Activity के onCreate() कॉलबैक में.
DisplayListener के onDisplayChanged() का इस्तेमाल करें. कॉलबैक में, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. जैसे, जब डिवाइस को 180 डिग्री घुमाया जाता है. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.
लॉक किया गया ओरिएंटेशन इस्तेमाल के उदाहरणों को सिर्फ़ एक बार सेट अप करें, जब Activity पहली बार बनाया जाता है. जैसे, Activity के onCreate() कॉलबैक में.
OrientationEventListener के onOrientationChanged() का इस्तेमाल करें. कॉलबैक में, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.
ओरिएंटेशन के कॉन्फ़िगरेशन में बदलाव किए गए इस्तेमाल के उदाहरणों को सिर्फ़ एक बार सेट अप करें, जब Activity पहली बार बनाया जाता है. जैसे, Activity के onCreate() कॉलबैक में.
DisplayListener के onDisplayChanged() का इस्तेमाल करें. कॉलबैक में, इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट करें. जैसे, जब डिवाइस को 180 डिग्री घुमाया जाता है. यह उन मामलों को भी मैनेज करता है जहां डिवाइस के घूमने पर (उदाहरण के लिए, 90 डिग्री) Activity फिर से नहीं बनाया जाता. यह तब होता है, जब छोटे फ़ॉर्म फ़ैक्टर वाले डिवाइसों पर ऐप्लिकेशन, स्क्रीन का आधा हिस्सा घेरता है. साथ ही, बड़े डिवाइसों पर ऐप्लिकेशन, स्क्रीन का दो तिहाई हिस्सा घेरता है.

अनलॉक किया गया ओरिएंटेशन

Activity का ओरिएंटेशन अनलॉक तब होता है, जब उसका डिसप्ले ओरिएंटेशन (जैसे, पोर्ट्रेट या लैंडस्केप) डिवाइस के फ़िज़िकल ओरिएंटेशन से मेल खाता हो. हालांकि, रिवर्स पोर्ट्रेट/लैंडस्केप को छोड़कर, कुछ डिवाइसों पर डिफ़ॉल्ट रूप से यह सुविधा काम नहीं करती. डिवाइस को चारों ओर घुमाने के लिए, Activity की screenOrientation प्रॉपर्टी को fullSensor पर सेट करें.

मल्टी-विंडो मोड में, डिफ़ॉल्ट रूप से रिवर्स पोर्ट्रेट/लैंडस्केप मोड काम नहीं करता. भले ही, screenOrientation प्रॉपर्टी को fullSensor पर सेट किया गया हो.

<!-- The Activity has an unlocked orientation, but might not rotate to reverse
portrait/landscape in single-window mode if the device doesn't support it by
default. -->
<activity android:name=".UnlockedOrientationActivity" />

<!-- The Activity has an unlocked orientation, and will rotate to all four
orientations in single-window mode. -->
<activity
   android:name=".UnlockedOrientationActivity"
   android:screenOrientation="fullSensor" />

लॉक किया गया ओरिएंटेशन

जब डिसप्ले का ओरिएंटेशन (जैसे, पोर्ट्रेट या लैंडस्केप) एक जैसा रहता है, तो डिसप्ले का ओरिएंटेशन लॉक हो जाता है. भले ही, डिवाइस का ओरिएंटेशन कुछ भी हो. ऐसा करने के लिए, AndroidManifest.xml फ़ाइल में Activity के एलान में screenOrientation प्रॉपर्टी की जानकारी दें.

जब डिसप्ले का ओरिएंटेशन लॉक होता है, तो डिवाइस के घूमने पर सिस्टम, Activity को न तो मिटाता है और न ही फिर से बनाता है.

<!-- The Activity keeps a portrait orientation even as the device rotates. -->
<activity
   android:name=".LockedOrientationActivity"
   android:screenOrientation="portrait" />

ओरिएंटेशन के कॉन्फ़िगरेशन में किए गए बदलावों को बदल दिया गया

जब कोई Activity, ओरिएंटेशन कॉन्फ़िगरेशन में किए गए बदलावों को बदल देता है, तो डिवाइस के फ़िज़िकल ओरिएंटेशन में बदलाव होने पर, सिस्टम उसे नष्ट नहीं करता और न ही उसे फिर से बनाता है. हालांकि, डिवाइस के फ़िज़िकल ओरिएंटेशन के हिसाब से, सिस्टम यूज़र इंटरफ़ेस (यूआई) को अपडेट करता है.

<!-- The Activity's UI might not rotate in reverse portrait/landscape if the
device doesn't support it by default. -->
<activity
   android:name=".OrientationConfigChangesOverriddenActivity"
   android:configChanges="orientation|screenSize" />

<!-- The Activity's UI will rotate to all 4 orientations in single-window
mode. -->
<activity
   android:name=".OrientationConfigChangesOverriddenActivity"
   android:configChanges="orientation|screenSize"
   android:screenOrientation="fullSensor" />

कैमरे के इस्तेमाल के उदाहरणों को सेट अप करना

ऊपर बताए गए उदाहरणों में, कैमरे के इस्तेमाल के उदाहरणों को पहली बार Activity बनाते समय सेट अप किया जा सकता है.

अगर Activity का ओरिएंटेशन अनलॉक है, तो डिवाइस को हर बार घुमाने पर यह सेटअप किया जाता है. ऐसा इसलिए होता है, क्योंकि ओरिएंटेशन में बदलाव होने पर सिस्टम, Activity को मिटा देता है और फिर से बना देता है. इस वजह से, इस्तेमाल के उदाहरण हर बार डिफ़ॉल्ट रूप से डिसप्ले के ओरिएंटेशन से मैच करने के लिए, अपने टारगेट रोटेशन को सेट करते हैं.

अगर Activity का ओरिएंटेशन लॉक है या ओरिएंटेशन कॉन्फ़िगरेशन में किए गए बदलावों को बदल देता है, तो यह सेटअप एक बार किया जाता है. ऐसा तब होता है, जब Activity पहली बार बनाया जाता है.

class CameraActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)

       val cameraProcessFuture = ProcessCameraProvider.getInstance(this)
       cameraProcessFuture.addListener(Runnable {
          val cameraProvider = cameraProcessFuture.get()

          // By default, the use cases set their target rotation to match the
          // display’s rotation.
          val preview = buildPreview()
          val imageAnalysis = buildImageAnalysis()
          val imageCapture = buildImageCapture()

          cameraProvider.bindToLifecycle(
              this, cameraSelector, preview, imageAnalysis, imageCapture)
       }, mainExecutor)
   }
}

OrientationEventListener सेटअप करना

OrientationEventListener का इस्तेमाल करके, डिवाइस के ओरिएंटेशन में बदलाव होने पर, कैमरे के इस्तेमाल के उदाहरणों के टारगेट रोटेशन को लगातार अपडेट किया जा सकता है.

class CameraActivity : AppCompatActivity() {

    private val orientationEventListener by lazy {
        object : OrientationEventListener(this) {
            override fun onOrientationChanged(orientation: Int) {
                if (orientation == ORIENTATION_UNKNOWN) {
                    return
                }

                val rotation = when (orientation) {
                     in 45 until 135 -> Surface.ROTATION_270
                     in 135 until 225 -> Surface.ROTATION_180
                     in 225 until 315 -> Surface.ROTATION_90
                     else -> Surface.ROTATION_0
                 }

                 imageAnalysis.targetRotation = rotation
                 imageCapture.targetRotation = rotation
            }
        }
    }

    override fun onStart() {
        super.onStart()
        orientationEventListener.enable()
    }

    override fun onStop() {
        super.onStop()
        orientationEventListener.disable()
    }
}

DisplayListener सेटअप करना

DisplayListener का इस्तेमाल करके, कुछ मामलों में कैमरे के इस्तेमाल के उदाहरणों के टारगेट रोटेशन को अपडेट किया जा सकता है. उदाहरण के लिए, जब डिवाइस 180 डिग्री घूमने के बाद, सिस्टम Activity को नष्ट न करे और नया Activity न बनाए.

class CameraActivity : AppCompatActivity() {

    private val displayListener = object : DisplayManager.DisplayListener {
        override fun onDisplayChanged(displayId: Int) {
            if (rootView.display.displayId == displayId) {
                val rotation = rootView.display.rotation
                imageAnalysis.targetRotation = rotation
                imageCapture.targetRotation = rotation
            }
        }

        override fun onDisplayAdded(displayId: Int) {
        }

        override fun onDisplayRemoved(displayId: Int) {
        }
    }

    override fun onStart() {
        super.onStart()
        val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
        displayManager.registerDisplayListener(displayListener, null)
    }

    override fun onStop() {
        super.onStop()
        val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
        displayManager.unregisterDisplayListener(displayListener)
    }
}