Browse Source

android: add serverURL configuration for MDM/EMM environments

Android for Enterprise provides special feature for applications to obtain configuration through RestrictionManager remotely by some MDM solution.

Jitsi Meet can be remotely installed and provisioned with a proper URL (making URL not editable by the user) inside the Work Profile or Fully managed device.
master
Roman 5 years ago
parent
commit
4b1743bb2f
No account linked to committer's email address

+ 3
- 0
android/app/src/main/AndroidManifest.xml View File

@@ -7,6 +7,9 @@
7 7
       android:label="@string/app_name"
8 8
       android:networkSecurityConfig="@xml/network_security_config"
9 9
       android:theme="@style/AppTheme">
10
+    <meta-data
11
+        android:name="android.content.APP_RESTRICTIONS"
12
+        android:resource="@xml/app_restrictions" />
10 13
     <activity
11 14
         android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"
12 15
         android:label="@string/app_name"

+ 83
- 5
android/app/src/main/java/org/jitsi/meet/MainActivity.java View File

@@ -16,9 +16,15 @@
16 16
 
17 17
 package org.jitsi.meet;
18 18
 
19
+import android.content.BroadcastReceiver;
20
+import android.content.Context;
19 21
 import android.content.Intent;
22
+import android.content.IntentFilter;
23
+import android.content.RestrictionEntry;
24
+import android.content.RestrictionsManager;
20 25
 import android.net.Uri;
21 26
 import android.os.Build;
27
+import android.os.Bundle;
22 28
 import android.provider.Settings;
23 29
 import android.util.Log;
24 30
 import android.view.KeyEvent;
@@ -31,6 +37,7 @@ import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
31 37
 import java.lang.reflect.Method;
32 38
 import java.net.MalformedURLException;
33 39
 import java.net.URL;
40
+import java.util.Collection;
34 41
 import java.util.Map;
35 42
 
36 43
 /**
@@ -48,6 +55,27 @@ public class MainActivity extends JitsiMeetActivity {
48 55
     private static final int OVERLAY_PERMISSION_REQUEST_CODE
49 56
         = (int) (Math.random() * Short.MAX_VALUE);
50 57
 
58
+    /**
59
+     * ServerURL configuration key for restriction configuration using {@link android.content.RestrictionsManager}
60
+     */
61
+    public static final String RESTRICTION_SERVER_URL = "SERVER_URL";
62
+
63
+    /**
64
+     * Broadcast receiver for restrictions handling
65
+     */
66
+    private BroadcastReceiver broadcastReceiver;
67
+
68
+    /**
69
+     * Flag if configuration is provided by RestrictionManager
70
+     */
71
+    private boolean configurationByRestrictions = false;
72
+
73
+    /**
74
+     * Default URL as could be obtained from RestrictionManager
75
+     */
76
+    private String defaultURL;
77
+
78
+
51 79
     // JitsiMeetActivity overrides
52 80
     //
53 81
 
@@ -85,16 +113,66 @@ public class MainActivity extends JitsiMeetActivity {
85 113
 
86 114
     @Override
87 115
     protected void initialize() {
116
+        broadcastReceiver = new BroadcastReceiver() {
117
+            @Override
118
+            public void onReceive(Context context, Intent intent) {
119
+                // As new restrictions including server URL are received,
120
+                // conference should be restarted with new configuration.
121
+                leave();
122
+                recreate();
123
+            }
124
+        };
125
+        registerReceiver(broadcastReceiver,
126
+            new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED));
127
+
128
+        resolveRestrictions();
129
+        setJitsiMeetConferenceDefaultOptions();
130
+        super.initialize();
131
+    }
132
+
133
+    @Override
134
+    public void onDestroy() {
135
+        if (broadcastReceiver != null) {
136
+            unregisterReceiver(broadcastReceiver);
137
+            broadcastReceiver = null;
138
+        }
139
+
140
+        super.onDestroy();
141
+    }
142
+
143
+    private void setJitsiMeetConferenceDefaultOptions() {
88 144
         // Set default options
89 145
         JitsiMeetConferenceOptions defaultOptions
90 146
             = new JitsiMeetConferenceOptions.Builder()
91
-                .setWelcomePageEnabled(true)
92
-                .setServerURL(buildURL("https://meet.jit.si"))
93
-                .setFeatureFlag("call-integration.enabled", false)
94
-                .build();
147
+            .setWelcomePageEnabled(true)
148
+            .setServerURL(buildURL(defaultURL))
149
+            .setFeatureFlag("call-integration.enabled", false)
150
+            .setFeatureFlag("server-url-change.enabled", !configurationByRestrictions)
151
+            .build();
95 152
         JitsiMeet.setDefaultConferenceOptions(defaultOptions);
153
+    }
96 154
 
97
-        super.initialize();
155
+    private void resolveRestrictions() {
156
+        RestrictionsManager manager =
157
+            (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
158
+        Bundle restrictions = manager.getApplicationRestrictions();
159
+        Collection<RestrictionEntry> entries = manager.getManifestRestrictions(
160
+            getApplicationContext().getPackageName());
161
+        for (RestrictionEntry restrictionEntry : entries) {
162
+            String key = restrictionEntry.getKey();
163
+            if (RESTRICTION_SERVER_URL.equals(key)) {
164
+                // If restrictions are passed to the application.
165
+                if (restrictions != null &&
166
+                    restrictions.containsKey(RESTRICTION_SERVER_URL)) {
167
+                    defaultURL = restrictions.getString(RESTRICTION_SERVER_URL);
168
+                    configurationByRestrictions = true;
169
+                // Otherwise use default URL from app-restrictions.xml.
170
+                } else {
171
+                    defaultURL = restrictionEntry.getSelectedString();
172
+                    configurationByRestrictions = false;
173
+                }
174
+            }
175
+        }
98 176
     }
99 177
 
100 178
     @Override

+ 2
- 0
android/app/src/main/res/values/strings.xml View File

@@ -1,3 +1,5 @@
1 1
 <resources>
2 2
     <string name="app_name">Jitsi Meet</string>
3
+    <string name="restriction_server_url_description">URL of Jitsi Meet server instance to connect to</string>
4
+    <string name="restriction_server_url_title">Server URL</string>
3 5
 </resources>

+ 11
- 0
android/app/src/main/res/xml/app_restrictions.xml View File

@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+    <!-- Server URL configuration -->
5
+    <restriction
6
+        android:defaultValue="https://meet.jit.si"
7
+        android:description="@string/restriction_server_url_description"
8
+        android:key="SERVER_URL"
9
+        android:restrictionType="string"
10
+        android:title="@string/restriction_server_url_title"/>
11
+</restrictions>

+ 15
- 1
react/features/app/components/App.native.js View File

@@ -4,7 +4,7 @@ import React from 'react';
4 4
 
5 5
 import { setColorScheme } from '../../base/color-scheme';
6 6
 import { DialogContainer } from '../../base/dialog';
7
-import { CALL_INTEGRATION_ENABLED, updateFlags } from '../../base/flags';
7
+import { CALL_INTEGRATION_ENABLED, SERVER_URL_CHANGE_ENABLED, updateFlags } from '../../base/flags';
8 8
 import { Platform } from '../../base/react';
9 9
 import { DimensionsDetector, clientResized } from '../../base/responsive-ui';
10 10
 import { updateSettings } from '../../base/settings';
@@ -86,6 +86,20 @@ export class App extends AbstractApp {
86 86
             // We set these early enough so then we avoid any unnecessary re-renders.
87 87
             const { dispatch } = this.state.store;
88 88
 
89
+            // Check if serverURL is configured externally and not allowed to change.
90
+            const serverURLChangeEnabled = this.props.flags[SERVER_URL_CHANGE_ENABLED];
91
+
92
+            if (!serverURLChangeEnabled) {
93
+                // As serverURL is provided externally, so we push it to settings.
94
+                if (typeof this.props.url !== 'undefined') {
95
+                    const { serverURL } = this.props.url;
96
+
97
+                    if (typeof serverURL !== 'undefined') {
98
+                        dispatch(updateSettings({ serverURL }));
99
+                    }
100
+                }
101
+            }
102
+
89 103
             dispatch(setColorScheme(this.props.colorScheme));
90 104
             dispatch(updateFlags(this.props.flags));
91 105
             dispatch(updateSettings(this.props.userInfo || {}));

+ 6
- 0
react/features/base/flags/constants.js View File

@@ -81,6 +81,12 @@ export const RAISE_HAND_ENABLED = 'raise-hand.enabled';
81 81
  */
82 82
 export const RECORDING_ENABLED = 'recording.enabled';
83 83
 
84
+/**
85
+ * Flag indicating if server URL change is enabled.
86
+ * Default: enabled (true)
87
+ */
88
+export const SERVER_URL_CHANGE_ENABLED = 'server-url-change.enabled';
89
+
84 90
 /**
85 91
  * Flag indicating if tile view feature should be enabled.
86 92
  * Default: enabled.

+ 19
- 3
react/features/settings/components/native/SettingsView.js View File

@@ -7,11 +7,11 @@ import { translate } from '../../../base/i18n';
7 7
 import { JitsiModal } from '../../../base/modal';
8 8
 import { connect } from '../../../base/redux';
9 9
 import { SETTINGS_VIEW_ID } from '../../constants';
10
-import { normalizeUserInputURL } from '../../functions';
10
+import { normalizeUserInputURL, isServerURLChangeEnabled } from '../../functions';
11 11
 import {
12 12
     AbstractSettingsView,
13 13
     _mapStateToProps as _abstractMapStateToProps,
14
-    type Props
14
+    type Props as AbstractProps
15 15
 } from '../AbstractSettingsView';
16 16
 
17 17
 import FormRow from './FormRow';
@@ -70,6 +70,20 @@ type State = {
70 70
     startWithVideoMuted: boolean,
71 71
 }
72 72
 
73
+/**
74
+ * The type of the React {@code Component} props of
75
+ * {@link SettingsView}.
76
+ */
77
+type Props = AbstractProps & {
78
+
79
+    /**
80
+     * Flag indicating if URL can be changed by user.
81
+     *
82
+     * @protected
83
+     */
84
+    _serverURLChangeEnabled: boolean
85
+}
86
+
73 87
 /**
74 88
  * The native container rendering the app settings page.
75 89
  *
@@ -168,6 +182,7 @@ class SettingsView extends AbstractSettingsView<Props, State> {
168 182
                         <TextInput
169 183
                             autoCapitalize = 'none'
170 184
                             autoCorrect = { false }
185
+                            editable = { this.props._serverURLChangeEnabled }
171 186
                             onBlur = { this._onBlurServerURL }
172 187
                             onChangeText = { this._onChangeServerURL }
173 188
                             placeholder = { this.props._serverURL }
@@ -514,7 +529,8 @@ class SettingsView extends AbstractSettingsView<Props, State> {
514 529
  */
515 530
 function _mapStateToProps(state) {
516 531
     return {
517
-        ..._abstractMapStateToProps(state)
532
+        ..._abstractMapStateToProps(state),
533
+        _serverURLChangeEnabled: isServerURLChangeEnabled(state)
518 534
     };
519 535
 }
520 536
 

+ 16
- 0
react/features/settings/functions.js View File

@@ -1,4 +1,6 @@
1 1
 // @flow
2
+
3
+import { SERVER_URL_CHANGE_ENABLED, getFeatureFlag } from '../base/flags';
2 4
 import { i18next, DEFAULT_LANGUAGE, LANGUAGES } from '../base/i18n';
3 5
 import { createLocalTrack } from '../base/lib-jitsi-meet/functions';
4 6
 import {
@@ -23,6 +25,20 @@ export function isSettingEnabled(settingName: string) {
23 25
     return interfaceConfig.SETTINGS_SECTIONS.includes(settingName);
24 26
 }
25 27
 
28
+/**
29
+ * Returns true if user is allowed to change Server URL.
30
+ *
31
+ * @param {(Function|Object)} stateful - The (whole) redux state, or redux's
32
+ * {@code getState} function to be used to retrieve the state.
33
+ * @returns {boolean} True to indicate that user can change Server URL, false otherwise.
34
+ */
35
+export function isServerURLChangeEnabled(stateful: Object | Function) {
36
+    const state = toState(stateful);
37
+    const flag = getFeatureFlag(state, SERVER_URL_CHANGE_ENABLED, true);
38
+
39
+    return flag;
40
+}
41
+
26 42
 /**
27 43
  * Normalizes a URL entered by the user.
28 44
  * FIXME: Consider adding this to base/util/uri.

Loading…
Cancel
Save