Commit 47e7ad4b authored by Benoit Marty's avatar Benoit Marty

Merge branch 'release/0.8.19'

parents d9d8db49 c990daf2
Pipeline #2061 failed with stages
This diff is collapsed.
......@@ -56,9 +56,9 @@ Let says your application is named MyRiot : You have to create your own flavour.
Modify riot-android/vector/build.gradle
---------------------------------------
In "productFlavors" section, duplicate "app" group if you plan to use GCM/FCM or "appfdroid" if don't.
In "productFlavors" section, duplicate "app" group if you plan to use FCM or "appfdroid" if don't.
for example, with GCM, it would give
for example, with FCM, it would give
```
appmyriot {
......@@ -66,22 +66,21 @@ for example, with GCM, it would give
// use the version name
versionCode rootProject.ext.versionCodeProp
versionName rootProject.ext.versionNameProp
resValue "string", "allow_gcm_use", "true"
resValue "string", "allow_ga_use", "true"
resValue "string", "short_flavor_description", "G"
resValue "string", "flavor_description", "GooglePlay"
buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
}
```
- if you use GCM, duplicate appCompile at the end of this file and replace appCompile by appmyriotCompile.
- if you use FCM, duplicate appCompile at the end of this file and replace appCompile by appmyriotCompile.
- if you don't, update the "if (!getGradle().getStartParameter().getTaskRequests().toString().contains("fdroid"))" to include your flavor.
Create your flavour directory
-----------------------------
- Copy riot-android/vector/src/app or appfroid if you use GCM or you don’t.
- Copy riot-android/vector/src/app or appfroid if you use FCM or you don’t.
- Rename it to appmyriot.
- If you use GCM, you will need to generate your own google-services.json.
- If you use FCM, you will need to generate your own google-services.json.
Customise your flavour
----------------------
......
......@@ -23,8 +23,8 @@ buildscript {
// global properties used in sub modules
ext {
versionCodeProp = 81800
versionNameProp = "0.8.18"
versionCodeProp = 81900
versionNameProp = "0.8.19"
versionBuild = System.getenv("BUILD_NUMBER") as Integer ?: 0
buildNumberProp = "${versionBuild}"
}
......
......@@ -66,3 +66,7 @@ DO NOT COMMIT
### Bad comment format in XML resources. Use <!-- --> instead of //
^\s*\/\/
### Bad RTL support, use attribute with Start and End
layout_constraintRight_
layout_constraintLeft_
......@@ -24,7 +24,7 @@ android {
versionName rootProject.ext.versionNameProp
// custom values
resValue "string", "bug_report_url", "https://riot.im/bugreports/submit"
resValue "string", "bug_report_url", "https://riot.im/bugreports/submit"
ndk {
abiFilters "armeabi-v7a", "x86"
......@@ -92,10 +92,9 @@ android {
// use the version name
versionCode rootProject.ext.versionCodeProp
versionName rootProject.ext.versionNameProp
resValue "string", "allow_gcm_use", "true"
resValue "string", "allow_ga_use", "true"
resValue "string", "short_flavor_description", "G"
resValue "string", "flavor_description", "GooglePlay"
buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
}
appfdroid {
......@@ -103,23 +102,41 @@ android {
// use the version name
versionCode rootProject.ext.versionCodeProp
versionName rootProject.ext.versionNameProp
resValue "string", "allow_gcm_use", "false"
resValue "string", "allow_ga_use", "false"
resValue "string", "short_flavor_description", "F"
resValue "string", "flavor_description", "FDroid"
buildConfigField "boolean", "ALLOW_FCM_USE", "false"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
}
}
lintOptions {
disable 'InvalidPackage'
disable 'MissingTranslation'
disable 'RestrictedApi'
disable 'ImpliedQuantity'
warning 'MissingTranslation'
// Treat some warnings as errors
// Resources
error 'TypographyEllipsis'
error 'ImpliedQuantity'
// UX
error 'ButtonOrder'
// Layout
error 'StringFormatCount'
error 'HardcodedText'
error 'SpUsage'
error 'ObsoleteLayoutParam'
error 'InefficientWeight'
error 'DisableBaselineAlignment'
error 'ScrollViewSize'
// RTL
error 'RtlEnabled'
error 'RtlHardcoded'
error 'RtlSymmetry'
// Code
error 'SetTextI18n'
error 'ViewConstructor'
error 'UseValueOf'
}
repositories {
......@@ -159,6 +176,9 @@ dependencies {
// Kotlin KTX
implementation 'androidx.core:core-ktx:0.3'
// Kotlin coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.2'
implementation 'com.android.support:multidex:1.0.0'
implementation 'me.leolin:ShortcutBadger:1.1.2@aar'
......@@ -221,15 +241,14 @@ dependencies {
implementation(name: 'react-native', ext: 'aar')
implementation(name: 'react-native-locale-detector', ext: 'aar')
// another tracking than GA
implementation 'org.piwik.sdk:piwik-sdk:2.0.0'
/************* flavors management **************/
// app flavor only
appImplementation 'com.google.firebase:firebase-core:16.0.3'
appImplementation 'com.google.firebase:firebase-messaging:17.3.0'
appImplementation 'com.google.firebase:firebase-core:16.0.4'
appImplementation 'com.google.firebase:firebase-messaging:17.3.4'
// fdroid flavor only
......
......@@ -8,19 +8,12 @@
android:name="firebase_analytics_collection_deactivated"
android:value="true" />
<service
android:name="im.vector.gcm.MatrixGcmListenerService">
<service android:name="im.vector.push.fcm.VectorFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="im.vector.gcm.MatrixInstanceIDListenerService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
......@@ -15,57 +15,71 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.gcm;
package im.vector.push.fcm;
import com.google.firebase.FirebaseApp;
import android.app.Activity;
import android.content.Context;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import org.matrix.androidsdk.util.Log;
import im.vector.VectorApp;
/**
* This class store the FCM token in SharedPrefs and ensure this token is retrieved.
* It has an alter ego in the fdroid variant.
*/
public class FcmHelper {
private static final String LOG_TAG = FcmHelper.class.getSimpleName();
class GCMHelper {
private static final String LOG_TAG = GCMHelper.class.getSimpleName();
private static final String PREFS_KEY_FCM_TOKEN = "FCM_TOKEN";
/**
* Retrieves the FCM registration token.
*
* @return the FCM token or null if not received from FCM
*/
static String getRegistrationToken() {
String registrationToken = null;
// Note: FirebaseApp initialization is not necessary, but some users report that application crashes if this is not done
// Because of this, we keep the code for the moment.
if (null == VectorApp.getInstance()) {
Log.e(LOG_TAG, "## getRegistrationToken() : No active application", new Exception("StackTrace"));
} else {
try {
if (null == FirebaseApp.initializeApp(VectorApp.getInstance())) {
Log.e(LOG_TAG, "## getRegistrationToken() : cannot initialise FirebaseApp", new Exception("StackTrace"));
}
} catch (Exception e) {
Log.e(LOG_TAG, "## getRegistrationToken() : init failed " + e.getMessage(), e);
}
}
// And we protect the call to getToken()
try {
registrationToken = FirebaseInstanceId.getInstance().getToken();
Log.d(LOG_TAG, "## getRegistrationToken(): " + registrationToken);
} catch (Exception e) {
Log.e(LOG_TAG, "## getRegistrationToken() : failed " + e.getMessage(), e);
}
@Nullable
public static String getFcmToken(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString(PREFS_KEY_FCM_TOKEN, null);
}
return registrationToken;
/**
* Store FCM token to the SharedPrefs
*
* @param context android context
* @param token the token to store
*/
public static void storeFcmToken(@NonNull Context context,
@Nullable String token) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putString(PREFS_KEY_FCM_TOKEN, token)
.apply();
}
/**
* Clear the registration token.
* onNewToken may not be called on application upgrade, so ensure my shared pref is set
*
* @param activity the first launch Activity
*/
static void clearRegistrationToken() {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (Exception e) {
Log.e(LOG_TAG, "##clearRegistrationToken() failed " + e.getMessage(), e);
public static void ensureFcmTokenIsRetrieved(final Activity activity) {
if (TextUtils.isEmpty(getFcmToken(activity))) {
try {
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(activity, new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
storeFcmToken(activity, instanceIdResult.getToken());
}
});
} catch (Exception e) {
Log.e(LOG_TAG, "## ensureFcmTokenIsRetrieved() : failed " + e.getMessage(), e);
}
}
}
}
......@@ -16,7 +16,7 @@
* limitations under the License.
*/
package im.vector.gcm;
package im.vector.push.fcm;
import android.support.annotation.Nullable;
......@@ -35,14 +35,14 @@ import java.util.Map;
import im.vector.Matrix;
import im.vector.VectorApp;
import im.vector.activity.CommonActivityUtils;
import im.vector.push.PushManager;
import im.vector.services.EventStreamService;
import im.vector.util.VectorUtils;
/**
* Class implementing GcmListenerService.
* Class extending FirebaseMessagingService.
*/
public class MatrixGcmListenerService extends FirebaseMessagingService {
private static final String LOG_TAG = MatrixGcmListenerService.class.getSimpleName();
public class VectorFirebaseMessagingService extends FirebaseMessagingService {
private static final String LOG_TAG = VectorFirebaseMessagingService.class.getSimpleName();
// Tells if the events service running state has been tested
private Boolean mCheckLaunched = false;
......@@ -51,9 +51,9 @@ public class MatrixGcmListenerService extends FirebaseMessagingService {
private android.os.Handler mUIHandler = null;
/**
* Try to create an event from the GCM data
* Try to create an event from the FCM data
*
* @param data the GCM data
* @param data the FCM data
* @return the event
*/
@Nullable
......@@ -113,13 +113,13 @@ public class MatrixGcmListenerService extends FirebaseMessagingService {
// update the badge counter
CommonActivityUtils.updateBadgeCount(getApplicationContext(), unreadCount);
GcmRegistrationManager gcmManager = Matrix.getInstance(getApplicationContext()).getSharedGCMRegistrationManager();
PushManager pushManager = Matrix.getInstance(getApplicationContext()).getPushManager();
if (!gcmManager.areDeviceNotificationsAllowed()) {
if (!pushManager.areDeviceNotificationsAllowed()) {
Log.d(LOG_TAG, "## onMessageReceivedInternal() : the notifications are disabled");
return;
}
if (!gcmManager.isBackgroundSyncAllowed() && VectorApp.isAppInBackground()) {
if (!pushManager.isBackgroundSyncAllowed() && VectorApp.isAppInBackground()) {
EventStreamService eventStreamService = EventStreamService.getInstance();
Event event = parseEvent(data);
......@@ -143,7 +143,7 @@ public class MatrixGcmListenerService extends FirebaseMessagingService {
}
// check if the application has been launched once
// the first GCM event could have been triggered whereas the application is not yet launched.
// the first FCM event could have been triggered whereas the application is not yet launched.
// so it is required to create the sessions and to start/resume event stream
if (!mCheckLaunched && null != Matrix.getInstance(getApplicationContext()).getDefaultSession()) {
CommonActivityUtils.startEventStreamService(this);
......@@ -178,6 +178,21 @@ public class MatrixGcmListenerService extends FirebaseMessagingService {
}
}
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is also called
* when the InstanceID token is initially generated, so this is where
* you retrieve the token.
*/
@Override
public void onNewToken(String refreshedToken) {
Log.d(LOG_TAG, "onNewToken: " + refreshedToken);
FcmHelper.storeFcmToken(this, refreshedToken);
Matrix.getInstance(this).getPushManager().resetFCMRegistration(refreshedToken);
}
/**
* Called when message is received.
*
......
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="im.vector">
<application>
<receiver android:name=".receiver.OnApplicationUpgradeReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
</application>
</manifest>
\ No newline at end of file
/**
* Copyright 2015 Google Inc. All Rights Reserved.
* Copyright 2017 Vector Creations Ltd
* <p>
/*
* Copyright 2014 OpenMarket Ltd
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.push.fcm;
package im.vector.gcm;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class FcmHelper {
import org.matrix.androidsdk.util.Log;
import im.vector.Matrix;
public class MatrixInstanceIDListenerService extends FirebaseInstanceIdService {
private static final String LOG_TAG = MatrixInstanceIDListenerService.class.getSimpleName();
/**
* Retrieves the FCM registration token.
*
* @return the FCM token or null if not received from FCM
*/
@Nullable
public static String getFcmToken(Context context) {
return null;
}
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is also called
* when the InstanceID token is initially generated, so this is where
* you retrieve the token.
* Store FCM token to the SharedPrefs
*
* @param context android context
* @param token the token to store
*/
// [START refresh_token]
@Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(LOG_TAG, "onTokenRefresh " + refreshedToken);
public static void storeFcmToken(@NonNull Context context,
@Nullable String token) {
// No op
}
Matrix.getInstance(this).getSharedGCMRegistrationManager().resetGCMRegistration(refreshedToken);
/**
* onNewToken may not be called on application upgrade, so ensure my shared pref is set
*
* @param activity the first launch Activity
*/
public static void ensureFcmTokenIsRetrieved(final Activity activity) {
// No op
}
}
/*
* Copyright 2014 OpenMarket Ltd
* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
......@@ -14,23 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.gcm;
class GCMHelper {
package im.vector.receiver;
/**
* Retrieves the GCM registration token.
*
* @return the registration token.
*/
static String getRegistrationToken() {
return null;
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.matrix.androidsdk.util.Log;
import im.vector.activity.CommonActivityUtils;
public class OnApplicationUpgradeReceiver extends BroadcastReceiver {
private static final String LOG_TAG = OnApplicationUpgradeReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG, "## onReceive() : Application has been upgraded, restart event stream service.");
/**
* Clear the registration token.
*/
static void clearRegistrationToken() {
// No op
// Start Event stream
CommonActivityUtils.startEventStreamService(context);
}
}
......@@ -41,7 +41,7 @@ class DebugReceiver : BroadcastReceiver() {
private fun dumpPreferences(context: Context) {
logPrefs("DefaultSharedPreferences", PreferenceManager.getDefaultSharedPreferences(context))
logPrefs("Vector.LoginStorage", context.getSharedPreferences("Vector.LoginStorage", Context.MODE_PRIVATE))
logPrefs("GcmRegistrationManager", context.getSharedPreferences("GcmRegistrationManager", Context.MODE_PRIVATE))
logPrefs("PushManager", context.getSharedPreferences("GcmRegistrationManager", Context.MODE_PRIVATE))
}
private fun logPrefs(name: String, sharedPreferences: SharedPreferences?) {
......
......@@ -12,14 +12,14 @@
<TextView
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="?attr/primary_dark_color"
android:background="?attr/vctr_primary_dark_color"
android:gravity="center_vertical"
android:text="Status Bar" />
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="?attr/primary_color"
android:background="?attr/vctr_primary_color"
android:gravity="center_vertical"
android:text="This is a simple text" />
......
......@@ -104,6 +104,7 @@
android:largeHeap="true"
android:logo="@drawable/logo"
android:resizeableActivity="false"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light"
tools:replace="allowBackup,label">
......@@ -295,7 +296,6 @@
android:label="Vector searches"
android:launchMode="singleTop"
android:parentActivityName=".activity.VectorRoomDetailsActivity"
android:theme="@style/SearchesAppTheme.Light"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
......@@ -389,7 +389,7 @@