mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Enable crosswiki notifications and minor UI fixes in displaying notif… (#1540)
* Enable crosswiki notifications and minor UI fixes in displaying notifications * Added java docs
This commit is contained in:
parent
41acb76bd8
commit
2a0b9d8a0b
11 changed files with 247 additions and 23 deletions
|
|
@ -19,12 +19,13 @@ android:
|
||||||
components:
|
components:
|
||||||
- tools
|
- tools
|
||||||
- platform-tools
|
- platform-tools
|
||||||
- build-tools-26.0.2
|
- build-tools-27.0.0
|
||||||
- extra-google-m2repository
|
- extra-google-m2repository
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- ${ANDROID_TARGET}
|
- ${ANDROID_TARGET}
|
||||||
- android-25
|
- android-25
|
||||||
- android-26
|
- android-26
|
||||||
|
- android-27
|
||||||
- sys-img-${ANDROID_ABI}-${ANDROID_TARGET}
|
- sys-img-${ANDROID_ABI}-${ANDROID_TARGET}
|
||||||
licenses:
|
licenses:
|
||||||
- 'android-sdk-license-.+'
|
- 'android-sdk-license-.+'
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@ dependencies {
|
||||||
testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
|
testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
|
||||||
testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
|
testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
|
||||||
|
|
||||||
|
implementation 'com.caverock:androidsvg:1.2.1'
|
||||||
|
implementation 'com.github.bumptech.glide:glide:4.7.1'
|
||||||
|
kapt 'com.github.bumptech.glide:compiler:4.7.1'
|
||||||
|
|
||||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||||
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
|
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
|
||||||
androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIB_VERSION"
|
androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIB_VERSION"
|
||||||
|
|
@ -117,7 +121,7 @@ android {
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false // See https://stackoverflow.com/questions/40232404/google-play-apk-and-android-studio-apk-usb-debug-behaving-differently - proguard.cfg modification alone insufficient.
|
minifyEnabled false // See https://stackoverflow.com/questions/40232404/google-play-apk-and-android-studio-apk-usb-debug-behaving-differently - proguard.cfg modification alone insufficient.
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-glide.txt'
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
|
|
|
||||||
9
app/proguard-glide.txt
Normal file
9
app/proguard-glide.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||||
|
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||||
|
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||||
|
**[] $VALUES;
|
||||||
|
public *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# for DexGuard only
|
||||||
|
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
|
||||||
36
app/src/main/java/fr/free/nrw/commons/glide/SvgDecoder.java
Normal file
36
app/src/main/java/fr/free/nrw/commons/glide/SvgDecoder.java
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package fr.free.nrw.commons.glide;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.bumptech.glide.load.Options;
|
||||||
|
import com.bumptech.glide.load.ResourceDecoder;
|
||||||
|
import com.bumptech.glide.load.engine.Resource;
|
||||||
|
import com.bumptech.glide.load.resource.SimpleResource;
|
||||||
|
import com.caverock.androidsvg.SVG;
|
||||||
|
import com.caverock.androidsvg.SVGParseException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an SVG internal representation from an {@link InputStream}.
|
||||||
|
*/
|
||||||
|
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handles(@NonNull InputStream source, @NonNull Options options) {
|
||||||
|
// TODO: Can we tell?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Resource<SVG> decode(@NonNull InputStream source, int width, int height,
|
||||||
|
@NonNull Options options)
|
||||||
|
throws IOException {
|
||||||
|
try {
|
||||||
|
SVG svg = SVG.getFromInputStream(source);
|
||||||
|
return new SimpleResource<>(svg);
|
||||||
|
} catch (SVGParseException ex) {
|
||||||
|
throw new IOException("Cannot load SVG from stream", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package fr.free.nrw.commons.glide;
|
||||||
|
|
||||||
|
import android.graphics.Picture;
|
||||||
|
import android.graphics.drawable.PictureDrawable;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.bumptech.glide.load.Options;
|
||||||
|
import com.bumptech.glide.load.engine.Resource;
|
||||||
|
import com.bumptech.glide.load.resource.SimpleResource;
|
||||||
|
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
|
||||||
|
import com.caverock.androidsvg.SVG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the {@link SVG}'s internal representation to an Android-compatible one
|
||||||
|
* ({@link Picture}).
|
||||||
|
*/
|
||||||
|
public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Resource<PictureDrawable> transcode(@NonNull Resource<SVG> toTranscode,
|
||||||
|
@NonNull Options options) {
|
||||||
|
SVG svg = toTranscode.get();
|
||||||
|
Picture picture = svg.renderToPicture();
|
||||||
|
PictureDrawable drawable = new PictureDrawable(picture);
|
||||||
|
return new SimpleResource<>(drawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package fr.free.nrw.commons.glide;
|
||||||
|
|
||||||
|
import android.graphics.drawable.PictureDrawable;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.bumptech.glide.load.DataSource;
|
||||||
|
import com.bumptech.glide.load.engine.GlideException;
|
||||||
|
import com.bumptech.glide.request.RequestListener;
|
||||||
|
import com.bumptech.glide.request.target.ImageViewTarget;
|
||||||
|
import com.bumptech.glide.request.target.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener which updates the {@link ImageView} to be software rendered, because
|
||||||
|
* {@link com.caverock.androidsvg.SVG SVG}/{@link android.graphics.Picture Picture} can't render on
|
||||||
|
* a hardware backed {@link android.graphics.Canvas Canvas}.
|
||||||
|
*/
|
||||||
|
public class SvgSoftwareLayerSetter implements RequestListener<PictureDrawable> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the layer type to none if the load fails
|
||||||
|
* @param e
|
||||||
|
* @param model
|
||||||
|
* @param target
|
||||||
|
* @param isFirstResource
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onLoadFailed(GlideException e, Object model, Target<PictureDrawable> target,
|
||||||
|
boolean isFirstResource) {
|
||||||
|
ImageView view = ((ImageViewTarget<?>) target).getView();
|
||||||
|
view.setLayerType(ImageView.LAYER_TYPE_NONE, null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the layer type to software when the resource is ready
|
||||||
|
* @param resource
|
||||||
|
* @param model
|
||||||
|
* @param target
|
||||||
|
* @param dataSource
|
||||||
|
* @param isFirstResource
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onResourceReady(PictureDrawable resource, Object model,
|
||||||
|
Target<PictureDrawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||||
|
ImageView view = ((ImageViewTarget<?>) target).getView();
|
||||||
|
view.setLayerType(ImageView.LAYER_TYPE_SOFTWARE, null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -444,8 +444,8 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
.param("notprop", "list")
|
.param("notprop", "list")
|
||||||
.param("format", "xml")
|
.param("format", "xml")
|
||||||
.param("meta", "notifications")
|
.param("meta", "notifications")
|
||||||
// .param("meta", "notifications")
|
|
||||||
.param("notformat", "model")
|
.param("notformat", "model")
|
||||||
|
.param("notwikis", "wikidatawiki|commonswiki|enwiki")
|
||||||
.get()
|
.get()
|
||||||
.getNode("/api/query/notifications/list");
|
.getNode("/api/query/notifications/list");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package fr.free.nrw.commons.notification;
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.graphics.drawable.PictureDrawable;
|
||||||
|
import android.text.Html;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
@ -8,17 +9,23 @@ import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.borjabravo.readmoretextview.ReadMoreTextView;
|
import com.borjabravo.readmoretextview.ReadMoreTextView;
|
||||||
|
import com.bumptech.glide.RequestBuilder;
|
||||||
import com.pedrogomez.renderers.Renderer;
|
import com.pedrogomez.renderers.Renderer;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.glide.SvgSoftwareLayerSetter;
|
||||||
|
|
||||||
|
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by root on 19.12.2017.
|
* Created by root on 19.12.2017.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NotificationRenderer extends Renderer<Notification> {
|
public class NotificationRenderer extends Renderer<Notification> {
|
||||||
|
private RequestBuilder<PictureDrawable> requestBuilder;
|
||||||
|
|
||||||
@BindView(R.id.title) ReadMoreTextView title;
|
@BindView(R.id.title) ReadMoreTextView title;
|
||||||
@BindView(R.id.time) TextView time;
|
@BindView(R.id.time) TextView time;
|
||||||
@BindView(R.id.icon) ImageView icon;
|
@BindView(R.id.icon) ImageView icon;
|
||||||
|
|
@ -41,23 +48,32 @@ public class NotificationRenderer extends Renderer<Notification> {
|
||||||
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
|
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
|
||||||
View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false);
|
View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false);
|
||||||
ButterKnife.bind(this, inflatedView);
|
ButterKnife.bind(this, inflatedView);
|
||||||
|
requestBuilder = GlideApp.with(inflatedView.getContext())
|
||||||
|
.as(PictureDrawable.class)
|
||||||
|
.error(R.drawable.round_icon_unknown)
|
||||||
|
.transition(withCrossFade())
|
||||||
|
.listener(new SvgSoftwareLayerSetter());
|
||||||
return inflatedView;
|
return inflatedView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
Notification notification = getContent();
|
Notification notification = getContent();
|
||||||
String str = notification.notificationText.trim();
|
setTitle(notification.notificationText);
|
||||||
str = str.concat(" ");
|
|
||||||
title.setText(str);
|
|
||||||
time.setText(notification.date);
|
time.setText(notification.date);
|
||||||
switch (notification.notificationType) {
|
requestBuilder.load(notification.iconUrl).into(icon);
|
||||||
case THANK_YOU_EDIT:
|
}
|
||||||
icon.setImageResource(R.drawable.ic_edit_black_24dp);
|
|
||||||
break;
|
/**
|
||||||
default:
|
* Cleans up the notification text and sets it as the title
|
||||||
icon.setImageResource(R.drawable.round_icon_unknown);
|
* Clean up is required to fix escaped HTML string and extra white spaces at the beginning of the notification
|
||||||
}
|
* @param notificationText
|
||||||
|
*/
|
||||||
|
private void setTitle(String notificationText) {
|
||||||
|
notificationText = notificationText.trim().replaceAll("(^\\h*)|(\\h*$)", "");
|
||||||
|
notificationText = Html.fromHtml(notificationText).toString();
|
||||||
|
notificationText = notificationText.concat(" ");
|
||||||
|
title.setText(notificationText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface NotificationClicked{
|
public interface NotificationClicked{
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,13 @@ import javax.annotation.Nullable;
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
|
||||||
import static fr.free.nrw.commons.notification.NotificationType.THANK_YOU_EDIT;
|
|
||||||
import static fr.free.nrw.commons.notification.NotificationType.UNKNOWN;
|
import static fr.free.nrw.commons.notification.NotificationType.UNKNOWN;
|
||||||
|
|
||||||
public class NotificationUtils {
|
public class NotificationUtils {
|
||||||
|
|
||||||
private static final String COMMONS_WIKI = "commonswiki";
|
private static final String COMMONS_WIKI = "commonswiki";
|
||||||
|
private static final String WIKIDATA_WIKI = "wikidatawiki";
|
||||||
|
private static final String WIKIPEDIA_WIKI = "enwiki";
|
||||||
|
|
||||||
public static boolean isCommonsNotification(Node document) {
|
public static boolean isCommonsNotification(Node document) {
|
||||||
if (document == null || !document.hasAttributes()) {
|
if (document == null || !document.hasAttributes()) {
|
||||||
|
|
@ -31,6 +32,32 @@ public class NotificationUtils {
|
||||||
return COMMONS_WIKI.equals(element.getAttribute("wiki"));
|
return COMMONS_WIKI.equals(element.getAttribute("wiki"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the wiki attribute corresponds to wikidatawiki
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isWikidataNotification(Node document) {
|
||||||
|
if (document == null || !document.hasAttributes()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Element element = (Element) document;
|
||||||
|
return WIKIDATA_WIKI.equals(element.getAttribute("wiki"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the wiki attribute corresponds to enwiki
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isWikipediaNotification(Node document) {
|
||||||
|
if (document == null || !document.hasAttributes()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Element element = (Element) document;
|
||||||
|
return WIKIPEDIA_WIKI.equals(element.getAttribute("wiki"));
|
||||||
|
}
|
||||||
|
|
||||||
public static NotificationType getNotificationType(Node document) {
|
public static NotificationType getNotificationType(Node document) {
|
||||||
Element element = (Element) document;
|
Element element = (Element) document;
|
||||||
String type = element.getAttribute("type");
|
String type = element.getAttribute("type");
|
||||||
|
|
@ -68,10 +95,17 @@ public class NotificationUtils {
|
||||||
return notifications;
|
return notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently the app is interested in showing notifications just from the following three wikis: commons, wikidata, wikipedia
|
||||||
|
* This function returns true only if the notification belongs to any of the above wikis and is of a known notification type
|
||||||
|
* @param node
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private static boolean isUsefulNotification(Node node) {
|
private static boolean isUsefulNotification(Node node) {
|
||||||
return isCommonsNotification(node)
|
return (isCommonsNotification(node)
|
||||||
&& !getNotificationType(node).equals(UNKNOWN)
|
|| isWikidataNotification(node)
|
||||||
&& !getNotificationType(node).equals(THANK_YOU_EDIT);
|
|| isWikipediaNotification(node))
|
||||||
|
&& !getNotificationType(node).equals(UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBundledNotification(Node document) {
|
public static boolean isBundledNotification(Node document) {
|
||||||
|
|
@ -97,7 +131,7 @@ public class NotificationUtils {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case THANK_YOU_EDIT:
|
case THANK_YOU_EDIT:
|
||||||
notificationText = context.getString(R.string.notifications_thank_you_edit);
|
notificationText = getThankYouEditDescription(document);
|
||||||
break;
|
break;
|
||||||
case EDIT_USER_TALK:
|
case EDIT_USER_TALK:
|
||||||
notificationText = getNotificationText(document);
|
notificationText = getNotificationText(document);
|
||||||
|
|
@ -146,6 +180,16 @@ public class NotificationUtils {
|
||||||
return body != null ? body.getTextContent() : "";
|
return body != null ? body.getTextContent() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the header node returned in the XML document to form the description for thank you edits
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getThankYouEditDescription(Node document) {
|
||||||
|
Node body = getNode(getModel(document), "header");
|
||||||
|
return body != null ? body.getTextContent() : "";
|
||||||
|
}
|
||||||
|
|
||||||
private static String getNotificationIconUrl(Node document) {
|
private static String getNotificationIconUrl(Node document) {
|
||||||
String format = "%s%s";
|
String format = "%s%s";
|
||||||
Node iconUrl = getNode(getModel(document), "iconUrl");
|
Node iconUrl = getNode(getModel(document), "iconUrl");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.PictureDrawable;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.Registry;
|
||||||
|
import com.bumptech.glide.annotation.GlideModule;
|
||||||
|
import com.bumptech.glide.module.AppGlideModule;
|
||||||
|
import com.caverock.androidsvg.SVG;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.glide.SvgDecoder;
|
||||||
|
import fr.free.nrw.commons.glide.SvgDrawableTranscoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module for the SVG sample app.
|
||||||
|
*/
|
||||||
|
@GlideModule
|
||||||
|
public class SvgModule extends AppGlideModule {
|
||||||
|
@Override
|
||||||
|
public void registerComponents(@NonNull Context context, @NonNull Glide glide,
|
||||||
|
@NonNull Registry registry) {
|
||||||
|
registry.register(SVG.class, PictureDrawable.class, new SvgDrawableTranscoder())
|
||||||
|
.append(InputStream.class, SVG.class, new SvgDecoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable manifest parsing to avoid adding similar modules twice.
|
||||||
|
@Override
|
||||||
|
public boolean isManifestParsingEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,17 +14,17 @@
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
#Thu Mar 01 15:28:48 IST 2018
|
#Thu Mar 01 15:28:48 IST 2018
|
||||||
systemProp.http.proxyPort=0
|
systemProp.http.proxyPort=0
|
||||||
compileSdkVersion=android-26
|
compileSdkVersion=android-27
|
||||||
android.useDeprecatedNdk=true
|
android.useDeprecatedNdk=true
|
||||||
BUTTERKNIFE_VERSION=8.6.0
|
BUTTERKNIFE_VERSION=8.6.0
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
buildToolsVersion=26.0.2
|
buildToolsVersion=27.0.0
|
||||||
targetSdkVersion=25
|
targetSdkVersion=27
|
||||||
|
|
||||||
#TODO: Temporary disabled. https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#aapt2
|
#TODO: Temporary disabled. https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#aapt2
|
||||||
#Refer to PR: https://github.com/commons-app/apps-android-commons/pull/932
|
#Refer to PR: https://github.com/commons-app/apps-android-commons/pull/932
|
||||||
android.enableAapt2=false
|
android.enableAapt2=false
|
||||||
SUPPORT_LIB_VERSION=26.0.2
|
SUPPORT_LIB_VERSION=27.1.1
|
||||||
minSdkVersion=15
|
minSdkVersion=15
|
||||||
systemProp.http.proxyHost=
|
systemProp.http.proxyHost=
|
||||||
LEAK_CANARY=1.5.4
|
LEAK_CANARY=1.5.4
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue