diff --git a/android/src/main/java/com/orientationlocker/OrientationActivityLifecycle.kt b/android/src/main/java/com/orientationlocker/OrientationActivityLifecycle.kt index 15ee130..f697a9d 100644 --- a/android/src/main/java/com/orientationlocker/OrientationActivityLifecycle.kt +++ b/android/src/main/java/com/orientationlocker/OrientationActivityLifecycle.kt @@ -61,10 +61,11 @@ class OrientationActivityLifecycle : Application.ActivityLifecycleCallbacks { } } + companion object { const val TAG = "OrientationActivityLifecycle" val activeCount = AtomicInteger(0) - var instance: OrientationActivityLifecycle? = null - fun getInstance() = instance ?: OrientationActivityLifecycle() + private var instance: OrientationActivityLifecycle? = null + fun getInstance(): OrientationActivityLifecycle = instance ?: OrientationActivityLifecycle() } } diff --git a/android/src/main/java/com/orientationlocker/OrientationLockerModule.kt b/android/src/main/java/com/orientationlocker/OrientationLockerModule.kt index 9d9ac97..47e9de8 100644 --- a/android/src/main/java/com/orientationlocker/OrientationLockerModule.kt +++ b/android/src/main/java/com/orientationlocker/OrientationLockerModule.kt @@ -25,7 +25,6 @@ import com.facebook.react.bridge.WritableMap import com.facebook.react.common.ReactConstants import com.facebook.react.modules.core.DeviceEventManagerModule - class OrientationLockerModule internal constructor(context: ReactApplicationContext) : OrientationLockerSpec(context), OrientationListeners { @@ -40,95 +39,100 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont private var lastDeviceOrientationValue = "" init { - if (mOrientationListener?.canDetectOrientation() == true) { - FLog.d(ReactConstants.TAG, "orientation detect enabled."); - mOrientationListener!!.enable(); - } else { - FLog.d(ReactConstants.TAG, "orientation detect disabled."); - mOrientationListener!!.disable(); - } - - mReceiver = (object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - val orientationValue = getCurrentOrientation() - lastOrientationValue = orientationValue - FLog.d(ReactConstants.TAG, "Orientation changed to $orientationValue"); - - val params = Arguments.createMap() - params.putString(ORIENTATION_PARAM, orientationValue) + mReceiver = + (object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + val orientationValue = getCurrentOrientation() + lastOrientationValue = orientationValue + FLog.d(ReactConstants.TAG, "Orientation changed to $orientationValue") - sendEvent(reactContext, OrientationConstant.orientationDidChange, params) - } + val params = Arguments.createMap() + params.putString(ORIENTATION_PARAM, orientationValue) - }) - OrientationActivityLifecycle.instance!!.registerListeners(this) + sendEvent(reactContext, OrientationConstant.orientationDidChange, params) + } + }) + OrientationActivityLifecycle.getInstance().registerListeners(this) } - override fun getName(): String = NAME + @ReactMethod override fun getOrientation(callback: Callback) { val orientation = getCurrentOrientation() callback.invoke(orientation) } + @ReactMethod override fun getDeviceOrientation(callback: Callback) { - callback.invoke(lastDeviceOrientationValue); + callback.invoke(lastDeviceOrientationValue) } @ReactMethod override fun init() { + if (mOrientationListener != null) { + return + } Log.e("OrientationModule", "init()") - mOrientationListener = (object : OrientationEventListener(reactContext, SensorManager.SENSOR_DELAY_UI) { - override fun onOrientationChanged(orientation: Int) { - FLog.d(ReactConstants.TAG, "DeviceOrientation changed to $orientation"); - var deviceOrientationValue = lastDeviceOrientationValue - - if (orientation == -1) { - deviceOrientationValue = OrientationDisplay.UNKNOWN.type; - } else if (orientation > 355 || orientation < 5) { - deviceOrientationValue = OrientationDisplay.PORTRAIT.type; - } else if (orientation in 86..94) { - deviceOrientationValue = OrientationDisplay.LANDSCAPE_RIGHT.type; - } else if (orientation in 176..184) { - deviceOrientationValue = OrientationDisplay.PORTRAIT_UPSIDEDOWN.type - } else if (orientation in 266..274) { - deviceOrientationValue = OrientationDisplay.LANDSCAPE_LEFT.type - } - - if (lastDeviceOrientationValue != deviceOrientationValue) { - lastDeviceOrientationValue = deviceOrientationValue - val params = Arguments.createMap() - params.putString(DEVICE_ORIENTATION_PARAM, deviceOrientationValue) - sendEvent(reactContext, OrientationConstant.deviceOrientationDidChange, params) + mOrientationListener = + (object : OrientationEventListener(reactContext, SensorManager.SENSOR_DELAY_UI) { + override fun onOrientationChanged(orientation: Int) { + FLog.d(ReactConstants.TAG, "DeviceOrientation changed to $orientation") + var deviceOrientationValue = lastDeviceOrientationValue + + if (orientation == -1) { + deviceOrientationValue = OrientationDisplay.UNKNOWN.type + } else if (orientation > 355 || orientation < 5) { + deviceOrientationValue = OrientationDisplay.PORTRAIT.type + } else if (orientation in 86..94) { + deviceOrientationValue = OrientationDisplay.LANDSCAPE_RIGHT.type + } else if (orientation in 176..184) { + deviceOrientationValue = OrientationDisplay.PORTRAIT_UPSIDEDOWN.type + } else if (orientation in 266..274) { + deviceOrientationValue = OrientationDisplay.LANDSCAPE_LEFT.type + } + + if (lastDeviceOrientationValue != deviceOrientationValue) { + lastDeviceOrientationValue = deviceOrientationValue + val params = Arguments.createMap() + params.putString(DEVICE_ORIENTATION_PARAM, deviceOrientationValue) + sendEvent(reactContext, OrientationConstant.deviceOrientationDidChange, params) + } + + val currentOrientationDisplay = getCurrentOrientation() + if (lastDeviceOrientationValue != currentOrientationDisplay) { + lastOrientationValue = currentOrientationDisplay + FLog.d(ReactConstants.TAG, "Orientation changed to $currentOrientationDisplay") + val params = Arguments.createMap() + params.putString(ORIENTATION_PARAM, currentOrientationDisplay) + sendEvent(reactContext, OrientationConstant.orientationDidChange, params) + return + } } + }) - val currentOrientationDisplay = getCurrentOrientation() - if (lastDeviceOrientationValue != currentOrientationDisplay) { - lastOrientationValue = currentOrientationDisplay - FLog.d(ReactConstants.TAG, "Orientation changed to $currentOrientationDisplay"); - val params = Arguments.createMap() - params.putString(ORIENTATION_PARAM, currentOrientationDisplay) - sendEvent(reactContext, OrientationConstant.orientationDidChange, params) - return - } - } - }) - mOrientationListener!!.enable() + if (mOrientationListener?.canDetectOrientation() == true) { + Log.d(ReactConstants.TAG, "orientation detect enabled.") + mOrientationListener!!.enable() + } else { + Log.d(ReactConstants.TAG, "orientation detect disabled.") + mOrientationListener!!.disable() + } } @ReactMethod override fun removeInit() { if (mOrientationListener != null) { mOrientationListener!!.disable() - mOrientationListener = null // 释放资源 + mOrientationListener = null } } - + @SuppressLint("SourceLockedOrientationActivity") + @ReactMethod override fun lockToPortrait() { if (currentActivity != null) { - currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT isLocked = true lastOrientationValue = OrientationDisplay.PORTRAIT.type @@ -145,9 +149,11 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } + @SuppressLint("SourceLockedOrientationActivity") + @ReactMethod override fun lockToPortraitUpsideDown() { if (currentActivity != null) { - currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT isLocked = true lastOrientationValue = OrientationDisplay.PORTRAIT_UPSIDEDOWN.type @@ -164,9 +170,10 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } + @ReactMethod override fun lockToLandscape() { if (currentActivity != null) { - currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; + currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE isLocked = true lastOrientationValue = OrientationDisplay.LANDSCAPE_LEFT.type @@ -183,9 +190,10 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } + @ReactMethod override fun lockToLandscapeLeft() { if (currentActivity != null) { - currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE isLocked = true lastOrientationValue = OrientationDisplay.LANDSCAPE_LEFT.type @@ -202,9 +210,10 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } + @ReactMethod override fun lockToLandscapeRight() { if (currentActivity != null) { - currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; + currentActivity!!.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE isLocked = true lastOrientationValue = OrientationDisplay.LANDSCAPE_RIGHT.type @@ -221,6 +230,7 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } + @ReactMethod override fun unlockAllOrientations() { if (currentActivity != null) { currentActivity!!.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR) @@ -234,23 +244,25 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont val lockParams = Arguments.createMap() lockParams.putString(ORIENTATION_PARAM, OrientationDisplay.UNKNOWN.type) sendEvent(reactContext, OrientationConstant.lockDidChange, lockParams) - } } + @ReactMethod override fun configure(option: ReadableMap) { // IOS only, skip android } + @ReactMethod override fun lockToAllOrientationsButUpsideDown() { // IOS only, skip android } + @ReactMethod + override fun getAutoRotateState(callback: Callback) { val resolver: ContentResolver = reactContext.contentResolver - val rotateLock = Settings.System.getInt( - resolver, - Settings.System.ACCELEROMETER_ROTATION, 0) == 1 + val rotateLock = + Settings.System.getInt(resolver, Settings.System.ACCELEROMETER_ROTATION, 0) == 1 callback.invoke(rotateLock) } @@ -276,7 +288,7 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } override fun start() { - FLog.i(ReactConstants.TAG, "orientation detect enabled."); + FLog.i(ReactConstants.TAG, "orientation detect enabled.") mOrientationListener?.enable() mReceiver?.let { compatRegisterReceiver(reactContext, it, IntentFilter("onConfigurationChanged"), false) @@ -285,7 +297,7 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } override fun stop() { - FLog.d(ReactConstants.TAG, "orientation detect disabled."); + FLog.d(ReactConstants.TAG, "orientation detect disabled.") mOrientationListener?.disable() try { if (isConfigurationChangeReceiverRegistered) { @@ -298,7 +310,7 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } override fun release() { - FLog.d(ReactConstants.TAG, "orientation detect disabled."); + FLog.d(ReactConstants.TAG, "orientation detect disabled.") mOrientationListener?.disable() if (currentActivity != null) { try { @@ -312,34 +324,40 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } } - // ======== Private Method ======== \\ - private fun sendEvent(reactContext: ReactContext, - eventName: String, - params: WritableMap?) { + private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) { reactContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(eventName, params) } @SuppressLint("UnspecifiedRegisterReceiverFlag") - private fun compatRegisterReceiver(context: Context, receiver: BroadcastReceiver, filter: IntentFilter, exported: Boolean) { + private fun compatRegisterReceiver( + context: Context, + receiver: BroadcastReceiver, + filter: IntentFilter, + exported: Boolean + ) { if (Build.VERSION.SDK_INT >= 34 && context.applicationInfo.targetSdkVersion >= 34) { context.registerReceiver( - receiver, filter, if (exported) Context.RECEIVER_EXPORTED else Context.RECEIVER_NOT_EXPORTED) + receiver, + filter, + if (exported) Context.RECEIVER_EXPORTED else Context.RECEIVER_NOT_EXPORTED + ) } else { context.registerReceiver(receiver, filter) } } private fun getCurrentOrientation(): String { - val display: Display = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { - reactApplicationContext.currentActivity!!.display as Display - } else { - @Suppress("Deprecated") - reactApplicationContext.currentActivity!!.windowManager.defaultDisplay - } + val display: Display = + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { + reactApplicationContext.currentActivity!!.display as Display + } else { + @Suppress("Deprecated") + reactApplicationContext.currentActivity!!.windowManager.defaultDisplay + } return when (display.rotation) { Surface.ROTATION_0 -> OrientationDisplay.PORTRAIT.type @@ -351,9 +369,8 @@ class OrientationLockerModule internal constructor(context: ReactApplicationCont } companion object { + const val NAME = "OrientationLocker" const val ORIENTATION_PARAM = "orientation" const val DEVICE_ORIENTATION_PARAM = "deviceOrientation" - const val NAME = "OrientationLocker" } - } diff --git a/example/src/App.tsx b/example/src/App.tsx index 99a6569..5d5a88f 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,28 +1,126 @@ import * as React from 'react'; -import { StyleSheet, View, Text } from 'react-native'; +import { + Button, + SafeAreaView, + ScrollView, + StyleSheet, + View, +} from 'react-native'; +import Orientation, { + useDeviceOrientationChange, + useLockListener, + useOrientationChange, +} from 'react-native-orientation-locker'; export default function App() { - const [result, _] = React.useState(); + const defaultCallback = (orientation: string) => { + console.log({ orientation }); + }; - React.useEffect(() => {}, []); + const getOrientation = () => { + Orientation.getOrientation(defaultCallback); + }; + + const getDeviceOrientation = () => { + Orientation.getDeviceOrientation(defaultCallback); + }; + + const lockToPortrait = () => { + Orientation.lockToPortrait(); + }; + + const lockToPortraitUpsideDown = () => { + Orientation.lockToPortraitUpsideDown(); + }; + + const lockToLandscape = () => { + Orientation.lockToLandscape(); + }; + + const lockToLandscapeLeft = () => { + Orientation.lockToLandscapeLeft(); + }; + + const lockToLandscapeRight = () => { + Orientation.lockToLandscapeRight(); + }; + + const unlockAllOrientations = () => { + Orientation.unlockAllOrientations(); + }; + + const lockToAllOrientationsButUpsideDown = () => { + Orientation.lockToAllOrientationsButUpsideDown(); + }; + + const getAutoRotateState = () => { + Orientation.getAutoRotateState((state) => { + console.log('getAutoRotateState', state); + }); + }; + + useDeviceOrientationChange((e) => { + console.log('useDeviceOrientationChange', e); + }); + useLockListener((e) => { + console.log('useLockListener', e); + }); + useOrientationChange((e) => { + console.log('useOrientationChange', e); + }); + + React.useEffect(() => { + Orientation.init(); + Orientation.configure({ disableFaceUpDown: false }); + return () => Orientation.removeInit(); + }, []); return ( - - Result: {result} - + + + + +