[RN] Use proximity sensor when in audio-only mode
When the audio-only mode is enabled, turn on the proximity sensor to dim the screen and disable touch controls when there is an object nearby.
This commit is contained in:
parent
37157dc9e2
commit
13e3375e8a
|
@ -11,6 +11,7 @@
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera" />
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus"/>
|
<uses-feature android:name="android.hardware.camera.autofocus"/>
|
||||||
|
|
|
@ -32,7 +32,8 @@ public class MainApplication extends Application implements ReactApplication {
|
||||||
new com.ocetnik.timer.BackgroundTimerPackage(),
|
new com.ocetnik.timer.BackgroundTimerPackage(),
|
||||||
new com.oney.WebRTCModule.WebRTCModulePackage(),
|
new com.oney.WebRTCModule.WebRTCModulePackage(),
|
||||||
new com.rnimmersive.RNImmersivePackage(),
|
new com.rnimmersive.RNImmersivePackage(),
|
||||||
new org.jitsi.meet.audiomode.AudioModePackage()
|
new org.jitsi.meet.audiomode.AudioModePackage(),
|
||||||
|
new org.jitsi.meet.proximity.ProximityPackage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.jitsi.meet.proximity;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.os.PowerManager.WakeLock;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.UiThreadUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module implementing a simple API to enable a proximity sensor-controlled
|
||||||
|
* wake lock. When the lock is held, if the proximity sensor detects a nearby
|
||||||
|
* object it will dim the screen and disable touch controls. The functionality
|
||||||
|
* is used with the conference audio-only mode.
|
||||||
|
*/
|
||||||
|
public class ProximityModule extends ReactContextBaseJavaModule {
|
||||||
|
/**
|
||||||
|
* React Native module name.
|
||||||
|
*/
|
||||||
|
private static final String MODULE_NAME = "Proximity";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This type of wake lock (the one activated by the proximity sensor) has
|
||||||
|
* been available for a while, but the constant was only exported in API
|
||||||
|
* level 21 (Android Marshmallow) so make no assumptions and use its value
|
||||||
|
* directly.
|
||||||
|
*
|
||||||
|
* TODO: Remove when we bump the API level to 21.
|
||||||
|
*/
|
||||||
|
private static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link WakeLock} instance.
|
||||||
|
*/
|
||||||
|
private final WakeLock wakeLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new module instance. There shall be a single instance of
|
||||||
|
* this module throughout the lifetime of the application.
|
||||||
|
*
|
||||||
|
* @param reactContext The {@link ReactApplicationContext} where this module
|
||||||
|
* is created.
|
||||||
|
*/
|
||||||
|
public ProximityModule(ReactApplicationContext reactContext) {
|
||||||
|
super(reactContext);
|
||||||
|
|
||||||
|
WakeLock wakeLock;
|
||||||
|
PowerManager powerManager
|
||||||
|
= (PowerManager)
|
||||||
|
reactContext.getSystemService(Context.POWER_SERVICE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
wakeLock
|
||||||
|
= powerManager.newWakeLock(
|
||||||
|
PROXIMITY_SCREEN_OFF_WAKE_LOCK,
|
||||||
|
MODULE_NAME);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
wakeLock = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wakeLock = wakeLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this module to be used in the React Native bridge.
|
||||||
|
*
|
||||||
|
* @return The name of this module to be used in the React Native bridge.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MODULE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquires / releases the proximity sensor wake lock.
|
||||||
|
*
|
||||||
|
* @param enabled {@code true} to enable the proximity sensor; otherwise,
|
||||||
|
* {@code false}.
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void setEnabled(final boolean enabled) {
|
||||||
|
if (wakeLock == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (enabled) {
|
||||||
|
if (!wakeLock.isHeld()) {
|
||||||
|
wakeLock.acquire();
|
||||||
|
}
|
||||||
|
} else if (wakeLock.isHeld()) {
|
||||||
|
wakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.jitsi.meet.proximity;
|
||||||
|
|
||||||
|
import com.facebook.react.ReactPackage;
|
||||||
|
import com.facebook.react.bridge.JavaScriptModule;
|
||||||
|
import com.facebook.react.bridge.NativeModule;
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.uimanager.ViewManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements {@link ReactPackage} for {@link ProximityModule}.
|
||||||
|
*/
|
||||||
|
public class ProximityPackage implements ReactPackage {
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @return List of native modules to be exposed by React Native.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<NativeModule> createNativeModules(
|
||||||
|
ReactApplicationContext reactContext) {
|
||||||
|
List<NativeModule> modules = new ArrayList<>();
|
||||||
|
|
||||||
|
modules.add(new ProximityModule(reactContext));
|
||||||
|
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<ViewManager> createViewManagers(
|
||||||
|
ReactApplicationContext reactContext) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#import "RCTBridgeModule.h"
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface Proximity : NSObject<RCTBridgeModule>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation Proximity
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables / disables the proximity sensor monitoring. On iOS enabling the
|
||||||
|
* proximity sensor automatically dims the screen and disables touch controls,
|
||||||
|
* so there is nothing else to do (unlike on Android)!
|
||||||
|
*
|
||||||
|
* @param enabled {@code YES} to enable proximity (sensor) monitoring;
|
||||||
|
* {@code NO}, otherwise.
|
||||||
|
*/
|
||||||
|
RCT_EXPORT_METHOD(setEnabled:(BOOL)enabled) {
|
||||||
|
[[UIDevice currentDevice] setProximityMonitoringEnabled:enabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -14,6 +14,7 @@
|
||||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||||
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B42DFAD1E2FD90700111B12 /* AudioMode.m */; };
|
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B42DFAD1E2FD90700111B12 /* AudioMode.m */; };
|
||||||
|
0B96CAF11E8CF0E8005F348C /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B96CAF01E8CF0E8005F348C /* Proximity.m */; };
|
||||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
||||||
|
@ -273,6 +274,7 @@
|
||||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
||||||
0965153BB98645B4A8B6AA10 /* RNBackgroundTimer.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNBackgroundTimer.xcodeproj; path = "../node_modules/react-native-background-timer/ios/RNBackgroundTimer.xcodeproj"; sourceTree = "<group>"; };
|
0965153BB98645B4A8B6AA10 /* RNBackgroundTimer.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNBackgroundTimer.xcodeproj; path = "../node_modules/react-native-background-timer/ios/RNBackgroundTimer.xcodeproj"; sourceTree = "<group>"; };
|
||||||
0B42DFAD1E2FD90700111B12 /* AudioMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AudioMode.m; path = app/AudioMode.m; sourceTree = "<group>"; };
|
0B42DFAD1E2FD90700111B12 /* AudioMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AudioMode.m; path = app/AudioMode.m; sourceTree = "<group>"; };
|
||||||
|
0B96CAF01E8CF0E8005F348C /* Proximity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Proximity.m; path = app/Proximity.m; sourceTree = "<group>"; };
|
||||||
0EA8C046B2BF46279796F07D /* libKCKeepAwake.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libKCKeepAwake.a; sourceTree = "<group>"; };
|
0EA8C046B2BF46279796F07D /* libKCKeepAwake.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libKCKeepAwake.a; sourceTree = "<group>"; };
|
||||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
||||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
||||||
|
@ -426,6 +428,7 @@
|
||||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
||||||
13B07FB71A68108700A75B9A /* main.m */,
|
13B07FB71A68108700A75B9A /* main.m */,
|
||||||
B3A9D0241E0481E10009343D /* POSIX.m */,
|
B3A9D0241E0481E10009343D /* POSIX.m */,
|
||||||
|
0B96CAF01E8CF0E8005F348C /* Proximity.m */,
|
||||||
);
|
);
|
||||||
name = app;
|
name = app;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -945,6 +948,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
B3A9D0251E0481E10009343D /* POSIX.m in Sources */,
|
B3A9D0251E0481E10009343D /* POSIX.m in Sources */,
|
||||||
|
0B96CAF11E8CF0E8005F348C /* Proximity.m in Sources */,
|
||||||
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */,
|
0B42DFAE1E2FD90700111B12 /* AudioMode.m in Sources */,
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Platform } from '../../base/react';
|
||||||
import '../../mobile/audio-mode';
|
import '../../mobile/audio-mode';
|
||||||
import '../../mobile/background';
|
import '../../mobile/background';
|
||||||
import '../../mobile/full-screen';
|
import '../../mobile/full-screen';
|
||||||
|
import '../../mobile/proximity';
|
||||||
import '../../mobile/wake-lock';
|
import '../../mobile/wake-lock';
|
||||||
|
|
||||||
import { AbstractApp } from './AbstractApp';
|
import { AbstractApp } from './AbstractApp';
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
import './middleware';
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { NativeModules } from 'react-native';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CONFERENCE_FAILED,
|
||||||
|
CONFERENCE_JOINED,
|
||||||
|
CONFERENCE_LEFT,
|
||||||
|
SET_AUDIO_ONLY
|
||||||
|
} from '../../base/conference';
|
||||||
|
import { MiddlewareRegistry } from '../../base/redux';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware which enables / disables the proximity sensor in accord with
|
||||||
|
* conference-related actions. If the proximity sensor is enabled, it will dim
|
||||||
|
* the screen and disable touch controls when an object is nearby. The
|
||||||
|
* functionality is enabled when a conference is in audio-only mode.
|
||||||
|
*
|
||||||
|
* @param {Store} store - Redux store.
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
MiddlewareRegistry.register(store => next => action => {
|
||||||
|
switch (action.type) {
|
||||||
|
case CONFERENCE_JOINED: {
|
||||||
|
const { audioOnly } = store.getState()['features/base/conference'];
|
||||||
|
|
||||||
|
_setProximityEnabled(audioOnly);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CONFERENCE_FAILED:
|
||||||
|
case CONFERENCE_LEFT:
|
||||||
|
_setProximityEnabled(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SET_AUDIO_ONLY:
|
||||||
|
_setProximityEnabled(action.audioOnly);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(action);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables / disables the proximity sensor. If the proximity sensor is enabled,
|
||||||
|
* it will dim the screen and disable touch controls when an object is nearby.
|
||||||
|
*
|
||||||
|
* @param {boolean} enabled - True to enable the proximity sensor or false to
|
||||||
|
* disable it.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _setProximityEnabled(enabled) {
|
||||||
|
NativeModules.Proximity.setEnabled(Boolean(enabled));
|
||||||
|
}
|
Loading…
Reference in New Issue