@capgo/capacitor-screen-orientation 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,277 @@
1
+ package ee.forgr.capacitor.screenorientation;
2
+
3
+ import android.content.Context;
4
+ import android.content.pm.ActivityInfo;
5
+ import android.content.res.Configuration;
6
+ import android.hardware.Sensor;
7
+ import android.hardware.SensorEvent;
8
+ import android.hardware.SensorEventListener;
9
+ import android.hardware.SensorManager;
10
+ import android.view.Surface;
11
+ import com.getcapacitor.JSObject;
12
+ import com.getcapacitor.Plugin;
13
+ import com.getcapacitor.PluginCall;
14
+ import com.getcapacitor.PluginMethod;
15
+ import com.getcapacitor.annotation.CapacitorPlugin;
16
+
17
+ @CapacitorPlugin(name = "CapacitorScreenOrientation")
18
+ public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEventListener {
19
+
20
+ private final String pluginVersion = "7.0.0";
21
+ private int currentOrientation;
22
+ private SensorManager sensorManager;
23
+ private Sensor accelerometer;
24
+ private boolean isTrackingMotion = false;
25
+ private String currentPhysicalOrientation = "portrait-primary";
26
+ private String lastNotifiedOrientation = null;
27
+
28
+ @Override
29
+ public void load() {
30
+ super.load();
31
+ currentOrientation = getActivity().getResources().getConfiguration().orientation;
32
+
33
+ // Initialize sensor manager
34
+ sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
35
+ if (sensorManager != null) {
36
+ accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
37
+ }
38
+ }
39
+
40
+ @Override
41
+ protected void handleOnDestroy() {
42
+ stopMotionTracking();
43
+ super.handleOnDestroy();
44
+ }
45
+
46
+ @Override
47
+ protected void handleOnConfigurationChanged(Configuration newConfig) {
48
+ super.handleOnConfigurationChanged(newConfig);
49
+
50
+ if (currentOrientation != newConfig.orientation) {
51
+ currentOrientation = newConfig.orientation;
52
+ notifyOrientationChange();
53
+ }
54
+ }
55
+
56
+ @PluginMethod
57
+ public void orientation(final PluginCall call) {
58
+ try {
59
+ final JSObject ret = new JSObject();
60
+ ret.put("type", getCurrentOrientationType());
61
+ call.resolve(ret);
62
+ } catch (final Exception e) {
63
+ call.reject("Could not get orientation", e);
64
+ }
65
+ }
66
+
67
+ @PluginMethod
68
+ public void lock(final PluginCall call) {
69
+ final String orientationString = call.getString("orientation");
70
+ final Boolean bypassLock = call.getBoolean("bypassOrientationLock", false);
71
+
72
+ if (orientationString == null) {
73
+ call.reject("Orientation parameter is required");
74
+ return;
75
+ }
76
+
77
+ try {
78
+ final int orientation = getOrientationConstant(orientationString);
79
+ getActivity().setRequestedOrientation(orientation);
80
+
81
+ // Start motion tracking if requested
82
+ if (bypassLock) {
83
+ startMotionTracking();
84
+ }
85
+
86
+ call.resolve();
87
+ } catch (final Exception e) {
88
+ call.reject("Could not lock orientation", e);
89
+ }
90
+ }
91
+
92
+ @PluginMethod
93
+ public void unlock(final PluginCall call) {
94
+ try {
95
+ stopMotionTracking();
96
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
97
+ call.resolve();
98
+ } catch (final Exception e) {
99
+ call.reject("Could not unlock orientation", e);
100
+ }
101
+ }
102
+
103
+ @PluginMethod
104
+ public void startOrientationTracking(final PluginCall call) {
105
+ final Boolean bypassLock = call.getBoolean("bypassOrientationLock", false);
106
+
107
+ if (bypassLock) {
108
+ startMotionTracking();
109
+ }
110
+
111
+ call.resolve();
112
+ }
113
+
114
+ @PluginMethod
115
+ public void stopOrientationTracking(final PluginCall call) {
116
+ stopMotionTracking();
117
+ call.resolve();
118
+ }
119
+
120
+ @PluginMethod
121
+ public void isOrientationLocked(final PluginCall call) {
122
+ try {
123
+ final String uiOrientation = getCurrentOrientationType();
124
+ final JSObject ret = new JSObject();
125
+
126
+ if (isTrackingMotion) {
127
+ // Compare physical orientation with UI orientation
128
+ final boolean locked = !currentPhysicalOrientation.equals(uiOrientation);
129
+ ret.put("locked", locked);
130
+ ret.put("physicalOrientation", currentPhysicalOrientation);
131
+ ret.put("uiOrientation", uiOrientation);
132
+ } else {
133
+ // No motion tracking active, can't determine if locked
134
+ ret.put("locked", false);
135
+ ret.put("uiOrientation", uiOrientation);
136
+ }
137
+
138
+ call.resolve(ret);
139
+ } catch (final Exception e) {
140
+ call.reject("Could not check orientation lock status", e);
141
+ }
142
+ }
143
+
144
+ @PluginMethod
145
+ public void getPluginVersion(final PluginCall call) {
146
+ try {
147
+ final JSObject ret = new JSObject();
148
+ ret.put("version", this.pluginVersion);
149
+ call.resolve(ret);
150
+ } catch (final Exception e) {
151
+ call.reject("Could not get plugin version", e);
152
+ }
153
+ }
154
+
155
+ private void notifyOrientationChange() {
156
+ final JSObject ret = new JSObject();
157
+ ret.put("type", getCurrentOrientationType());
158
+ notifyListeners("screenOrientationChange", ret);
159
+ }
160
+
161
+ private String getCurrentOrientationType() {
162
+ final int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
163
+ final int orientation = getActivity().getResources().getConfiguration().orientation;
164
+
165
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
166
+ return rotation == Surface.ROTATION_0 ? "portrait-primary" : "portrait-secondary";
167
+ } else {
168
+ return rotation == Surface.ROTATION_90 ? "landscape-primary" : "landscape-secondary";
169
+ }
170
+ }
171
+
172
+ private int getOrientationConstant(final String orientationString) {
173
+ switch (orientationString) {
174
+ case "any":
175
+ return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
176
+ case "natural":
177
+ return ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
178
+ case "landscape":
179
+ return ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
180
+ case "portrait":
181
+ return ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
182
+ case "portrait-primary":
183
+ return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
184
+ case "portrait-secondary":
185
+ return ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
186
+ case "landscape-primary":
187
+ return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
188
+ case "landscape-secondary":
189
+ return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
190
+ default:
191
+ return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
192
+ }
193
+ }
194
+
195
+ // Motion tracking methods
196
+ private void startMotionTracking() {
197
+ if (isTrackingMotion || accelerometer == null) {
198
+ return;
199
+ }
200
+
201
+ isTrackingMotion = true;
202
+ sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
203
+ android.util.Log.i("ScreenOrientation", "Started motion-based orientation tracking");
204
+ }
205
+
206
+ private void stopMotionTracking() {
207
+ if (!isTrackingMotion) {
208
+ return;
209
+ }
210
+
211
+ isTrackingMotion = false;
212
+ if (sensorManager != null) {
213
+ sensorManager.unregisterListener(this);
214
+ }
215
+ android.util.Log.i("ScreenOrientation", "Stopped motion-based orientation tracking");
216
+ }
217
+
218
+ @Override
219
+ public void onSensorChanged(SensorEvent event) {
220
+ if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
221
+ return;
222
+ }
223
+
224
+ float x = event.values[0];
225
+ float y = event.values[1];
226
+ float z = event.values[2];
227
+
228
+ // Determine orientation based on accelerometer values
229
+ String newOrientation = determinePhysicalOrientation(x, y, z);
230
+
231
+ if (!newOrientation.equals(currentPhysicalOrientation)) {
232
+ currentPhysicalOrientation = newOrientation;
233
+
234
+ // Notify listeners of physical orientation change
235
+ if (!newOrientation.equals(lastNotifiedOrientation)) {
236
+ lastNotifiedOrientation = newOrientation;
237
+ final JSObject ret = new JSObject();
238
+ ret.put("type", newOrientation);
239
+ notifyListeners("screenOrientationChange", ret);
240
+ }
241
+ }
242
+ }
243
+
244
+ @Override
245
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
246
+ // Not needed for orientation detection
247
+ }
248
+
249
+ private String determinePhysicalOrientation(float x, float y, float z) {
250
+ final float threshold = 5.0f;
251
+
252
+ // X axis: left/right tilt
253
+ // Y axis: forward/backward tilt
254
+ // Z axis: up/down (gravity when flat)
255
+
256
+ if (Math.abs(z) > 8) {
257
+ // Device is relatively flat, use x/y to determine orientation
258
+ if (Math.abs(x) > Math.abs(y)) {
259
+ // Landscape orientation
260
+ return x > 0 ? "landscape-secondary" : "landscape-primary";
261
+ } else {
262
+ // Portrait orientation
263
+ return y > 0 ? "portrait-secondary" : "portrait-primary";
264
+ }
265
+ } else {
266
+ // Device is tilted, use strongest axis
267
+ if (Math.abs(x) > threshold && Math.abs(x) > Math.abs(y)) {
268
+ return x > 0 ? "landscape-secondary" : "landscape-primary";
269
+ } else if (Math.abs(y) > threshold) {
270
+ return y > 0 ? "portrait-secondary" : "portrait-primary";
271
+ }
272
+ }
273
+
274
+ // Default to current if unclear
275
+ return currentPhysicalOrientation;
276
+ }
277
+ }