瀏覽代碼

android: add the ability to make a "libre" build

A libre build will exclude the following:

- Analytics modules
- Google Play services GMS
- Crashlytics
- Firebase
master
Saúl Ibarra Corretgé 6 年之前
父節點
當前提交
2d45709a6a

+ 26
- 9
android/app/build.gradle 查看文件

@@ -1,6 +1,7 @@
1 1
 apply plugin: 'com.android.application'
2 2
 
3
-boolean googleServicesEnabled = project.file('google-services.json').exists()
3
+boolean googleServicesEnabled \
4
+    = project.file('google-services.json').exists() && !rootProject.ext.libreBuild
4 5
 
5 6
 // Crashlytics integration is done as part of Firebase now, so it gets
6 7
 // automagically activated with google-services.json
@@ -36,11 +37,24 @@ android {
36 37
             minifyEnabled true
37 38
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
38 39
             buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
40
+            buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
39 41
         }
40 42
         release {
41 43
             minifyEnabled true
42 44
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
43 45
             buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
46
+            buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
47
+        }
48
+    }
49
+
50
+    sourceSets {
51
+        main {
52
+            java {
53
+                if (rootProject.ext.libreBuild) {
54
+                    srcDir "src"
55
+                    exclude "**/GoogleServicesHelper.java"
56
+                }
57
+            }
44 58
         }
45 59
     }
46 60
 
@@ -58,7 +72,17 @@ dependencies {
58 72
     implementation fileTree(dir: 'libs', include: ['*.jar'])
59 73
     implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
60 74
     implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
61
-    implementation 'com.google.android.gms:play-services-auth:16.0.1'
75
+
76
+    if (!rootProject.ext.libreBuild) {
77
+        implementation 'com.google.android.gms:play-services-auth:16.0.1'
78
+
79
+        // Firebase
80
+        //  - Crashlytics
81
+        //  - Dynamic Links
82
+        implementation 'com.google.firebase:firebase-core:16.0.6'
83
+        implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
84
+        implementation 'com.google.firebase:firebase-dynamic-links:16.1.5'
85
+    }
62 86
 
63 87
     implementation project(':sdk')
64 88
 
@@ -73,13 +97,6 @@ dependencies {
73 97
         exclude group: "com.android.support", module: "annotations"
74 98
     }
75 99
     annotationProcessor "com.github.bumptech.glide:compiler:${rootProject.ext.glideVersion}"
76
-
77
-    // Firebase
78
-    //  - Crashlytics
79
-    //  - Dynamic Links
80
-    implementation 'com.google.firebase:firebase-core:16.0.6'
81
-    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
82
-    implementation 'com.google.firebase:firebase-dynamic-links:16.1.5'
83 100
 }
84 101
 
85 102
 gradle.projectsEvaluated {

+ 1
- 0
android/app/proguard-rules.pro 查看文件

@@ -80,6 +80,7 @@
80 80
 
81 81
 # Jisti Meet SDK
82 82
 
83
+-keep class org.jitsi.meet.** { *; }
83 84
 -keep class org.jitsi.meet.sdk.** { *; }
84 85
 
85 86
 # We added the following when we switched minifyEnabled on. Probably because we

+ 40
- 0
android/app/src/main/java/org/jitsi/meet/GoogleServicesHelper.java 查看文件

@@ -0,0 +1,40 @@
1
+package org.jitsi.meet;
2
+
3
+import android.net.Uri;
4
+import android.util.Log;
5
+
6
+import com.crashlytics.android.Crashlytics;
7
+import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
8
+import io.fabric.sdk.android.Fabric;
9
+
10
+import org.jitsi.meet.sdk.JitsiMeetActivity;
11
+
12
+/**
13
+ * Helper class to initialize Google related services and functionality.
14
+ * This functionality is compiled conditionally and called via reflection, that's why it was
15
+ * extracted here.
16
+ *
17
+ * "Libre builds" (builds with the LIBRE_BUILD flag set) will not include this file.
18
+ */
19
+final class GoogleServicesHelper {
20
+    public static void initialize(JitsiMeetActivity activity) {
21
+        if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
22
+            Log.d(activity.getClass().getSimpleName(), "Initializing Google Services");
23
+
24
+            Fabric.with(activity, new Crashlytics());
25
+
26
+            FirebaseDynamicLinks.getInstance().getDynamicLink(activity.getIntent())
27
+                .addOnSuccessListener(activity, pendingDynamicLinkData -> {
28
+                    Uri dynamicLink = null;
29
+
30
+                    if (pendingDynamicLinkData != null) {
31
+                        dynamicLink = pendingDynamicLinkData.getLink();
32
+                    }
33
+
34
+                    if (dynamicLink != null) {
35
+                        activity.join(dynamicLink.toString());
36
+                    }
37
+                });
38
+        }
39
+    }
40
+}

+ 10
- 19
android/app/src/main/java/org/jitsi/meet/MainActivity.java 查看文件

@@ -29,10 +29,7 @@ import org.jitsi.meet.sdk.JitsiMeet;
29 29
 import org.jitsi.meet.sdk.JitsiMeetActivity;
30 30
 import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
31 31
 
32
-import com.crashlytics.android.Crashlytics;
33
-import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
34
-import io.fabric.sdk.android.Fabric;
35
-
32
+import java.lang.reflect.Method;
36 33
 import java.net.MalformedURLException;
37 34
 import java.net.URL;
38 35
 import java.util.Map;
@@ -57,22 +54,16 @@ public class MainActivity extends JitsiMeetActivity {
57 54
 
58 55
     @Override
59 56
     protected boolean extraInitialize() {
60
-        // Setup Crashlytics and Firebase Dynamic Links
61
-        if (BuildConfig.GOOGLE_SERVICES_ENABLED) {
62
-            Fabric.with(this, new Crashlytics());
63
-
64
-            FirebaseDynamicLinks.getInstance().getDynamicLink(getIntent())
65
-                .addOnSuccessListener(this, pendingDynamicLinkData -> {
66
-                    Uri dynamicLink = null;
57
+        Log.d(this.getClass().getSimpleName(), "LIBRE_BUILD="+BuildConfig.LIBRE_BUILD);
67 58
 
68
-                    if (pendingDynamicLinkData != null) {
69
-                        dynamicLink = pendingDynamicLinkData.getLink();
70
-                    }
71
-
72
-                    if (dynamicLink != null) {
73
-                        join(dynamicLink.toString());
74
-                    }
75
-                });
59
+        // Setup Crashlytics and Firebase Dynamic Links
60
+        // Here we are using reflection since it may have been disabled at compile time.
61
+        try {
62
+            Class<?> cls = Class.forName("org.jitsi.meet.GoogleServicesHelper");
63
+            Method m = cls.getMethod("initialize", JitsiMeetActivity.class);
64
+            m.invoke(null, this);
65
+        } catch (Exception e) {
66
+            // Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
76 67
         }
77 68
 
78 69
         // In Debug builds React needs permission to write over other apps in

+ 3
- 0
android/build.gradle 查看文件

@@ -167,6 +167,9 @@ ext {
167 167
     // Glide
168 168
     excludeAppGlideModule = true
169 169
     glideVersion = "4.7.1"  // keep in sync with react-native-fast-image
170
+
171
+    // Libre build
172
+    libreBuild = (System.env.LIBRE_BUILD ?: "true").toBoolean()
170 173
 }
171 174
 
172 175
 // If Android SDK is not installed, accept its license so that it

+ 26
- 7
android/sdk/build.gradle 查看文件

@@ -10,10 +10,25 @@ android {
10 10
     }
11 11
 
12 12
     buildTypes {
13
-        debug {}
13
+        debug {
14
+            buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
15
+        }
14 16
         release {
15 17
             minifyEnabled false
16 18
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19
+            buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
20
+        }
21
+    }
22
+
23
+    sourceSets {
24
+        main {
25
+            java {
26
+                if (rootProject.ext.libreBuild) {
27
+                    srcDir "src"
28
+                    exclude "**/AmplitudeModule.java"
29
+                }
30
+                exclude "test/"
31
+            }
17 32
         }
18 33
     }
19 34
 }
@@ -24,19 +39,23 @@ dependencies {
24 39
     implementation "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"
25 40
     implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
26 41
 
27
-    implementation 'com.amplitude:android-sdk:2.14.1'
28
-    implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
29 42
     api 'com.facebook.react:react-native:+'
30 43
 
44
+    implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
45
+
46
+    if (!rootProject.ext.libreBuild) {
47
+        implementation 'com.amplitude:android-sdk:2.14.1'
48
+        implementation(project(":react-native-google-signin")) {
49
+            exclude group: 'com.google.android.gms'
50
+            exclude group: 'com.android.support'
51
+        }
52
+    }
53
+
31 54
     implementation project(':react-native-background-timer')
32 55
     implementation project(':react-native-calendar-events')
33 56
     implementation(project(':react-native-fast-image')) {
34 57
         exclude group: 'com.android.support'
35 58
     }
36
-    implementation(project(":react-native-google-signin")) {
37
-        exclude group: 'com.google.android.gms'
38
-        exclude group: 'com.android.support'
39
-    }
40 59
     implementation project(':react-native-immersive')
41 60
     implementation project(':react-native-keep-awake')
42 61
     implementation project(':react-native-linear-gradient')

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/AppInfoModule.java 查看文件

@@ -75,6 +75,7 @@ class AppInfoModule
75 75
         constants.put(
76 76
             "version",
77 77
             packageInfo == null ? "" : packageInfo.versionName);
78
+        constants.put("LIBRE_BUILD", BuildConfig.LIBRE_BUILD);
78 79
 
79 80
         return constants;
80 81
     }

+ 38
- 21
android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java 查看文件

@@ -21,6 +21,7 @@ import android.app.Application;
21 21
 import android.support.annotation.Nullable;
22 22
 
23 23
 import com.facebook.react.ReactInstanceManager;
24
+import com.facebook.react.ReactPackage;
24 25
 import com.facebook.react.bridge.NativeModule;
25 26
 import com.facebook.react.bridge.ReactContext;
26 27
 import com.facebook.react.bridge.ReactApplicationContext;
@@ -28,6 +29,7 @@ import com.facebook.react.common.LifecycleState;
28 29
 import com.facebook.react.devsupport.DevInternalSettings;
29 30
 import com.facebook.react.modules.core.DeviceEventManagerModule;
30 31
 
32
+import java.lang.reflect.Constructor;
31 33
 import java.util.ArrayList;
32 34
 import java.util.Arrays;
33 35
 import java.util.List;
@@ -48,7 +50,6 @@ class ReactInstanceManagerHolder {
48 50
             ReactApplicationContext reactContext) {
49 51
         List<NativeModule> nativeModules
50 52
             = new ArrayList<>(Arrays.<NativeModule>asList(
51
-                new AmplitudeModule(reactContext),
52 53
                 new AndroidSettingsModule(reactContext),
53 54
                 new AppInfoModule(reactContext),
54 55
                 new AudioModeModule(reactContext),
@@ -64,6 +65,14 @@ class ReactInstanceManagerHolder {
64 65
             nativeModules.add(new RNConnectionService(reactContext));
65 66
         }
66 67
 
68
+        try {
69
+            Class<?> amplitudeModuleClass = Class.forName("AmplitudeModule");
70
+            Constructor constructor = amplitudeModuleClass.getConstructor(ReactApplicationContext.class);
71
+            nativeModules.add((NativeModule)constructor.newInstance(reactContext));
72
+        } catch (Exception e) {
73
+            // Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
74
+        }
75
+
67 76
         return nativeModules;
68 77
     }
69 78
 
@@ -128,31 +137,39 @@ class ReactInstanceManagerHolder {
128 137
             return;
129 138
         }
130 139
 
140
+        List<ReactPackage> packages
141
+            = new ArrayList<>(Arrays.asList(
142
+                new com.BV.LinearGradient.LinearGradientPackage(),
143
+                new com.calendarevents.CalendarEventsPackage(),
144
+                new com.corbt.keepawake.KCKeepAwakePackage(),
145
+                new com.dylanvann.fastimage.FastImageViewPackage(),
146
+                new com.facebook.react.shell.MainReactPackage(),
147
+                new com.oblador.vectoricons.VectorIconsPackage(),
148
+                new com.ocetnik.timer.BackgroundTimerPackage(),
149
+                new com.oney.WebRTCModule.WebRTCModulePackage(),
150
+                new com.rnimmersive.RNImmersivePackage(),
151
+                new com.zmxv.RNSound.RNSoundPackage(),
152
+                new ReactPackageAdapter() {
153
+                    @Override
154
+                    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
155
+                        return ReactInstanceManagerHolder.createNativeModules(reactContext);
156
+                    }
157
+                }));
158
+
159
+        try {
160
+            Class<?> googlePackageClass = Class.forName("co.apptailor.googlesignin.RNGoogleSigninPackage");
161
+            Constructor constructor = googlePackageClass.getConstructor();
162
+            packages.add((ReactPackage)constructor.newInstance());
163
+        } catch (Exception e) {
164
+            // Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
165
+        }
166
+
131 167
         reactInstanceManager
132 168
             = ReactInstanceManager.builder()
133 169
                 .setApplication(application)
134 170
                 .setBundleAssetName("index.android.bundle")
135 171
                 .setJSMainModulePath("index.android")
136
-                .addPackage(new co.apptailor.googlesignin.RNGoogleSigninPackage())
137
-                .addPackage(new com.BV.LinearGradient.LinearGradientPackage())
138
-                .addPackage(new com.calendarevents.CalendarEventsPackage())
139
-                .addPackage(new com.corbt.keepawake.KCKeepAwakePackage())
140
-                .addPackage(new com.dylanvann.fastimage.FastImageViewPackage())
141
-                .addPackage(new com.facebook.react.shell.MainReactPackage())
142
-                .addPackage(new com.oblador.vectoricons.VectorIconsPackage())
143
-                .addPackage(new com.ocetnik.timer.BackgroundTimerPackage())
144
-                .addPackage(new com.oney.WebRTCModule.WebRTCModulePackage())
145
-                .addPackage(new com.rnimmersive.RNImmersivePackage())
146
-                .addPackage(new com.zmxv.RNSound.RNSoundPackage())
147
-                .addPackage(new ReactPackageAdapter() {
148
-                    @Override
149
-                    public List<NativeModule> createNativeModules(
150
-                            ReactApplicationContext reactContext) {
151
-                        return
152
-                            ReactInstanceManagerHolder.createNativeModules(
153
-                                reactContext);
154
-                    }
155
-                })
172
+                .addPackages(packages)
156 173
                 .setUseDeveloperSupport(BuildConfig.DEBUG)
157 174
                 .setInitialLifecycleState(LifecycleState.RESUMED)
158 175
                 .build();

+ 5
- 0
react/features/analytics/handlers/amplitude/Amplitude.native.js 查看文件

@@ -13,6 +13,11 @@ class Amplitude {
13 13
      * be used only for multi-project logging.
14 14
      */
15 15
     constructor(instanceName) {
16
+        // It might not have been included in the build.
17
+        if (!AmplitudeNative) {
18
+            throw new Error('Amplitude analytics is not supported');
19
+        }
20
+
16 21
         this._instanceName = instanceName;
17 22
     }
18 23
 

react/features/base/config/functions.js → react/features/base/config/functions.any.js 查看文件

@@ -1,4 +1,4 @@
1
-/* @flow */
1
+// @flow
2 2
 
3 3
 import _ from 'lodash';
4 4
 

+ 21
- 0
react/features/base/config/functions.native.js 查看文件

@@ -0,0 +1,21 @@
1
+// @flow
2
+
3
+import { NativeModules } from 'react-native';
4
+
5
+export * from './functions.any';
6
+
7
+/**
8
+ * Removes all analytics related options from the given configuration, in case of a libre build.
9
+ *
10
+ * @param {*} config - The configuration which needs to be cleaned up.
11
+ * @returns {void}
12
+ */
13
+export function _cleanupConfig(config: Object) {
14
+    if (NativeModules.AppInfo.LIBRE_BUILD) {
15
+        config.analytics.scriptURLs = [];
16
+        delete config.analytics.amplitudeAPPKey;
17
+        delete config.analytics.googleAnalyticsTrackingId;
18
+        delete config.callStatsID;
19
+        delete config.callStatsSecret;
20
+    }
21
+}

+ 12
- 0
react/features/base/config/functions.web.js 查看文件

@@ -0,0 +1,12 @@
1
+// @flow
2
+
3
+export * from './functions.any';
4
+
5
+/**
6
+ * Removes all analytics related options from the given configuration, in case of a libre build.
7
+ *
8
+ * @param {*} config - The configuration which needs to be cleaned up.
9
+ * @returns {void}
10
+ */
11
+export function _cleanupConfig(config: Object) { // eslint-disable-line no-unused-vars
12
+}

+ 5
- 0
react/features/base/config/reducer.js 查看文件

@@ -5,6 +5,7 @@ import _ from 'lodash';
5 5
 import { equals, ReducerRegistry, set } from '../redux';
6 6
 
7 7
 import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from './actionTypes';
8
+import { _cleanupConfig } from './functions';
8 9
 
9 10
 /**
10 11
  * The initial state of the feature base/config when executing in a
@@ -29,6 +30,8 @@ const INITIAL_NON_RN_STATE = {
29 30
  * @type {Object}
30 31
  */
31 32
 const INITIAL_RN_STATE = {
33
+    analytics: {},
34
+
32 35
     // FIXME The support for audio levels in lib-jitsi-meet polls the statistics
33 36
     // of WebRTC at a short interval multiple times a second. Unfortunately,
34 37
     // React Native is slow to fetch these statistics from the native WebRTC
@@ -135,6 +138,8 @@ function _setConfig(state, { config }) {
135 138
         _getInitialState()
136 139
     );
137 140
 
141
+    _cleanupConfig(newState);
142
+
138 143
     return equals(state, newState) ? state : newState;
139 144
 }
140 145
 

+ 14
- 4
react/features/google-api/googleApi.native.js 查看文件

@@ -1,8 +1,12 @@
1 1
 // @flow
2 2
 
3
-import {
4
-    GoogleSignin
5
-} from 'react-native-google-signin';
3
+import { NativeModules } from 'react-native';
4
+
5
+let GoogleSignin;
6
+
7
+if (NativeModules.RNGoogleSignin) {
8
+    GoogleSignin = require('react-native-google-signin').GoogleSignin;
9
+}
6 10
 
7 11
 import {
8 12
     API_URL_BROADCAST_STREAMS,
@@ -26,7 +30,9 @@ class GoogleApi {
26 30
      * @returns {void}
27 31
      */
28 32
     configure(config: Object) {
29
-        GoogleSignin.configure(config);
33
+        if (GoogleSignin) {
34
+            GoogleSignin.configure(config);
35
+        }
30 36
     }
31 37
 
32 38
     /**
@@ -58,6 +64,10 @@ class GoogleApi {
58 64
      * @returns {Promise<*>}
59 65
      */
60 66
     hasPlayServices() {
67
+        if (!GoogleSignin) {
68
+            return Promise.reject(new Error('Google SignIn not supported'));
69
+        }
70
+
61 71
         return GoogleSignin.hasPlayServices();
62 72
     }
63 73
 

Loading…
取消
儲存