Compare commits

...

13 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
e89df8c346 chore(ios) sync Podfile.lock 2020-09-24 14:03:43 +02:00
Saúl Ibarra Corretgé
f4fe1a71a5 fix(ios) add local network usage description for iOS 14 2020-09-24 13:48:30 +02:00
Saúl Ibarra Corretgé
e237539197 chore(android,ios,version) bump 2020-09-24 13:45:50 +02:00
Saúl Ibarra Corretgé
c1ddd0cde7 fix(analytics) clarify log line 2020-09-24 13:42:53 +02:00
Saúl Ibarra Corretgé
b40a0ff82c fix(analytics) make handler loading more resilient
- Don't initialize handler's is their API key is not set
- Don't swallow exceptions when creating handlers
- Don't remove all handlers if an external one fails
- Dispose the analytics subsystem if no handlers are registered
2020-09-24 13:42:53 +02:00
Saúl Ibarra Corretgé
86b2425658 fix(analytics) make sure rtcstats is not enabled on mobile 2020-09-24 13:42:53 +02:00
Saúl Ibarra Corretgé
8c319dbf67 fix(analytics) avoid Amplitude initialization failure on mobile 2020-09-24 13:42:52 +02:00
Saúl Ibarra Corretgé
4e3da8e61f chore(ios,version) bump SDK 2020-09-18 11:40:39 +02:00
Saúl Ibarra Corretgé
8979352334 chore(ios) bump cocoapods version 2020-09-18 10:27:54 +02:00
Saúl Ibarra Corretgé
c0e1c277f9 chore(ios,version) bump SDK 2020-09-18 09:20:10 +02:00
Saúl Ibarra Corretgé
d895ccdeff chore(android,version) bump 2020-09-18 09:07:00 +02:00
Saúl Ibarra Corretgé
1594ae89db fix(android,calendar) avoid crash 2020-09-18 08:56:30 +02:00
Saúl Ibarra Corretgé
c4870c9159 android: fix crash when requesting permissions
The RN Permissions module calls this in a non-UI thread. What we observe is a
crash in ViewGroup.dispatchCancelPendingInputEvents, which is called on the
calling (ie, non-UI) thread. This doesn't look very safe, so try to avoid a
crash by pretending the permission was denied.
2020-09-18 08:54:02 +02:00
13 changed files with 95 additions and 49 deletions

View File

@@ -20,5 +20,5 @@
android.useAndroidX=true
android.enableJetifier=true
appVersion=20.4.0
appVersion=20.4.2
sdkVersion=2.10.0

View File

@@ -24,6 +24,8 @@ import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Helper class to encapsulate the work which needs to be done on
* {@link Activity} lifecycle methods in order for the React side to be aware of
@@ -177,6 +179,16 @@ public class JitsiMeetActivityDelegate {
public static void requestPermissions(Activity activity, String[] permissions, int requestCode, PermissionListener listener) {
permissionListener = listener;
activity.requestPermissions(permissions, requestCode);
// The RN Permissions module calls this in a non-UI thread. What we observe is a crash in ViewGroup.dispatchCancelPendingInputEvents,
// which is called on the calling (ie, non-UI) thread. This doesn't look very safe, so try to avoid a crash by pretending the permission
// was denied.
try {
activity.requestPermissions(permissions, requestCode);
} catch (Exception e) {
JitsiMeetLogger.e(e, "Error requesting permissions");
onRequestPermissionsResult(requestCode, permissions, new int[0]);
}
}
}

View File

@@ -530,9 +530,9 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
Crashlytics: 9220f5bc89e7a618df411b4f639389dbfb0e03d2
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
Fabric: ea977e3cd9c20425516d3dafd3bf8c941c51223f
FBLazyVector: 4a5251159a3ed05dc11cc8b74cf937869935814b
FBReactNativeSpec: 6fa602a20993212cc9877a81838578ffb0008bc9
Firebase: 497158b816d0a86fc31babbd05546fcd7e6083ff
@@ -591,4 +591,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 082858daebbe170e7a490de433e7f2a99e0c3701
COCOAPODS: 1.9.1
COCOAPODS: 1.9.3

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>20.4.0</string>
<string>20.4.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@@ -66,10 +66,10 @@
<string>See your scheduled meetings in the app.</string>
<key>NSCameraUsageDescription</key>
<string>Participate in meetings with video.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in meetings with voice.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network is used for establishing Peer-to-Peer connections.</string>
<key>NSUserActivityTypes</key>
<array>
<string>org.jitsi.JitsiMeet.ios.conference</string>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>20.4.0</string>
<string>20.4.2</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>UISupportedInterfaceOrientations</key>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>20.4.0</string>
<string>20.4.2</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CLKComplicationPrincipalClass</key>

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.10.0</string>
<string>2.10.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

4
package-lock.json generated
View File

@@ -14469,8 +14469,8 @@
"integrity": "sha512-cuXIIv+dcG8a8qkTD8pMzeqOEZCO+UGKglZWIe1osve+yJslmCowYQff+bI9xa7NOt2w+Vtd4L3d9JonlSqODg=="
},
"react-native-calendar-events": {
"version": "github:jitsi/react-native-calendar-events#928a80e2ffef0d7e84936d7e7e0acc4f53ee8470",
"from": "github:jitsi/react-native-calendar-events#928a80e2ffef0d7e84936d7e7e0acc4f53ee8470"
"version": "github:jitsi/react-native-calendar-events#df48ecdc4e1e90c5352f803ddbab1fa7269b74a7",
"from": "github:jitsi/react-native-calendar-events#df48ecdc4e1e90c5352f803ddbab1fa7269b74a7"
},
"react-native-callstats": {
"version": "3.61.0",

View File

@@ -69,7 +69,7 @@
"react-linkify": "1.0.0-alpha",
"react-native": "github:jitsi/react-native#efd2aff5661d75a230e36406b698cfe0ee545be2",
"react-native-background-timer": "2.1.1",
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#928a80e2ffef0d7e84936d7e7e0acc4f53ee8470",
"react-native-calendar-events": "github:jitsi/react-native-calendar-events#df48ecdc4e1e90c5352f803ddbab1fa7269b74a7",
"react-native-callstats": "3.61.0",
"react-native-collapsible": "1.5.1",
"react-native-default-preference": "1.4.2",

View File

@@ -57,12 +57,15 @@ export function resetAnalytics() {
* @param {Store} store - The redux store in which the specified {@code action} is being dispatched.
* @returns {Promise} Resolves with the handlers that have been successfully loaded.
*/
export function createHandlers({ getState }: { getState: Function }) {
export async function createHandlers({ getState }: { getState: Function }) {
getJitsiMeetGlobalNS().analyticsHandlers = [];
window.analyticsHandlers = []; // Legacy support.
if (!isAnalyticsEnabled(getState)) {
return Promise.resolve([]);
// Avoid all analytics processing if there are no handlers, since no event would be sent.
analytics.dispose();
return [];
}
const state = getState();
@@ -100,43 +103,47 @@ export function createHandlers({ getState }: { getState: Function }) {
};
const handlers = [];
try {
const amplitude = new AmplitudeHandler(handlerConstructorOptions);
if (amplitudeAPPKey) {
try {
const amplitude = new AmplitudeHandler(handlerConstructorOptions);
analytics.amplitudeIdentityProps = amplitude.getIdentityProps();
analytics.amplitudeIdentityProps = amplitude.getIdentityProps();
handlers.push(amplitude);
// eslint-disable-next-line no-empty
} catch (e) {}
handlers.push(amplitude);
} catch (e) {
logger.error('Failed to initialize Amplitude handler', e);
}
}
try {
const matomo = new MatomoHandler(handlerConstructorOptions);
if (matomoEndpoint && matomoSiteID) {
try {
const matomo = new MatomoHandler(handlerConstructorOptions);
handlers.push(matomo);
// eslint-disable-next-line no-empty
} catch (e) {}
handlers.push(matomo);
} catch (e) {
logger.error('Failed to initialize Matomo handler', e);
}
}
return (
_loadHandlers(scriptURLs, handlerConstructorOptions)
.then(externalHandlers => {
handlers.push(...externalHandlers);
if (handlers.length === 0) {
// Throwing an error in order to dispose the analytics in the catch clause due to the lack of any
// analytics handlers.
throw new Error('No analytics handlers created!');
}
if (Array.isArray(scriptURLs) && scriptURLs.length > 0) {
let externalHandlers;
return handlers;
})
.catch(e => {
analytics.dispose();
if (handlers.length !== 0) {
logger.error(e);
}
try {
externalHandlers = await _loadHandlers(scriptURLs, handlerConstructorOptions);
handlers.push(...externalHandlers);
} catch (e) {
logger.error('Failed to initialize external analytics handlers', e);
}
}
return [];
}));
// Avoid all analytics processing if there are no handlers, since no event would be sent.
if (handlers.length === 0) {
analytics.dispose();
}
logger.info(`Initialized ${handlers.length} analytics handlers`);
return handlers;
}
/**
@@ -228,7 +235,7 @@ function _inIframe() {
}
/**
* Tries to load the scripts for the analytics handlers and creates them.
* Tries to load the scripts for the external analytics handlers and creates them.
*
* @param {Array} scriptURLs - The array of script urls to load.
* @param {Object} handlerConstructorOptions - The default options to pass when creating handlers.
@@ -279,7 +286,7 @@ function _loadHandlers(scriptURLs = [], handlerConstructorOptions) {
logger.warn(`Error creating analytics handler: ${error}`);
}
}
logger.debug(`Loaded ${handlers.length} analytics handlers`);
logger.debug(`Loaded ${handlers.length} external analytics handlers`);
return handlers;
});

View File

@@ -72,6 +72,11 @@ export default class AmplitudeHandler extends AbstractHandler {
* @returns {Object}
*/
getIdentityProps() {
// TODO: Remove when web and native Aplitude implementations are unified.
if (navigator.product === 'ReactNative') {
return {};
}
return {
sessionId: amplitude.getInstance(this._amplitudeOptions).getSessionId(),
deviceId: amplitude.getInstance(this._amplitudeOptions).options.deviceId,

View File

@@ -0,0 +1,21 @@
// @flow
import { toState } from '../base/redux';
/**
* Checks whether rtcstats is enabled or not.
*
* @param {Function|Object} stateful - The redux store or {@code getState} function.
* @returns {boolean}
*/
export function isRtcstatsEnabled(stateful: Function | Object) {
// TODO: Remove when rtcstats is fully cimpatible with mobile.
if (navigator.product === 'ReactNative') {
return false;
}
const state = toState(stateful);
const config = state['features/base/config'];
return config?.analytics?.rtcstatsEnabled ?? false;
}

View File

@@ -9,6 +9,7 @@ import { getLocalParticipant } from '../base/participants';
import { MiddlewareRegistry } from '../base/redux';
import RTCStats from './RTCStats';
import { isRtcstatsEnabled } from './functions';
import logger from './logger';
/**
@@ -25,7 +26,7 @@ MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case LIB_WILL_INIT: {
if (analytics.rtcstatsEnabled) {
if (isRtcstatsEnabled(state)) {
// RTCStats "proxies" WebRTC functions such as GUM and RTCPeerConnection by rewriting the global
// window functions. Because lib-jitsi-meet uses references to those functions that are taken on
// init, we need to add these proxies before it initializes, otherwise lib-jitsi-meet will use the
@@ -47,7 +48,7 @@ MiddlewareRegistry.register(store => next => action => {
break;
}
case CONFERENCE_JOINED: {
if (analytics.rtcstatsEnabled && RTCStats.isInitialized()) {
if (isRtcstatsEnabled(state) && RTCStats.isInitialized()) {
// Once the conference started connect to the rtcstats server and send data.
try {
RTCStats.connect();