Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iss 22846 add runtime permission flow on android #1407

Merged
merged 5 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,23 @@ class HMSManager(
}
// endregion

@ReactMethod
fun setPermissionsAccepted(
data: ReadableMap,
promise: Promise?,
) {
val rnSDK =
HMSHelper.getHms(data, hmsCollection) ?: run {
promise?.reject(
"6004",
"RN HMS SDK not initialized",
)
return
}
rnSDK.hmsSDK?.setPermissionsAccepted()
promise?.resolve(null)
}

// region Warning on JS side
@ReactMethod
fun addListener(eventName: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ class HMSRNSDK(
}
}

if (data?.hasKey("haltPreviewJoinForPermissionsRequest") == true) {
val halt = data?.getBoolean("haltPreviewJoinForPermissionsRequest")
if (halt != null) {
builder.haltPreviewJoinForPermissionsRequest(halt)
}
}

this.hmsSDK = builder.build()

hmsSDK?.let {
Expand Down Expand Up @@ -286,6 +293,17 @@ class HMSRNSDK(
data.putArray("removedPeers", removedPeersArray)
delegate.emitEvent("ON_PEER_LIST_UPDATED", data)
}

override fun onPermissionsRequested(permissions: List<String>) {
if (eventsEnableStatus["ON_PERMISSIONS_REQUESTED"] != true) {
return
}
val data: WritableMap = Arguments.createMap()

data.putArray("permissions", Arguments.fromList(permissions))
data.putString("id", id)
delegate.emitEvent("ON_PERMISSIONS_REQUESTED", data)
}
},
)
} else {
Expand Down Expand Up @@ -557,6 +575,17 @@ class HMSRNSDK(
data.putString("id", id)
delegate.emitEvent("ON_TRANSCRIPTS", data)
}

override fun onPermissionsRequested(permissions: List<String>) {
if (eventsEnableStatus["ON_PERMISSIONS_REQUESTED"] != true) {
return
}
val data: WritableMap = Arguments.createMap()

data.putArray("permissions", Arguments.fromList(permissions))
data.putString("id", id)
delegate.emitEvent("ON_PERMISSIONS_REQUESTED", data)
}
},
)

Expand Down
63 changes: 63 additions & 0 deletions packages/react-native-hms/src/classes/HMSSDK.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { HMSRole } from './HMSRole';
import type { HMSTrack } from './HMSTrack';
import type { HMSLogger } from './HMSLogger';
import type { HMSPeer } from './HMSPeer';
import type { HMSVideoViewMode } from './HMSVideoViewMode';
import type { HMSTrackSettings } from './HMSTrackSettings';
import type { HMSRTMPConfig } from './HMSRTMPConfig';
import type { HMSHLSConfig } from './HMSHLSConfig';
Expand Down Expand Up @@ -74,6 +75,7 @@ export class HMSSDK {
private appStateSubscription?: any;
private onPreviewDelegate?: any;
private onJoinDelegate?: any;
private onPermissionsRequestedDelegate?: any;
private onRoomDelegate?: any;
private onTranscriptsDelegate?: any;
private onPeerDelegate?: any;
Expand Down Expand Up @@ -145,6 +147,7 @@ export class HMSSDK {
*/
static async build(params?: {
trackSettings?: HMSTrackSettings;
haltPreviewJoinForPermissionsRequest?: boolean;
appGroup?: String;
preferredExtension?: String;
logSettings?: HMSLogSettings;
Expand All @@ -154,6 +157,8 @@ export class HMSSDK {
const { major, minor, patch } = ReactNativeVersion.version;
let id = await HMSManager.build({
trackSettings: params?.trackSettings,
haltPreviewJoinForPermissionsRequest:
params?.haltPreviewJoinForPermissionsRequest, // required for Android Permissions, not required for iOS
appGroup: params?.appGroup, // required for iOS Screenshare, not required for Android
preferredExtension: params?.preferredExtension, // required for iOS Screenshare, not required for Android
frameworkInfo: {
Expand Down Expand Up @@ -1520,6 +1525,12 @@ export class HMSSDK {
return HMSManager.setAlwaysScreenOn({ id: this.id, enabled });
};

setPermissionsAccepted = async () => {
if (Platform.OS === 'ios') return;
logger?.verbose('#Function setPermissionsAccepted', { id: this.id });
return HMSManager.setPermissionsAccepted({ id: this.id });
};

/**
* - This is a prototype event listener that takes action and listens for updates related to that particular action
*
Expand Down Expand Up @@ -1568,6 +1579,28 @@ export class HMSSDK {
this.onJoinDelegate = callback;
break;
}
case HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED: {
// Checking if we already have ON_PERMISSIONS_REQUESTED subscription
if (
!this.emitterSubscriptions[
HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED
]
) {
// Adding ON_PERMISSIONS_REQUESTED native listener
const permissionsRequestedSubscription =
HMSNativeEventListener.addListener(
this.id,
HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED,
this.onPermissionsRequestedListener
);
this.emitterSubscriptions[
HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED
] = permissionsRequestedSubscription;
}
// Adding App Delegate listener
this.onPermissionsRequestedDelegate = callback;
break;
}
case HMSUpdateListenerActions.ON_ROOM_UPDATE: {
// Checking if we already have ON_ROOM_UPDATE subscription
if (
Expand Down Expand Up @@ -2031,6 +2064,23 @@ export class HMSSDK {
this.onJoinDelegate = null;
break;
}
case HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED: {
const subscription =
this.emitterSubscriptions[
HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED
];
// Removing ON_PERMISSIONS_REQUESTED native listener
if (subscription) {
subscription.remove();

this.emitterSubscriptions[
HMSUpdateListenerActions.ON_PERMISSIONS_REQUESTED
] = undefined;
}
// Removing App Delegate listener
this.onPermissionsRequestedDelegate = null;
break;
}
case HMSUpdateListenerActions.ON_ROOM_UPDATE: {
const subscription =
this.emitterSubscriptions[HMSUpdateListenerActions.ON_ROOM_UPDATE];
Expand Down Expand Up @@ -2431,6 +2481,19 @@ export class HMSSDK {
}
};

onPermissionsRequestedListener = (data: {
id: string;
permissions: Array<string>;
}) => {
if (data.id !== this.id) {
return;
}
if (this.onPermissionsRequestedDelegate) {
logger?.verbose('#Listener ON_PERMISSIONS_REQUESTED_LISTENER_CALL', data);
this.onPermissionsRequestedDelegate({ ...data });
}
};

onRoomListener = (data: any) => {
if (data.id !== this.id) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ export enum HMSUpdateListenerActions {
ON_SESSION_STORE_CHANGED = 'ON_SESSION_STORE_CHANGED',
ON_PEER_LIST_UPDATED = 'ON_PEER_LIST_UPDATED',
ON_TRANSCRIPTS = 'ON_TRANSCRIPTS',
ON_PERMISSIONS_REQUESTED = 'ON_PERMISSIONS_REQUESTED',
}
11 changes: 10 additions & 1 deletion packages/react-native-room-kit/example/ExampleAppChangelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Board: https://app.devrev.ai/100ms/vistas/vista-254

- Add runtime permission flow on Android
https://app.devrev.ai/100ms/works/ISS-22855

- Resolve app not running on Android 14 issue
https://app.devrev.ai/100ms/works/ISS-22860

- Resolve warning about React State update
https://app.devrev.ai/100ms/works/ISS-22807

Room Kit: 1.2.2
React Native SDK: 1.10.9
Android SDK: 2.9.63
Android SDK: 2.9.62
iOS SDK: 1.14.1
62 changes: 25 additions & 37 deletions packages/react-native-room-kit/example/src/utils/functions.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { Platform } from 'react-native';
import {Platform} from 'react-native';

Check failure on line 1 in packages/react-native-room-kit/example/src/utils/functions.ts

View workflow job for this annotation

GitHub Actions / Trunk Check

prettier

Incorrect formatting, autoformat by running 'trunk fmt'

import {
PERMISSIONS,
request,
requestMultiple,
RESULTS,
} from 'react-native-permissions';
import { getRoomLinkDetails } from './getRoomLinkDetails';
import {getRoomLinkDetails} from './getRoomLinkDetails';

export const getMeetingUrl = () =>
'https://reactnative.app.100ms.live/meeting/rlk-lsml-aiy';

export const callService = async (
roomID: string,
success: Function,
failure: Function
failure: Function,
) => {
let roomCode;
let subdomain;
try {
if (validateUrl(roomID)) {
const { roomCode: code, roomDomain: domain } = getRoomLinkDetails(roomID);
const {roomCode: code, roomDomain: domain} = getRoomLinkDetails(roomID);
roomCode = code;
subdomain = domain;

Expand All @@ -33,29 +33,17 @@
return;
}

const permissions = await checkPermissions([
PERMISSIONS.ANDROID.CAMERA,
PERMISSIONS.ANDROID.RECORD_AUDIO,
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
]);

if (permissions) {
const userId = getRandomUserId(6);
const isQARoom = subdomain && subdomain.search('.qa-') >= 0;
success(
roomCode,
userId,
isQARoom
? `https://auth-nonprod.100ms.live${Platform.OS === 'ios' ? '/' : ''}`
: undefined, // Auth Endpoint
isQARoom ? 'https://qa-init.100ms.live/init' : undefined, // HMSConfig Endpoint
isQARoom ? 'https://api-nonprod.100ms.live' : undefined // Room Layout endpoint
);
return;
} else {
failure('permission not granted');
return;
}
const userId = getRandomUserId(6);
const isQARoom = subdomain && subdomain.search('.qa-') >= 0;
success(
roomCode,
userId,
isQARoom
? `https://auth-nonprod.100ms.live${Platform.OS === 'ios' ? '/' : ''}`
: undefined, // Auth Endpoint
isQARoom ? 'https://qa-init.100ms.live/init' : undefined, // HMSConfig Endpoint
isQARoom ? 'https://api-nonprod.100ms.live' : undefined, // Room Layout endpoint
);
} catch (error) {
console.log(error);
failure('error in call service');
Expand All @@ -73,7 +61,7 @@
};

export const getRandomUserId = (length: number) => {
return Array.from({ length }, () => {
return Array.from({length}, () => {
const randomAlphaAsciiCode = getRandomNumberInRange(97, 123); // 97 - 122 is the ascii code range for a-z chars
const alphaCharacter = String.fromCharCode(randomAlphaAsciiCode);
return alphaCharacter;
Expand All @@ -89,7 +77,7 @@
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
'(\\?[;&a-z\\d%_.~+=-]*)?' +
'(\\#[-a-z\\d_]*)?$',
'i'
'i',
);
return pattern.test(url);
}
Expand All @@ -99,16 +87,16 @@
export const checkPermissions = async (
permissions: Array<
(typeof PERMISSIONS.ANDROID)[keyof typeof PERMISSIONS.ANDROID]
>
>,
): Promise<boolean> => {
if (Platform.OS === 'ios') {
return true;
}

try {
const requiredPermissions = permissions.filter(
(permission) =>
permission.toString() !== PERMISSIONS.ANDROID.BLUETOOTH_CONNECT
permission =>
permission.toString() !== PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
);

const results = await requestMultiple(requiredPermissions);
Expand All @@ -121,22 +109,22 @@
console.log(
requiredPermissions[permission],
':',
results[requiredPermissions[permission]]
results[requiredPermissions[permission]],
);
}

// Bluetooth Connect Permission handling
if (
permissions.findIndex(
(permission) =>
permission.toString() === PERMISSIONS.ANDROID.BLUETOOTH_CONNECT
permission =>
permission.toString() === PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
) >= 0
) {
const bleConnectResult = await request(
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
);
console.log(
`${PERMISSIONS.ANDROID.BLUETOOTH_CONNECT} : ${bleConnectResult}`
`${PERMISSIONS.ANDROID.BLUETOOTH_CONNECT} : ${bleConnectResult}`,
);
}

Expand Down
1 change: 1 addition & 0 deletions packages/react-native-room-kit/src/HMSInstanceSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ const getHmsInstance = async (
const hmsInstance = await HMSSDK.build({
logSettings,
trackSettings,
haltPreviewJoinForPermissionsRequest: true,
appGroup,
preferredExtension,
isPrebuilt: true,
Expand Down
Loading
Loading