Skip to content

Commit fa9deb0

Browse files
committed
Merge branch 'feat-sreen-orientation-with-accelerometer-data'
2 parents 02fbe29 + 83f6380 commit fa9deb0

File tree

7 files changed

+392
-67
lines changed

7 files changed

+392
-67
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ npx cap sync
3333
* [`setQuality(...)`](#setquality)
3434
* [`addListener('captureVideoFinished', ...)`](#addlistenercapturevideofinished)
3535
* [`addListener('capturePhotoFinished', ...)`](#addlistenercapturephotofinished)
36+
* [`addListener('accelerometerOrientation', ...)`](#addlisteneraccelerometerorientation)
37+
* [`removeAllListeners()`](#removealllisteners)
3638
* [Interfaces](#interfaces)
39+
* [Type Aliases](#type-aliases)
3740

3841
</docgen-index>
3942

@@ -266,6 +269,31 @@ addListener(eventName: 'capturePhotoFinished', listenerFunc: (data: CaptureResul
266269
--------------------
267270

268271

272+
### addListener('accelerometerOrientation', ...)
273+
274+
```typescript
275+
addListener(eventName: 'accelerometerOrientation', listenerFunc: (data: { orientation: CustomOrientation; }) => void) => Promise<PluginListenerHandle> & PluginListenerHandle
276+
```
277+
278+
| Param | Type |
279+
| ------------------ | ---------------------------------------------------------------------------------------------------- |
280+
| **`eventName`** | <code>'accelerometerOrientation'</code> |
281+
| **`listenerFunc`** | <code>(data: { orientation: <a href="#customorientation">CustomOrientation</a>; }) =&gt; void</code> |
282+
283+
**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt; & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
284+
285+
--------------------
286+
287+
288+
### removeAllListeners()
289+
290+
```typescript
291+
removeAllListeners() => Promise<void>
292+
```
293+
294+
--------------------
295+
296+
269297
### Interfaces
270298

271299

@@ -283,4 +311,12 @@ addListener(eventName: 'capturePhotoFinished', listenerFunc: (data: CaptureResul
283311
| **`filePath`** | <code>string</code> | File path for photo or video taken by camera. Example: file://your-app-dir/.../my-video.mp4 |
284312
| **`errorMessage`** | <code>string</code> | Error message if any |
285313

314+
315+
### Type Aliases
316+
317+
318+
#### CustomOrientation
319+
320+
<code>'portraitUp' | 'portraitDown' | 'landscapeRight' | 'landscaperLeft'</code>
321+
286322
</docgen-api>

android/src/main/java/io/numbersprotocol/capturelite/plugins/previewcamera/PreviewCamera.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import android.hardware.camera2.CameraManager
99
import android.hardware.camera2.CameraMetadata
1010
import android.util.DisplayMetrics
1111
import android.util.Log
12+
import android.view.Surface
1213
import android.view.View
1314
import android.view.ViewGroup
1415
import android.widget.FrameLayout
@@ -182,6 +183,23 @@ class PreviewCamera(private val bridge: Bridge) {
182183
}
183184
}
184185

186+
fun shouldRebuildCameraUseCases(newCustomOrientation: String) {
187+
if (previewCameraFragment?.recording != null) return;
188+
189+
bridge.activity.runOnUiThread {
190+
var orientation = Surface.ROTATION_0
191+
if (newCustomOrientation == "landscapeRight")
192+
orientation = Surface.ROTATION_90
193+
if (newCustomOrientation == "portraitDown")
194+
orientation = Surface.ROTATION_180
195+
if (newCustomOrientation == "landscapeLeft")
196+
orientation = Surface.ROTATION_270
197+
// previewCameraFragment?.bindCameraUseCases(orientation)
198+
Log.d("Custom Orientation", newCustomOrientation)
199+
previewCameraFragment?.customOrientation = orientation
200+
}
201+
}
202+
185203

186204
companion object {
187205

@@ -265,5 +283,8 @@ class PreviewCamera(private val bridge: Bridge) {
265283
return availableCameras
266284
}
267285
}
286+
}
268287

288+
fun Float.isBetween(a: Double, b: Double): Boolean {
289+
return a <= this && this <= b
269290
}

android/src/main/java/io/numbersprotocol/capturelite/plugins/previewcamera/PreviewCameraFragment.kt

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ const val ANIMATION_SLOW_MILLIS = 100L
5353
* create an instance of this fragment.
5454
*/
5555
class PreviewCameraFragment : Fragment() {
56+
var customOrientation = Surface.ROTATION_0
57+
5658
/** Android ViewBinding */
5759
private var _fragmentCameraBinding: FragmentPreviewCameraBinding? = null
5860
private val fragmentCameraBinding get() = _fragmentCameraBinding!!
5961

6062
private var videoCapture: VideoCapture<Recorder>? = null
61-
private var recording: Recording? = null
63+
var recording: Recording? = null
6264

6365
private lateinit var outputDirectory: File
6466
private lateinit var broadcastManager: LocalBroadcastManager
@@ -80,9 +82,9 @@ class PreviewCameraFragment : Fragment() {
8082
var flashMode = ImageCapture.FLASH_MODE_OFF
8183
var flashModeAvailable = true;
8284

83-
private val displayManager by lazy {
84-
requireContext().getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
85-
}
85+
// private val displayManager by lazy {
86+
// requireContext().getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
87+
// }
8688

8789
/** Blocking camera operations are performed using this executor */
8890
private lateinit var cameraExecutor: ExecutorService
@@ -142,7 +144,7 @@ class PreviewCameraFragment : Fragment() {
142144

143145
override fun onCreate(savedInstanceState: Bundle?) {
144146
super.onCreate(savedInstanceState)
145-
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
147+
// activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
146148

147149
arguments?.let {
148150
cameraId = it.getString(ARG_PARAM1)
@@ -178,7 +180,7 @@ class PreviewCameraFragment : Fragment() {
178180
// broadcastManager.registerReceiver(volumeDownReceiver, filter)
179181

180182
// Every time the orientation of device changes, update rotation for use cases
181-
displayManager.registerDisplayListener(displayListener, null)
183+
// displayManager.registerDisplayListener(displayListener, null)
182184

183185
//Initialize WindowManager to retrieve display metrics
184186
windowManager = WindowManager(view.context)
@@ -234,6 +236,14 @@ class PreviewCameraFragment : Fragment() {
234236
}
235237

236238
fun takePhoto(call: PluginCall, notifyListener: CapacitorNotifyListener) {
239+
if (customOrientation == Surface.ROTATION_0 || customOrientation == Surface.ROTATION_180) {
240+
imageCapture?.targetRotation = Surface.ROTATION_0
241+
} else if (customOrientation == Surface.ROTATION_270) {
242+
imageCapture?.targetRotation = Surface.ROTATION_90
243+
} else {
244+
imageCapture?.targetRotation = Surface.ROTATION_270
245+
}
246+
237247
imageCapture?.let { imageCapture ->
238248
// Setup image capture metadata
239249
val metadata = ImageCapture.Metadata().apply {
@@ -333,6 +343,16 @@ class PreviewCameraFragment : Fragment() {
333343

334344
// configure Recorder and Start recording to the mediaStoreOutput.
335345
try {
346+
Log.d("Custom Orientation", "capture with $customOrientation")
347+
348+
if(customOrientation == Surface.ROTATION_0 || customOrientation == Surface.ROTATION_180) {
349+
videoCapture?.targetRotation = Surface.ROTATION_0
350+
} else if (customOrientation == Surface.ROTATION_270) {
351+
videoCapture?.targetRotation = Surface.ROTATION_90
352+
} else {
353+
videoCapture?.targetRotation = Surface.ROTATION_270
354+
}
355+
336356
recording = videoCapture!!.output
337357
.prepareRecording(requireActivity(), fileOutputOptions)
338358
.apply {
@@ -477,17 +497,25 @@ class PreviewCameraFragment : Fragment() {
477497
}
478498

479499
/** Declare and bind preview, capture and analysis use cases */
480-
private fun bindCameraUseCases() {
500+
fun bindCameraUseCases(customScreenOrientation: Int = Surface.ROTATION_0) {
481501

482502
// Get screen metrics used to setup camera for full screen resolution
483503
val metrics = windowManager.getCurrentWindowMetrics().bounds
484504

485505
Log.d(TAG, "Screen metrics: ${metrics.width()} x ${metrics.height()}")
486506

487-
val screenAspectRatio = aspectRatio(metrics.width(), metrics.height())
507+
var screenWidth = min(metrics.width(), metrics.height())
508+
var screenHeight = max(metrics.width(), metrics.height())
509+
// if (customScreenOrientation == Surface.ROTATION_90 || customScreenOrientation == Surface.ROTATION_270) {
510+
// screenWidth = metrics.height()
511+
// screenHeight = metrics.width()
512+
// }
513+
514+
var screenAspectRatio = aspectRatio(screenWidth, screenHeight)
488515
Log.d(TAG, "Preview aspect ratio: $screenAspectRatio")
489516

490-
val rotation = fragmentCameraBinding.viewFinder.display.rotation
517+
// val rotation = fragmentCameraBinding.viewFinder.display.rotation
518+
val rotation = customScreenOrientation
491519

492520
// CameraProvider TODO: handle IllegalStateException for cameraProvider
493521
val cameraProvider = cameraProvider
@@ -496,20 +524,20 @@ class PreviewCameraFragment : Fragment() {
496524
// CameraSelector
497525
val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
498526

499-
var aspectRatio = aspectRatio(metrics.width(), metrics.height())
527+
// var aspectRatio = aspectRatio(screenWidth, screenHeight)
500528
if (this.captureQuality == "low") {
501-
aspectRatio = aspectRatio(1920, 1080)
502-
if (rotation % 2 == 0) {
503-
aspectRatio = aspectRatio(1080, 1920)
504-
}
529+
screenAspectRatio = aspectRatio(1080, 1920)
530+
// if (rotation % 2 == 0) {
531+
// screenAspectRatio = aspectRatio(1920, 1080)
532+
// }
505533
}
506534
// Preview
507535
preview = Preview.Builder()
508536
// We request aspect ratio but no resolution
509-
.setTargetAspectRatio(aspectRatio)
537+
.setTargetAspectRatio(screenAspectRatio)
510538
// .setTargetAspectRatio(aspectRatio)
511539
// Set initial target rotation
512-
.setTargetRotation(rotation)
540+
.setTargetRotation(Surface.ROTATION_0)
513541
.build()
514542
.also { it.setSurfaceProvider(fragmentCameraBinding.viewFinder.surfaceProvider) }
515543

@@ -526,10 +554,10 @@ class PreviewCameraFragment : Fragment() {
526554
// .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
527555
// We request aspect ratio but no resolution to match preview config, but letting
528556
// CameraX optimize for whatever specific resolution best fits our use cases
529-
.setTargetAspectRatio(aspectRatio)
557+
.setTargetAspectRatio(screenAspectRatio)
530558
// Set initial target rotation, we will have to call this again if rotation changes
531559
// during the lifecycle of this use case
532-
.setTargetRotation(rotation)
560+
.setTargetRotation(Surface.ROTATION_0)
533561
// .setCaptureMode(captureMode)
534562
.setJpegQuality(imageQuality)
535563
.setFlashMode(flashMode)
@@ -544,6 +572,8 @@ class PreviewCameraFragment : Fragment() {
544572
).build()
545573
videoCapture = VideoCapture.withOutput(recorder)
546574

575+
videoCapture!!.targetRotation = Surface.ROTATION_0
576+
547577
try {
548578
// Must unbind the use-cases before rebinding them
549579
cameraProvider.unbindAll()
@@ -743,7 +773,7 @@ class PreviewCameraFragment : Fragment() {
743773

744774
override fun onDestroy() {
745775

746-
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
776+
// activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
747777

748778
_fragmentCameraBinding = null
749779
super.onDestroy()
@@ -752,7 +782,7 @@ class PreviewCameraFragment : Fragment() {
752782

753783
// Unregister the broadcast receivers and listeners
754784
// broadcastManager.unregisterReceiver(volumeDownReceiver)
755-
displayManager.unregisterDisplayListener(displayListener)
785+
// displayManager.unregisterDisplayListener(displayListener)
756786
}
757787

758788
override fun onDestroyView() {

0 commit comments

Comments
 (0)