From d47baf2208e1e7a70d57dc4bfa9fa6507d9a13e1 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 10:48:03 +0200 Subject: [PATCH 001/128] fix lint error: Multi-catch with these reflection exceptions requires API level 19 (current min is 7) --- .../org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java index b68de63a..9020c24b 100644 --- a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java +++ b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java @@ -46,7 +46,9 @@ public SubscriberInfo getSuperSubscriberInfo() { } try { return superSubscriberInfoClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { throw new RuntimeException(e); } } From a4c613e58ea1fd90f46a75f39dc95297d4759971 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 10:51:35 +0200 Subject: [PATCH 002/128] Gradle 3.4.1 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 53319 -> 54212 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 22 +++++++++++++++------- gradlew.bat | 6 ------ 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 9c519b5c..958c35ba 100644 --- a/build.gradle +++ b/build.gradle @@ -7,5 +7,5 @@ if (JavaVersion.current().isJava8Compatible()) { } task wrapper(type: Wrapper) { - gradleVersion = '2.14.1' + gradleVersion = '3.4.1' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d3b83982b9b1bccad955349d702be9b884c6e049..90ae8dfd9ca83141cd5b1fc8cf52c663bce33bc5 100644 GIT binary patch delta 21905 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 Date: Mon, 10 Apr 2017 10:52:25 +0200 Subject: [PATCH 003/128] updated Android versions --- .travis.yml | 2 +- EventBusPerformance/build.gradle | 4 ++-- EventBusTest/build.gradle | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5f3aa2fd..4c8fcf6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ jdk: android: components: - tools - - build-tools-23.0.2 + - build-tools-25.0.2 - android-10 - extra-android-m2repository diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 53180e6e..23fd53b6 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.2.1' + classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } @@ -29,7 +29,7 @@ apt { } android { - buildToolsVersion '23.0.2' // When updating, don't forget to adjust .travis.yml + buildToolsVersion '25.0.2' // When updating, don't forget to adjust .travis.yml compileSdkVersion 19 sourceSets { diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index a1d04468..b65a4bdd 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.2.1' + classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } @@ -22,13 +22,13 @@ dependencies { androidTestApt project(':EventBusAnnotationProcessor') androidTestCompile project(':EventBus') compile fileTree(dir: 'libs', include: '*.jar') - androidTestCompile 'com.android.support.test:runner:0.4.1' - androidTestCompile 'com.android.support.test:rules:0.4.1' + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test:rules:0.5' } android { - buildToolsVersion '23.0.2' // When updating, don't forget to adjust .travis.yml - compileSdkVersion 19 + buildToolsVersion '25.0.0' // When updating, don't forget to adjust .travis.yml + compileSdkVersion 25 compileOptions { sourceCompatibility = JavaVersion.VERSION_1_7 From 9d96410c6550bba9b9d49983a94b39f287382ff6 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 11:00:20 +0200 Subject: [PATCH 004/128] travis: switch to Java 8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4c8fcf6b..cf7a4bd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: android jdk: - - oraclejdk7 + - oraclejdk8 # http://docs.travis-ci.com/user/languages/android/ android: From 48ad4b924fda081930031bc33d757fe85ef00425 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 11:16:20 +0200 Subject: [PATCH 005/128] travis: added android-25 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cf7a4bd4..96aae900 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ android: - tools - build-tools-25.0.2 - android-10 + - android-25 - extra-android-m2repository before_script: From 60c5d3d0b465cb5708378767e21d01d1485da9e7 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 12:55:44 +0200 Subject: [PATCH 006/128] buildToolsVersion 25.0.2 also for test --- EventBusTest/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index b65a4bdd..d9742aab 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -27,7 +27,7 @@ dependencies { } android { - buildToolsVersion '25.0.0' // When updating, don't forget to adjust .travis.yml + buildToolsVersion '25.0.2' // When updating, don't forget to adjust .travis.yml compileSdkVersion 25 compileOptions { From 18729a7df8959c1edc1c05bad8a0809d58c5c652 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 13:16:41 +0200 Subject: [PATCH 007/128] show test lint problems in 'stdout' - debug an travis issue --- EventBusTest/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index d9742aab..ed6296f2 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -49,6 +49,11 @@ android { testApplicationId "de.greenrobot.event.test" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } + + lintOptions { + // To see problems right away, also nice for Travis CI + textOutput 'stdout' + } } apt { From 16b043a11fc1afd59abba102f20bc2ba826f0cf2 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Apr 2017 13:30:28 +0200 Subject: [PATCH 008/128] Travis only lint error in test: abortOnError false for now --- EventBusTest/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index ed6296f2..34c45681 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -53,6 +53,9 @@ android { lintOptions { // To see problems right away, also nice for Travis CI textOutput 'stdout' + + // TODO FIXME: Travis only error + abortOnError false } } From 435d9b0f6c64ae4761b531046da1c482fadb1436 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 26 May 2017 21:50:15 +0200 Subject: [PATCH 009/128] com.android.tools.build:gradle:2.3.2, buildToolsVersion 25.0.3, Gradle 3.5 --- .travis.yml | 2 +- EventBusPerformance/build.gradle | 4 ++-- EventBusTest/build.gradle | 4 ++-- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 54212 -> 54783 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 96aae900..94fcd6f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ jdk: android: components: - tools - - build-tools-25.0.2 + - build-tools-25.0.3 - android-10 - android-25 - extra-android-m2repository diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 23fd53b6..cf5c647e 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.3.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } @@ -29,7 +29,7 @@ apt { } android { - buildToolsVersion '25.0.2' // When updating, don't forget to adjust .travis.yml + buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml compileSdkVersion 19 sourceSets { diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 34c45681..8751edbb 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.3.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } @@ -27,7 +27,7 @@ dependencies { } android { - buildToolsVersion '25.0.2' // When updating, don't forget to adjust .travis.yml + buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml compileSdkVersion 25 compileOptions { diff --git a/build.gradle b/build.gradle index 958c35ba..2243fd1d 100644 --- a/build.gradle +++ b/build.gradle @@ -7,5 +7,5 @@ if (JavaVersion.current().isJava8Compatible()) { } task wrapper(type: Wrapper) { - gradleVersion = '3.4.1' + gradleVersion = '3.5' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 90ae8dfd9ca83141cd5b1fc8cf52c663bce33bc5..79eb0160bc80b1a4d113f3147ed7755989a9ad29 100644 GIT binary patch delta 6729 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 delta 6082 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 76d36bb3..ee2c6b4d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Apr 10 10:49:50 CEST 2017 +#Fri May 26 21:49:46 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip From 88f3149112096e741cfefeac5e4245228da036e0 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 12 Jun 2017 08:02:33 +0200 Subject: [PATCH 010/128] Simplify add instructions, quick-link to ProGuard docs. --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1f193bd9..0c154d32 100644 --- a/README.md +++ b/README.md @@ -54,18 +54,18 @@ EventBus in 3 steps EventBus.getDefault().post(new MessageEvent()); ``` -**Read the full [getting started guide](http://greenrobot.org/eventbus/documentation/how-to-get-started/).** +Read the full [getting started guide](http://greenrobot.org/eventbus/documentation/how-to-get-started/). Add EventBus to your project ---------------------------- -Please ensure that you are using the latest version by [checking here](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.greenrobot%22%20AND%20a%3A%22eventbus%22) + -Gradle: +Via Gradle: ```gradle compile 'org.greenrobot:eventbus:3.0.0' ``` -Maven: +Via Maven: ```xml org.greenrobot @@ -74,16 +74,18 @@ Maven: ``` -[Or download EventBus from Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.greenrobot%22%20AND%20a%3A%22eventbus%22) +Or download [the latest JAR](https://search.maven.org/remote_content?g=org.greenrobot&a=eventbus&v=LATEST) from Maven Central. Homepage, Documentation, Links ------------------------------ -For more details on EventBus please check [EventBus' website](http://greenrobot.org/eventbus). Here are some direct links you may find useful: +For more details please check the [EventBus website](http://greenrobot.org/eventbus). Here are some direct links you may find useful: [Features](http://greenrobot.org/eventbus/features/) [Documentation](http://greenrobot.org/eventbus/documentation/) +[ProGuard](http://greenrobot.org/eventbus/documentation/proguard) + [Changelog](http://greenrobot.org/eventbus/changelog/) [FAQ](http://greenrobot.org/eventbus/documentation/faq/) From adda90cf11406785487b414433beb43e7d5a17c9 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 19 Jun 2017 07:44:45 +0200 Subject: [PATCH 011/128] Fix empty test suite error for EventBusTest module. - Closes https://github.com/greenrobot/EventBus/issues/439 - Remove outdated instrumentation tags from AndroidManifest.xml to stop overriding build.gradle config. Make sure to remove existing run configurations, sync your project, then right click class/method to run test. --- EventBusTest/AndroidManifest.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/EventBusTest/AndroidManifest.xml b/EventBusTest/AndroidManifest.xml index 22aedee0..03275fde 100644 --- a/EventBusTest/AndroidManifest.xml +++ b/EventBusTest/AndroidManifest.xml @@ -6,15 +6,11 @@ - - \ No newline at end of file From 4fd90e6e399f8166672d19a861236b7f112f5d2d Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 11:17:55 +0100 Subject: [PATCH 012/128] com.android.tools.build:gradle:2.3.3 --- EventBusPerformance/build.gradle | 2 +- EventBusTest/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index cf5c647e..0aab22b0 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 8751edbb..e92f19aa 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } From 2c01ac0225ad31f1c28a274e1f48dd965f78ce44 Mon Sep 17 00:00:00 2001 From: Markus Date: Sun, 22 Feb 2015 14:07:06 +0100 Subject: [PATCH 013/128] prepared Logger, probably too many methods --- EventBus/src/de/greenrobot/event/Logger.java | 239 +++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 EventBus/src/de/greenrobot/event/Logger.java diff --git a/EventBus/src/de/greenrobot/event/Logger.java b/EventBus/src/de/greenrobot/event/Logger.java new file mode 100644 index 00000000..9d7cba85 --- /dev/null +++ b/EventBus/src/de/greenrobot/event/Logger.java @@ -0,0 +1,239 @@ +package de.greenrobot.event; + +import android.annotation.TargetApi; +import android.os.Build; +import android.util.Log; + +import java.util.logging.Level; + +public abstract class Logger { + private static final boolean useAndroidLog; + private static volatile Logger DEFAULT_LOGGER; + + + static { + boolean android = false; + try { + android = Class.forName("android.util.Log") != null; + } catch (ClassNotFoundException e) { + // OK + } + useAndroidLog = android; + } + + + public static synchronized Logger initDefaultLogger(String tag) { + if (DEFAULT_LOGGER != null) { + throw new IllegalStateException("Default logger already set up"); + } + DEFAULT_LOGGER = create(tag); + return DEFAULT_LOGGER; + } + + public static Logger get() { + if (DEFAULT_LOGGER == null) { + throw new IllegalStateException("Default logger must be initialized before"); + } + return DEFAULT_LOGGER; + } + + public static Logger create(String tag) { + if (useAndroidLog) { + return new AndroidLogger(tag); + } else { + return new JavaLogger(tag); + } + } + + + public abstract boolean isLoggable(int level); + + public abstract void v(String msg); + + public abstract void v(String msg, Throwable th); + + public abstract void d(String msg); + + public abstract void d(String msg, Throwable th); + + public abstract void i(String msg); + + public abstract void i(String msg, Throwable th); + + public abstract void w(String msg); + + public abstract void w(String msg, Throwable th); + + public abstract void w(Throwable th); + + public abstract void e(String msg); + + public abstract void e(String msg, Throwable th); + + public abstract void wtf(String msg); + + public abstract void wtf(String msg, Throwable th); + + public static class AndroidLogger extends Logger { + public static final int VERBOSE = 2; + public static final int DEBUG = 3; + public static final int INFO = 4; + public static final int WARN = 5; + public static final int ERROR = 6; + public static final int ASSERT = 7; + + private final String tag; + + public AndroidLogger(String tag) { + this.tag = tag; + } + + public boolean isLoggable(int level) { + return Log.isLoggable(tag, level); + } + + public void v(String msg) { + Log.v(tag, msg); + } + + public void v(String msg, Throwable th) { + Log.v(tag, msg, th); + } + + public void d(String msg) { + Log.d(tag, msg); + } + + public void d(String msg, Throwable th) { + Log.d(tag, msg, th); + } + + public void i(String msg) { + Log.i(tag, msg); + } + + public void i(String msg, Throwable th) { + Log.i(tag, msg, th); + } + + public void w(String msg) { + Log.w(tag, msg); + } + + public void w(String msg, Throwable th) { + Log.w(tag, msg, th); + } + + public void w(Throwable th) { + Log.w(tag, th); + } + + public void e(String msg) { + Log.e(tag, msg); + } + + public void e(String msg, Throwable th) { + Log.e(tag, msg, th); + } + + @TargetApi(Build.VERSION_CODES.FROYO) + @Override + public void wtf(String msg) { + Log.wtf(tag, msg); + } + + @TargetApi(Build.VERSION_CODES.FROYO) + @Override + public void wtf(String msg, Throwable th) { + Log.wtf(tag, msg, th); + } + } + + public static class JavaLogger extends Logger { + private static final Level[] LEVEL_MAP = { + Level.OFF, Level.OFF, Level.OFF, // Unused + Level.FINEST, // VERBOSE = 2 + Level.FINE, //DEBUG = 3 + Level.INFO, // INFO = 4 + Level.WARNING, // WARN = 5 + Level.SEVERE, //ERROR = 6 + Level.SEVERE, //ASSERT = 7 + }; + + java.util.logging.Logger logger = java.util.logging.Logger.getLogger(""); + + public JavaLogger(String tag) { + logger = java.util.logging.Logger.getLogger(tag); + } + + @Override + public boolean isLoggable(int level) { + return logger.isLoggable(LEVEL_MAP[level]); + } + + @Override + public void v(String msg) { + logger.finest(msg); + } + + @Override + public void v(String msg, Throwable th) { + logger.log(Level.FINEST, msg, th); + } + + @Override + public void d(String msg) { + logger.fine(msg); + } + + @Override + public void d(String msg, Throwable th) { + logger.log(Level.FINE, msg, th); + } + + @Override + public void i(String msg) { + logger.info(msg); + } + + @Override + public void i(String msg, Throwable th) { + logger.log(Level.INFO, msg, th); + } + + @Override + public void w(String msg) { + logger.warning(msg); + } + + @Override + public void w(String msg, Throwable th) { + logger.log(Level.WARNING, msg, th); + } + + @Override + public void w(Throwable th) { + logger.log(Level.WARNING, null, th); + } + + @Override + public void e(String msg) { + logger.severe(msg); + } + + @Override + public void e(String msg, Throwable th) { + logger.log(Level.SEVERE, msg, th); + } + + @Override + public void wtf(String msg) { + logger.severe(msg); + } + + @Override + public void wtf(String msg, Throwable th) { + logger.log(Level.SEVERE, msg, th); + } + } +} From 7a0949fcfbc60e37dfc7800baa28e3581ed1624d Mon Sep 17 00:00:00 2001 From: William Ferguson Date: Sun, 31 Jan 2016 00:49:47 +1000 Subject: [PATCH 014/128] Providing mechanisms to allow non Android use of the library. --- .../org/greenrobot/eventbus/AsyncPoster.java | 2 +- .../greenrobot/eventbus/BackgroundPoster.java | 6 +- .../src/org/greenrobot/eventbus/EventBus.java | 35 ++++-- .../greenrobot/eventbus/EventBusBuilder.java | 20 ++++ .../greenrobot/eventbus/HandlerPoster.java | 8 +- .../src/org/greenrobot/eventbus/Poster.java | 32 ++++++ .../org/greenrobot/eventbus/SyncPoster.java | 35 ++++++ .../greenrobot/eventbus/log/AndroidLog.java | 95 ++++++++++++++++ .../org/greenrobot/eventbus/log/EBLog.java | 79 ++++++++++++++ .../greenrobot/eventbus/log/GenericLog.java | 39 +++++++ .../greenrobot/eventbus/log/SystemOutLog.java | 103 ++++++++++++++++++ .../eventbus/util/AndroidMTCalculator.java | 16 +++ .../eventbus/util/AsyncExecutor.java | 8 +- .../util/ExceptionToResourceMapping.java | 8 +- .../eventbus/util/MainThreadCalculator.java | 14 +++ .../eventbus/util/NonAndroidMTCalculator.java | 12 ++ 16 files changed, 482 insertions(+), 30 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/Poster.java create mode 100644 EventBus/src/org/greenrobot/eventbus/SyncPoster.java create mode 100644 EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java create mode 100644 EventBus/src/org/greenrobot/eventbus/log/EBLog.java create mode 100644 EventBus/src/org/greenrobot/eventbus/log/GenericLog.java create mode 100644 EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java create mode 100644 EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java create mode 100644 EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java create mode 100644 EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java diff --git a/EventBus/src/org/greenrobot/eventbus/AsyncPoster.java b/EventBus/src/org/greenrobot/eventbus/AsyncPoster.java index a56f4ebf..90a30d1e 100644 --- a/EventBus/src/org/greenrobot/eventbus/AsyncPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/AsyncPoster.java @@ -21,7 +21,7 @@ * * @author Markus */ -class AsyncPoster implements Runnable { +class AsyncPoster implements Runnable, Poster { private final PendingPostQueue queue; private final EventBus eventBus; diff --git a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java index 2a5319d0..d2e5dcfb 100644 --- a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java @@ -15,14 +15,14 @@ */ package org.greenrobot.eventbus; -import android.util.Log; +import org.greenrobot.eventbus.log.EBLog; /** * Posts events in background. * * @author Markus */ -final class BackgroundPoster implements Runnable { +final class BackgroundPoster implements Runnable, Poster { private final PendingPostQueue queue; private final EventBus eventBus; @@ -64,7 +64,7 @@ public void run() { eventBus.invokeSubscriber(pendingPost); } } catch (InterruptedException e) { - Log.w("Event", Thread.currentThread().getName() + " was interruppted", e); + EBLog.w(Thread.currentThread().getName() + " was interruppted", e); } } finally { executorRunning = false; diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 1cd57e32..ae2b5834 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -15,8 +15,12 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; -import android.util.Log; +import org.greenrobot.eventbus.log.AndroidLog; +import org.greenrobot.eventbus.log.EBLog; +import org.greenrobot.eventbus.log.SystemOutLog; +import org.greenrobot.eventbus.util.AndroidMTCalculator; +import org.greenrobot.eventbus.util.MainThreadCalculator; +import org.greenrobot.eventbus.util.NonAndroidMTCalculator; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -59,11 +63,12 @@ protected PostingThreadState initialValue() { } }; - private final HandlerPoster mainThreadPoster; + private final Poster mainThreadPoster; private final BackgroundPoster backgroundPoster; private final AsyncPoster asyncPoster; private final SubscriberMethodFinder subscriberMethodFinder; private final ExecutorService executorService; + private final MainThreadCalculator mtCalculator; private final boolean throwSubscriberException; private final boolean logSubscriberExceptions; @@ -105,10 +110,15 @@ public EventBus() { } EventBus(EventBusBuilder builder) { + if (builder.logTarget == null) { + EBLog.setLogTarget(builder.nonAndroidEnvironment ? new SystemOutLog() : new AndroidLog(TAG)); + } else { + EBLog.setLogTarget(builder.logTarget); + } subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); - mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10); + mainThreadPoster = (builder.nonAndroidEnvironment ? new SyncPoster(this) : new HandlerPoster(this, 10)); backgroundPoster = new BackgroundPoster(this); asyncPoster = new AsyncPoster(this); indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0; @@ -121,6 +131,7 @@ public EventBus() { throwSubscriberException = builder.throwSubscriberException; eventInheritance = builder.eventInheritance; executorService = builder.executorService; + mtCalculator = (builder.nonAndroidEnvironment ? new NonAndroidMTCalculator() : new AndroidMTCalculator()); } /** @@ -196,7 +207,7 @@ private void checkPostStickyEventToSubscription(Subscription newSubscription, Ob if (stickyEvent != null) { // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state) // --> Strange corner case, which we don't take care of here. - postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper()); + postToSubscription(newSubscription, stickyEvent, mtCalculator.isMainThread()); } } @@ -230,7 +241,7 @@ public synchronized void unregister(Object subscriber) { } typesBySubscriber.remove(subscriber); } else { - Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); + EBLog.w("Subscriber to unregister was not registered before: " + subscriber.getClass()); } } @@ -241,7 +252,7 @@ public void post(Object event) { eventQueue.add(event); if (!postingState.isPosting) { - postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); + postingState.isMainThread = mtCalculator.isMainThread(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); @@ -374,7 +385,7 @@ private void postSingleEvent(Object event, PostingThreadState postingState) thro } if (!subscriptionFound) { if (logNoSubscriberMessages) { - Log.d(TAG, "No subscribers registered for event " + eventClass); + EBLog.d("No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { @@ -494,10 +505,10 @@ private void handleSubscriberException(Subscription subscription, Object event, if (event instanceof SubscriberExceptionEvent) { if (logSubscriberExceptions) { // Don't send another SubscriberExceptionEvent to avoid infinite event recursion, just log - Log.e(TAG, "SubscriberExceptionEvent subscriber " + subscription.subscriber.getClass() + EBLog.e("SubscriberExceptionEvent subscriber " + subscription.subscriber.getClass() + " threw an exception", cause); SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) event; - Log.e(TAG, "Initial event " + exEvent.causingEvent + " caused exception in " + EBLog.e("Initial event " + exEvent.causingEvent + " caused exception in " + exEvent.causingSubscriber, exEvent.throwable); } } else { @@ -505,7 +516,7 @@ private void handleSubscriberException(Subscription subscription, Object event, throw new EventBusException("Invoking subscriber failed", cause); } if (logSubscriberExceptions) { - Log.e(TAG, "Could not dispatch event: " + event.getClass() + " to subscribing class " + EBLog.e("Could not dispatch event: " + event.getClass() + " to subscribing class " + subscription.subscriber.getClass(), cause); } if (sendSubscriberExceptionEvent) { @@ -518,7 +529,7 @@ private void handleSubscriberException(Subscription subscription, Object event, /** For ThreadLocal, much faster to set (and get multiple values). */ final static class PostingThreadState { - final List eventQueue = new ArrayList(); + final List eventQueue = new ArrayList<>(); boolean isPosting; boolean isMainThread; Subscription subscription; diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index e212750e..3a899a21 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -17,6 +17,8 @@ import org.greenrobot.eventbus.meta.SubscriberInfoIndex; +import org.greenrobot.eventbus.log.GenericLog; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -40,6 +42,8 @@ public class EventBusBuilder { ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE; List> skipMethodVerificationForClasses; List subscriberInfoIndexes; + GenericLog logTarget; + boolean nonAndroidEnvironment; EventBusBuilder() { } @@ -137,6 +141,22 @@ public EventBusBuilder addIndex(SubscriberInfoIndex index) { return this; } + /** + * Set a specific log handler for all EventBus logging. + * + * By default all logging is via {@link android.util.Log} but if you want to use EventBus + * outside the Android environment then you will need to provide another log target. + */ + public EventBusBuilder logger(GenericLog logTarget) { + this.logTarget = logTarget; + return this; + } + + public EventBusBuilder nonAndroidEnvironment(boolean nonAndroidEnvironment) { + this.nonAndroidEnvironment = nonAndroidEnvironment; + return this; + } + /** * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be * done only once before the first usage of the default EventBus. diff --git a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java index 3247be53..3596c47a 100644 --- a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java @@ -20,21 +20,21 @@ import android.os.Message; import android.os.SystemClock; -final class HandlerPoster extends Handler { +final class HandlerPoster extends Handler implements Poster { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; private final EventBus eventBus; private boolean handlerActive; - HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { - super(looper); + HandlerPoster(EventBus eventBus, int maxMillisInsideHandleMessage) { + super(Looper.getMainLooper()); this.eventBus = eventBus; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); } - void enqueue(Subscription subscription, Object event) { + public void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { queue.enqueue(pendingPost); diff --git a/EventBus/src/org/greenrobot/eventbus/Poster.java b/EventBus/src/org/greenrobot/eventbus/Poster.java new file mode 100644 index 00000000..3ebe24f4 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/Poster.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 Markus Junginger, greenrobot (http://greenrobot.de) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +/** + * Posts events. + * + * @author William Ferguson + */ +interface Poster { + + /** + * Enqueue an event to be posted for a particular subscription. + * + * @param subscription Subscription which will receive the event. + * @param event Event that will be posted to subscribers. + */ + void enqueue(Subscription subscription, Object event); +} diff --git a/EventBus/src/org/greenrobot/eventbus/SyncPoster.java b/EventBus/src/org/greenrobot/eventbus/SyncPoster.java new file mode 100644 index 00000000..29e5c0cf --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/SyncPoster.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Markus Junginger, greenrobot (http://greenrobot.de) + * + * 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 + * + * 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 org.greenrobot.eventbus; + + +/** + * Posts events in the current Thread. + * + * @author William Ferguson + */ +class SyncPoster implements Poster { + + private final EventBus eventBus; + + SyncPoster(EventBus eventBus) { + this.eventBus = eventBus; + } + + public void enqueue(Subscription subscription, Object event) { + eventBus.invokeSubscriber(subscription, event); + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java b/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java new file mode 100644 index 00000000..c15def5a --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) Xandar IP 2013. + * + * All Rights Reserved + * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent + * of the author, unless otherwise indicated for stand-alone materials. + * + * Contact support@xandar.com.au for copyright requests. + */ + +package org.greenrobot.eventbus.log; + +import android.util.Log; + +/** + * Logs to the Android log. + */ +public final class AndroidLog implements GenericLog { + + private final String tag; + + public AndroidLog(String tag) { + this.tag = tag; + } + + @Override + public void v(String msg) { + Log.v(tag, msg); + } + + @Override + public void v(String msg, Throwable tr) { + Log.v(tag, msg, tr); + } + + @Override + public void d(String msg) { + Log.d(tag, msg); + } + + @Override + public void d(String msg, Throwable tr) { + Log.d(tag, msg, tr); + } + + @Override + public void i(String msg) { + Log.i(tag, msg); + } + + @Override + public void i(String msg, Throwable tr) { + Log.i(tag, msg, tr); + } + + @Override + public void w(String msg) { + Log.w(tag, msg); + } + + @Override + public void w(String msg, Throwable tr) { + Log.w(tag, msg, tr); + } + + @Override + public void w(Throwable tr) { + Log.w(tag, tr); + } + + @Override + public void e(String msg) { + Log.e(tag, msg); + } + + @Override + public void e(String msg, Throwable tr) { + Log.e(tag, msg, tr); + } + + @Override + public void wtf(String msg) { + Log.wtf(tag, msg); + } + + @Override + public void wtf(Throwable tr) { + Log.wtf(tag, tr); + } + + @Override + public void wtf(String msg, Throwable tr) { + Log.wtf(tag, msg, tr); + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/log/EBLog.java b/EventBus/src/org/greenrobot/eventbus/log/EBLog.java new file mode 100644 index 00000000..a321c9e5 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/log/EBLog.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) Xandar IP 2013. + * + * All Rights Reserved + * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent + * of the author, unless otherwise indicated for stand-alone materials. + * + * Contact support@xandar.com.au for copyright requests. + */ + +package org.greenrobot.eventbus.log; + +/** + * Provides a platform neutral logging target for all EVentBus logging.. + */ +public final class EBLog { + + private static GenericLog log; + + public static void setLogTarget(GenericLog logTarget) { + log = logTarget; + } + + public static void v(String msg) { + log.v(msg); + } + + public static void v(String msg, Throwable tr) { + log.v(msg, tr); + } + + public static void d(String msg) { + log.d(msg); + } + + public static void d(String msg, Throwable tr) { + log.d(msg, tr); + } + + public static void i(String msg) { + log.i(msg); + } + + public static void i(String msg, Throwable tr) { + log.i(msg, tr); + } + + public static void w(String msg) { + log.w(msg); + } + + public static void w(String msg, Throwable tr) { + log.w(msg, tr); + } + + public static void w(Throwable tr) { + log.w(tr); + } + + public static void e(String msg) { + log.e(msg); + } + + public static void e(String msg, Throwable tr) { + log.e(msg, tr); + } + + public static void wtf(String msg) { + log.wtf(msg); + } + + public static void wtf(Throwable tr) { + log.wtf(tr); + } + + public static void wtf(String msg, Throwable tr) { + log.wtf(msg, tr); + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java b/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java new file mode 100644 index 00000000..8ad08177 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) Xandar IP 2013. + * + * All Rights Reserved + * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent + * of the author, unless otherwise indicated for stand-alone materials. + * + * Contact support@xandar.com.au for copyright requests. + */ + +package org.greenrobot.eventbus.log; + +/** + * Means of logging regardless of what platform you are on. + * + * @author William Ferguson + */ +public interface GenericLog { + + void v(String msg); + void v(String msg, Throwable tr); + + void d(String msg); + void d(String msg, Throwable tr); + + void i(String msg); + void i(String msg, Throwable tr); + + void w(String msg); + void w(String msg, Throwable tr); + void w(Throwable tr); + + void e(String msg); + void e(String msg, Throwable tr); + + void wtf(String msg); + void wtf(Throwable tr); + void wtf(String msg, Throwable tr); +} diff --git a/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java b/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java new file mode 100644 index 00000000..096af53f --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) Xandar IP 2013. + * + * All Rights Reserved + * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent + * of the author, unless otherwise indicated for stand-alone materials. + * + * Contact support@xandar.com.au for copyright requests. + */ + +package org.greenrobot.eventbus.log; + +/** + * Logs to SystemOut. + * + * @author William Ferguson + */ +public final class SystemOutLog implements GenericLog { + + @Override + public void v(String msg) { + System.out.println("VERBOSE: " + msg); + } + + @Override + public void v(String msg, Throwable tr) { + System.out.println("VERBOSE: " + msg); + System.out.println("VERBOSE: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void d(String msg) { + System.out.println("DEBUG: " + msg); + } + + @Override + public void d(String msg, Throwable tr) { + System.out.println("DEBUG: " + msg); + System.out.println("DEBUG: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void i(String msg) { + System.out.println("INFO: " + msg); + } + + @Override + public void i(String msg, Throwable tr) { + System.out.println("INFO: " + msg); + System.out.println("INFO: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void w(String msg) { + System.out.println("WARN: " + msg); + } + + @Override + public void w(String msg, Throwable tr) { + System.out.println("WARN: " + msg); + System.out.println("WARN: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void w(Throwable tr) { + System.out.println("WARN: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void e(String msg) { + System.out.println("ERROR: " + msg); + } + + @Override + public void e(String msg, Throwable tr) { + System.out.println("ERROR: " + msg); + System.out.println("ERROR: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void wtf(String msg) { + System.out.println("WTF: " + msg); + } + + @Override + public void wtf(Throwable tr) { + System.out.println("WTF: " + tr.getMessage()); + tr.printStackTrace(System.out); + } + + @Override + public void wtf(String msg, Throwable tr) { + System.out.println("WTF: " + msg); + System.out.println("WTF: " + tr.getMessage()); + tr.printStackTrace(System.out); + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java new file mode 100644 index 00000000..23ce5753 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java @@ -0,0 +1,16 @@ +package org.greenrobot.eventbus.util; + +import android.os.Looper; + +/** + * Returns true if the current Thread is the Android Main Looper Thread. + * + * @author William Ferguson + */ +public class AndroidMTCalculator implements MainThreadCalculator { + + @Override + public boolean isMainThread() { + return Looper.getMainLooper() == Looper.myLooper(); + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java index c44c1366..d989b361 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java +++ b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java @@ -15,10 +15,8 @@ */ package org.greenrobot.eventbus.util; -import android.app.Activity; -import android.util.Log; - import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.log.EBLog; import java.lang.reflect.Constructor; import java.util.concurrent.Executor; @@ -59,7 +57,7 @@ public AsyncExecutor build() { return buildForScope(null); } - public AsyncExecutor buildForActivityScope(Activity activity) { + public AsyncExecutor buildForActivityScope(Object activity) { return buildForScope(activity.getClass()); } @@ -119,7 +117,7 @@ public void run() { try { event = failureEventConstructor.newInstance(e); } catch (Exception e1) { - Log.e(EventBus.TAG, "Original exception:", e); + EBLog.e("Original exception:", e); throw new RuntimeException("Could not create failure event", e1); } if (event instanceof HasExecutionScope) { diff --git a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java index 9ab0d006..b334c13c 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java +++ b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java @@ -16,9 +16,7 @@ package org.greenrobot.eventbus.util; -import android.util.Log; - -import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.log.EBLog; import java.util.HashMap; import java.util.Map; @@ -36,7 +34,7 @@ public class ExceptionToResourceMapping { public final Map, Integer> throwableToMsgIdMap; public ExceptionToResourceMapping() { - throwableToMsgIdMap = new HashMap, Integer>(); + throwableToMsgIdMap = new HashMap<>(); } /** Looks at the exception and its causes trying to find an ID. */ @@ -52,7 +50,7 @@ public Integer mapThrowable(final Throwable throwable) { throwableToCheck = throwableToCheck.getCause(); depthToGo--; if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) { - Log.d(EventBus.TAG, "No specific message ressource ID found for " + throwable); + EBLog.d("No specific message resource ID found for " + throwable); // return config.defaultErrorMsgId; return null; } diff --git a/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java new file mode 100644 index 00000000..6feeb21d --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java @@ -0,0 +1,14 @@ +package org.greenrobot.eventbus.util; + +/** + * Determines whether the current Thread is the Android Main Looper Thread. + * + * @author William Ferguson + */ +public interface MainThreadCalculator { + + /** + * @return true if the current Thread is the Android Main Looper Thread. + */ + boolean isMainThread(); +} diff --git a/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java new file mode 100644 index 00000000..2a7897ee --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java @@ -0,0 +1,12 @@ +package org.greenrobot.eventbus.util; + +/** + * Always returns false as the Main Looper Thread only occurs within Android. + */ +public class NonAndroidMTCalculator implements MainThreadCalculator { + + @Override + public boolean isMainThread() { + return false; + } +} From 5b3a8c47eb2f75a8b563ad7abe1aef1d7a349347 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 5 Feb 2016 19:24:14 +0100 Subject: [PATCH 015/128] simplified Logger to use java.util.logging.Level --- EventBus/src/de/greenrobot/event/Logger.java | 213 +++++-------------- 1 file changed, 50 insertions(+), 163 deletions(-) diff --git a/EventBus/src/de/greenrobot/event/Logger.java b/EventBus/src/de/greenrobot/event/Logger.java index 9d7cba85..b2af3d40 100644 --- a/EventBus/src/de/greenrobot/event/Logger.java +++ b/EventBus/src/de/greenrobot/event/Logger.java @@ -1,7 +1,5 @@ package de.greenrobot.event; -import android.annotation.TargetApi; -import android.os.Build; import android.util.Log; import java.util.logging.Level; @@ -45,195 +43,84 @@ public static Logger create(String tag) { } } + public abstract boolean isLoggable(Level level); - public abstract boolean isLoggable(int level); + public abstract void log(Level level, String msg); - public abstract void v(String msg); - - public abstract void v(String msg, Throwable th); - - public abstract void d(String msg); - - public abstract void d(String msg, Throwable th); - - public abstract void i(String msg); - - public abstract void i(String msg, Throwable th); - - public abstract void w(String msg); - - public abstract void w(String msg, Throwable th); - - public abstract void w(Throwable th); - - public abstract void e(String msg); - - public abstract void e(String msg, Throwable th); - - public abstract void wtf(String msg); - - public abstract void wtf(String msg, Throwable th); + public abstract void log(Level level, String msg, Throwable th); public static class AndroidLogger extends Logger { - public static final int VERBOSE = 2; - public static final int DEBUG = 3; - public static final int INFO = 4; - public static final int WARN = 5; - public static final int ERROR = 6; - public static final int ASSERT = 7; - private final String tag; public AndroidLogger(String tag) { this.tag = tag; } - public boolean isLoggable(int level) { - return Log.isLoggable(tag, level); - } - - public void v(String msg) { - Log.v(tag, msg); - } - - public void v(String msg, Throwable th) { - Log.v(tag, msg, th); - } - - public void d(String msg) { - Log.d(tag, msg); - } - - public void d(String msg, Throwable th) { - Log.d(tag, msg, th); - } - - public void i(String msg) { - Log.i(tag, msg); - } - - public void i(String msg, Throwable th) { - Log.i(tag, msg, th); - } - - public void w(String msg) { - Log.w(tag, msg); - } - - public void w(String msg, Throwable th) { - Log.w(tag, msg, th); - } - - public void w(Throwable th) { - Log.w(tag, th); - } - - public void e(String msg) { - Log.e(tag, msg); - } - - public void e(String msg, Throwable th) { - Log.e(tag, msg, th); - } - - @TargetApi(Build.VERSION_CODES.FROYO) - @Override - public void wtf(String msg) { - Log.wtf(tag, msg); + public boolean isLoggable(Level level) { + if (level == Level.OFF) { + return false; + } else { + return Log.isLoggable(tag, mapLevel(level)); + } + } + + public void log(Level level, String msg) { + if (level != Level.OFF) { + Log.println(mapLevel(level), tag, msg); + } + } + + public void log(Level level, String msg, Throwable th) { + if (level != Level.OFF) { + // That's how Log does it internally + Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th)); + } + } + + protected int mapLevel(Level level) { + if (level == Level.OFF) { + return 0; + } else if (level == Level.FINEST || level == Level.FINER) { + return Log.VERBOSE; + } else if (level == Level.FINE || level == Level.CONFIG) { + return Log.DEBUG; + } else if (level == Level.INFO) { + return Log.INFO; + } else if (level == Level.WARNING) { + return Log.WARN; + } else if (level == Level.SEVERE) { + return Log.ERROR; + } else if (level == Level.ALL) { + // Hmm, well.. + return Log.ASSERT; + } else { + throw new IllegalArgumentException("Unexpected level: " + level); + } } - @TargetApi(Build.VERSION_CODES.FROYO) - @Override - public void wtf(String msg, Throwable th) { - Log.wtf(tag, msg, th); - } } public static class JavaLogger extends Logger { - private static final Level[] LEVEL_MAP = { - Level.OFF, Level.OFF, Level.OFF, // Unused - Level.FINEST, // VERBOSE = 2 - Level.FINE, //DEBUG = 3 - Level.INFO, // INFO = 4 - Level.WARNING, // WARN = 5 - Level.SEVERE, //ERROR = 6 - Level.SEVERE, //ASSERT = 7 - }; - - java.util.logging.Logger logger = java.util.logging.Logger.getLogger(""); + protected final java.util.logging.Logger logger; public JavaLogger(String tag) { logger = java.util.logging.Logger.getLogger(tag); } @Override - public boolean isLoggable(int level) { - return logger.isLoggable(LEVEL_MAP[level]); - } - - @Override - public void v(String msg) { - logger.finest(msg); - } - - @Override - public void v(String msg, Throwable th) { - logger.log(Level.FINEST, msg, th); - } - - @Override - public void d(String msg) { - logger.fine(msg); - } - - @Override - public void d(String msg, Throwable th) { - logger.log(Level.FINE, msg, th); - } - - @Override - public void i(String msg) { - logger.info(msg); - } - - @Override - public void i(String msg, Throwable th) { - logger.log(Level.INFO, msg, th); - } - - @Override - public void w(String msg) { - logger.warning(msg); - } - - @Override - public void w(String msg, Throwable th) { - logger.log(Level.WARNING, msg, th); + public boolean isLoggable(Level level) { + return logger.isLoggable(level); } @Override - public void w(Throwable th) { - logger.log(Level.WARNING, null, th); + public void log(Level level, String msg) { + logger.log(level, msg); } @Override - public void e(String msg) { - logger.severe(msg); + public void log(Level level, String msg, Throwable th) { + logger.log(level, msg, th); } - @Override - public void e(String msg, Throwable th) { - logger.log(Level.SEVERE, msg, th); - } - - @Override - public void wtf(String msg) { - logger.severe(msg); - } - - @Override - public void wtf(String msg, Throwable th) { - logger.log(Level.SEVERE, msg, th); - } } } From b034e2c0ecf9e07013a559d1f57c229dc0ea66ff Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 8 Feb 2016 18:19:56 +0100 Subject: [PATCH 016/128] remove DEFAULT_LOGGER, map level based on intValue --- EventBus/src/de/greenrobot/event/Logger.java | 43 +++++--------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/EventBus/src/de/greenrobot/event/Logger.java b/EventBus/src/de/greenrobot/event/Logger.java index b2af3d40..10a11970 100644 --- a/EventBus/src/de/greenrobot/event/Logger.java +++ b/EventBus/src/de/greenrobot/event/Logger.java @@ -6,8 +6,6 @@ public abstract class Logger { private static final boolean useAndroidLog; - private static volatile Logger DEFAULT_LOGGER; - static { boolean android = false; @@ -19,22 +17,6 @@ public abstract class Logger { useAndroidLog = android; } - - public static synchronized Logger initDefaultLogger(String tag) { - if (DEFAULT_LOGGER != null) { - throw new IllegalStateException("Default logger already set up"); - } - DEFAULT_LOGGER = create(tag); - return DEFAULT_LOGGER; - } - - public static Logger get() { - if (DEFAULT_LOGGER == null) { - throw new IllegalStateException("Default logger must be initialized before"); - } - return DEFAULT_LOGGER; - } - public static Logger create(String tag) { if (useAndroidLog) { return new AndroidLogger(tag); @@ -78,26 +60,21 @@ public void log(Level level, String msg, Throwable th) { } protected int mapLevel(Level level) { - if (level == Level.OFF) { - return 0; - } else if (level == Level.FINEST || level == Level.FINER) { - return Log.VERBOSE; - } else if (level == Level.FINE || level == Level.CONFIG) { - return Log.DEBUG; - } else if (level == Level.INFO) { + int value = level.intValue(); + if (value < 800) { // below INFO + if (value < 500) { // below FINE + return Log.VERBOSE; + } else { + return Log.DEBUG; + } + } else if (value < 900) { // below WARNING return Log.INFO; - } else if (level == Level.WARNING) { + } else if (value < 1000) { // below ERROR return Log.WARN; - } else if (level == Level.SEVERE) { - return Log.ERROR; - } else if (level == Level.ALL) { - // Hmm, well.. - return Log.ASSERT; } else { - throw new IllegalArgumentException("Unexpected level: " + level); + return Log.ERROR; } } - } public static class JavaLogger extends Logger { From e4f7ea1d27b691ca0a08434c249483017d9a0cc2 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 15 Feb 2016 19:03:25 +0100 Subject: [PATCH 017/128] SystemOutLogger etc. --- EventBus/src/de/greenrobot/event/Logger.java | 35 +++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/EventBus/src/de/greenrobot/event/Logger.java b/EventBus/src/de/greenrobot/event/Logger.java index 10a11970..897d437b 100644 --- a/EventBus/src/de/greenrobot/event/Logger.java +++ b/EventBus/src/de/greenrobot/event/Logger.java @@ -5,7 +5,7 @@ import java.util.logging.Level; public abstract class Logger { - private static final boolean useAndroidLog; + private static final boolean ANDROID_LOG_AVAILABLE; static { boolean android = false; @@ -14,14 +14,18 @@ public abstract class Logger { } catch (ClassNotFoundException e) { // OK } - useAndroidLog = android; + ANDROID_LOG_AVAILABLE = android; + } + + public static boolean isAndroidLogAvailable() { + return ANDROID_LOG_AVAILABLE; } public static Logger create(String tag) { - if (useAndroidLog) { + if (ANDROID_LOG_AVAILABLE) { return new AndroidLogger(tag); } else { - return new JavaLogger(tag); + return new SystemOutLogger(); } } @@ -91,13 +95,36 @@ public boolean isLoggable(Level level) { @Override public void log(Level level, String msg) { + // TODO Replace logged method with caller method logger.log(level, msg); } @Override public void log(Level level, String msg, Throwable th) { + // TODO Replace logged method with caller method logger.log(level, msg, th); } } + + public static class SystemOutLogger extends Logger { + + @Override + public boolean isLoggable(Level level) { + return true; + } + + @Override + public void log(Level level, String msg) { + System.out.println("[" + level + "] " + msg); + } + + @Override + public void log(Level level, String msg, Throwable th) { + System.out.println("[" + level + "] " + msg); + th.printStackTrace(System.out); + } + + } + } From 06dfe109da0261838f56a82cc407bf581ca83701 Mon Sep 17 00:00:00 2001 From: Markus Date: Thu, 25 Feb 2016 23:58:58 +0100 Subject: [PATCH 018/128] replaced logging with smaller Logger --- .../greenrobot/eventbus/BackgroundPoster.java | 6 +- .../src/org/greenrobot/eventbus/EventBus.java | 28 ++--- .../greenrobot/eventbus/EventBusBuilder.java | 22 ++-- .../greenrobot/eventbus}/Logger.java | 66 ++++------- .../greenrobot/eventbus/log/AndroidLog.java | 95 ---------------- .../org/greenrobot/eventbus/log/EBLog.java | 79 -------------- .../greenrobot/eventbus/log/GenericLog.java | 39 ------- .../greenrobot/eventbus/log/SystemOutLog.java | 103 ------------------ .../eventbus/util/AsyncExecutor.java | 4 +- .../util/ExceptionToResourceMapping.java | 4 +- 10 files changed, 54 insertions(+), 392 deletions(-) rename EventBus/src/{de/greenrobot/event => org/greenrobot/eventbus}/Logger.java (59%) delete mode 100644 EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/log/EBLog.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/log/GenericLog.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java diff --git a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java index d2e5dcfb..624ddf6d 100644 --- a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java @@ -15,11 +15,11 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.log.EBLog; +import java.util.logging.Level; /** * Posts events in background. - * + * * @author Markus */ final class BackgroundPoster implements Runnable, Poster { @@ -64,7 +64,7 @@ public void run() { eventBus.invokeSubscriber(pendingPost); } } catch (InterruptedException e) { - EBLog.w(Thread.currentThread().getName() + " was interruppted", e); + eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e); } } finally { executorRunning = false; diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index ae2b5834..8312a983 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -15,9 +15,6 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.log.AndroidLog; -import org.greenrobot.eventbus.log.EBLog; -import org.greenrobot.eventbus.log.SystemOutLog; import org.greenrobot.eventbus.util.AndroidMTCalculator; import org.greenrobot.eventbus.util.MainThreadCalculator; import org.greenrobot.eventbus.util.NonAndroidMTCalculator; @@ -31,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; +import java.util.logging.Level; /** * EventBus is a central publish/subscribe event system for Android. Events are posted ({@link #post(Object)}) to the @@ -78,6 +76,7 @@ protected PostingThreadState initialValue() { private final boolean eventInheritance; private final int indexCount; + private final Logger logger; /** Convenience singleton for apps using a process-wide EventBus instance. */ public static EventBus getDefault() { @@ -110,11 +109,7 @@ public EventBus() { } EventBus(EventBusBuilder builder) { - if (builder.logTarget == null) { - EBLog.setLogTarget(builder.nonAndroidEnvironment ? new SystemOutLog() : new AndroidLog(TAG)); - } else { - EBLog.setLogTarget(builder.logTarget); - } + logger = builder.initLogger(); subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); @@ -241,7 +236,7 @@ public synchronized void unregister(Object subscriber) { } typesBySubscriber.remove(subscriber); } else { - EBLog.w("Subscriber to unregister was not registered before: " + subscriber.getClass()); + logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } } @@ -385,7 +380,7 @@ private void postSingleEvent(Object event, PostingThreadState postingState) thro } if (!subscriptionFound) { if (logNoSubscriberMessages) { - EBLog.d("No subscribers registered for event " + eventClass); + logger.log(Level.FINE, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { @@ -505,10 +500,10 @@ private void handleSubscriberException(Subscription subscription, Object event, if (event instanceof SubscriberExceptionEvent) { if (logSubscriberExceptions) { // Don't send another SubscriberExceptionEvent to avoid infinite event recursion, just log - EBLog.e("SubscriberExceptionEvent subscriber " + subscription.subscriber.getClass() + logger.log(Level.SEVERE, "SubscriberExceptionEvent subscriber " + subscription.subscriber.getClass() + " threw an exception", cause); SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) event; - EBLog.e("Initial event " + exEvent.causingEvent + " caused exception in " + logger.log(Level.SEVERE, "Initial event " + exEvent.causingEvent + " caused exception in " + exEvent.causingSubscriber, exEvent.throwable); } } else { @@ -516,7 +511,7 @@ private void handleSubscriberException(Subscription subscription, Object event, throw new EventBusException("Invoking subscriber failed", cause); } if (logSubscriberExceptions) { - EBLog.e("Could not dispatch event: " + event.getClass() + " to subscribing class " + logger.log(Level.SEVERE, "Could not dispatch event: " + event.getClass() + " to subscribing class " + subscription.subscriber.getClass(), cause); } if (sendSubscriberExceptionEvent) { @@ -541,6 +536,13 @@ ExecutorService getExecutorService() { return executorService; } + /** + * For internal use only. + */ + public Logger getLogger() { + return logger; + } + // Just an idea: we could provide a callback to post() to be notified, an alternative would be events, of course... /* public */interface PostCallback { void onPostCompleted(List exceptionEvents); diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 3a899a21..b12a7f38 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -17,8 +17,6 @@ import org.greenrobot.eventbus.meta.SubscriberInfoIndex; -import org.greenrobot.eventbus.log.GenericLog; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -42,7 +40,7 @@ public class EventBusBuilder { ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE; List> skipMethodVerificationForClasses; List subscriberInfoIndexes; - GenericLog logTarget; + Logger logger; boolean nonAndroidEnvironment; EventBusBuilder() { @@ -134,7 +132,7 @@ public EventBusBuilder strictMethodVerification(boolean strictMethodVerification /** Adds an index generated by EventBus' annotation preprocessor. */ public EventBusBuilder addIndex(SubscriberInfoIndex index) { - if(subscriberInfoIndexes == null) { + if (subscriberInfoIndexes == null) { subscriberInfoIndexes = new ArrayList<>(); } subscriberInfoIndexes.add(index); @@ -143,18 +141,22 @@ public EventBusBuilder addIndex(SubscriberInfoIndex index) { /** * Set a specific log handler for all EventBus logging. - * + *

* By default all logging is via {@link android.util.Log} but if you want to use EventBus * outside the Android environment then you will need to provide another log target. */ - public EventBusBuilder logger(GenericLog logTarget) { - this.logTarget = logTarget; + public EventBusBuilder logger(Logger logger) { + this.logger = logger; return this; } - public EventBusBuilder nonAndroidEnvironment(boolean nonAndroidEnvironment) { - this.nonAndroidEnvironment = nonAndroidEnvironment; - return this; + Logger initLogger() { + if (logger != null) { + return logger; + } else { + return Logger.AndroidLogger.isAndroidLogAvailable() ? new Logger.AndroidLogger("EventBus") : + new Logger.SystemOutLogger(); + } } /** diff --git a/EventBus/src/de/greenrobot/event/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java similarity index 59% rename from EventBus/src/de/greenrobot/event/Logger.java rename to EventBus/src/org/greenrobot/eventbus/Logger.java index 897d437b..7a1ad232 100644 --- a/EventBus/src/de/greenrobot/event/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -1,55 +1,39 @@ -package de.greenrobot.event; +package org.greenrobot.eventbus; import android.util.Log; import java.util.logging.Level; -public abstract class Logger { - private static final boolean ANDROID_LOG_AVAILABLE; +public interface Logger { - static { - boolean android = false; - try { - android = Class.forName("android.util.Log") != null; - } catch (ClassNotFoundException e) { - // OK - } - ANDROID_LOG_AVAILABLE = android; - } + void log(Level level, String msg); - public static boolean isAndroidLogAvailable() { - return ANDROID_LOG_AVAILABLE; - } + void log(Level level, String msg, Throwable th); - public static Logger create(String tag) { - if (ANDROID_LOG_AVAILABLE) { - return new AndroidLogger(tag); - } else { - return new SystemOutLogger(); - } - } + public static class AndroidLogger implements Logger { + static final boolean ANDROID_LOG_AVAILABLE; - public abstract boolean isLoggable(Level level); + static { + boolean android = false; + try { + android = Class.forName("android.util.Log") != null; + } catch (ClassNotFoundException e) { + // OK + } + ANDROID_LOG_AVAILABLE = android; + } - public abstract void log(Level level, String msg); + public static boolean isAndroidLogAvailable() { + return ANDROID_LOG_AVAILABLE; + } - public abstract void log(Level level, String msg, Throwable th); - public static class AndroidLogger extends Logger { private final String tag; public AndroidLogger(String tag) { this.tag = tag; } - public boolean isLoggable(Level level) { - if (level == Level.OFF) { - return false; - } else { - return Log.isLoggable(tag, mapLevel(level)); - } - } - public void log(Level level, String msg) { if (level != Level.OFF) { Log.println(mapLevel(level), tag, msg); @@ -81,18 +65,13 @@ protected int mapLevel(Level level) { } } - public static class JavaLogger extends Logger { + public static class JavaLogger implements Logger { protected final java.util.logging.Logger logger; public JavaLogger(String tag) { logger = java.util.logging.Logger.getLogger(tag); } - @Override - public boolean isLoggable(Level level) { - return logger.isLoggable(level); - } - @Override public void log(Level level, String msg) { // TODO Replace logged method with caller method @@ -107,12 +86,7 @@ public void log(Level level, String msg, Throwable th) { } - public static class SystemOutLogger extends Logger { - - @Override - public boolean isLoggable(Level level) { - return true; - } + public static class SystemOutLogger implements Logger { @Override public void log(Level level, String msg) { diff --git a/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java b/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java deleted file mode 100644 index c15def5a..00000000 --- a/EventBus/src/org/greenrobot/eventbus/log/AndroidLog.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Xandar IP 2013. - * - * All Rights Reserved - * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent - * of the author, unless otherwise indicated for stand-alone materials. - * - * Contact support@xandar.com.au for copyright requests. - */ - -package org.greenrobot.eventbus.log; - -import android.util.Log; - -/** - * Logs to the Android log. - */ -public final class AndroidLog implements GenericLog { - - private final String tag; - - public AndroidLog(String tag) { - this.tag = tag; - } - - @Override - public void v(String msg) { - Log.v(tag, msg); - } - - @Override - public void v(String msg, Throwable tr) { - Log.v(tag, msg, tr); - } - - @Override - public void d(String msg) { - Log.d(tag, msg); - } - - @Override - public void d(String msg, Throwable tr) { - Log.d(tag, msg, tr); - } - - @Override - public void i(String msg) { - Log.i(tag, msg); - } - - @Override - public void i(String msg, Throwable tr) { - Log.i(tag, msg, tr); - } - - @Override - public void w(String msg) { - Log.w(tag, msg); - } - - @Override - public void w(String msg, Throwable tr) { - Log.w(tag, msg, tr); - } - - @Override - public void w(Throwable tr) { - Log.w(tag, tr); - } - - @Override - public void e(String msg) { - Log.e(tag, msg); - } - - @Override - public void e(String msg, Throwable tr) { - Log.e(tag, msg, tr); - } - - @Override - public void wtf(String msg) { - Log.wtf(tag, msg); - } - - @Override - public void wtf(Throwable tr) { - Log.wtf(tag, tr); - } - - @Override - public void wtf(String msg, Throwable tr) { - Log.wtf(tag, msg, tr); - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/log/EBLog.java b/EventBus/src/org/greenrobot/eventbus/log/EBLog.java deleted file mode 100644 index a321c9e5..00000000 --- a/EventBus/src/org/greenrobot/eventbus/log/EBLog.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) Xandar IP 2013. - * - * All Rights Reserved - * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent - * of the author, unless otherwise indicated for stand-alone materials. - * - * Contact support@xandar.com.au for copyright requests. - */ - -package org.greenrobot.eventbus.log; - -/** - * Provides a platform neutral logging target for all EVentBus logging.. - */ -public final class EBLog { - - private static GenericLog log; - - public static void setLogTarget(GenericLog logTarget) { - log = logTarget; - } - - public static void v(String msg) { - log.v(msg); - } - - public static void v(String msg, Throwable tr) { - log.v(msg, tr); - } - - public static void d(String msg) { - log.d(msg); - } - - public static void d(String msg, Throwable tr) { - log.d(msg, tr); - } - - public static void i(String msg) { - log.i(msg); - } - - public static void i(String msg, Throwable tr) { - log.i(msg, tr); - } - - public static void w(String msg) { - log.w(msg); - } - - public static void w(String msg, Throwable tr) { - log.w(msg, tr); - } - - public static void w(Throwable tr) { - log.w(tr); - } - - public static void e(String msg) { - log.e(msg); - } - - public static void e(String msg, Throwable tr) { - log.e(msg, tr); - } - - public static void wtf(String msg) { - log.wtf(msg); - } - - public static void wtf(Throwable tr) { - log.wtf(tr); - } - - public static void wtf(String msg, Throwable tr) { - log.wtf(msg, tr); - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java b/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java deleted file mode 100644 index 8ad08177..00000000 --- a/EventBus/src/org/greenrobot/eventbus/log/GenericLog.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Xandar IP 2013. - * - * All Rights Reserved - * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent - * of the author, unless otherwise indicated for stand-alone materials. - * - * Contact support@xandar.com.au for copyright requests. - */ - -package org.greenrobot.eventbus.log; - -/** - * Means of logging regardless of what platform you are on. - * - * @author William Ferguson - */ -public interface GenericLog { - - void v(String msg); - void v(String msg, Throwable tr); - - void d(String msg); - void d(String msg, Throwable tr); - - void i(String msg); - void i(String msg, Throwable tr); - - void w(String msg); - void w(String msg, Throwable tr); - void w(Throwable tr); - - void e(String msg); - void e(String msg, Throwable tr); - - void wtf(String msg); - void wtf(Throwable tr); - void wtf(String msg, Throwable tr); -} diff --git a/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java b/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java deleted file mode 100644 index 096af53f..00000000 --- a/EventBus/src/org/greenrobot/eventbus/log/SystemOutLog.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) Xandar IP 2013. - * - * All Rights Reserved - * No part of this application may be reproduced, copied, modified or adapted, without the prior written consent - * of the author, unless otherwise indicated for stand-alone materials. - * - * Contact support@xandar.com.au for copyright requests. - */ - -package org.greenrobot.eventbus.log; - -/** - * Logs to SystemOut. - * - * @author William Ferguson - */ -public final class SystemOutLog implements GenericLog { - - @Override - public void v(String msg) { - System.out.println("VERBOSE: " + msg); - } - - @Override - public void v(String msg, Throwable tr) { - System.out.println("VERBOSE: " + msg); - System.out.println("VERBOSE: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void d(String msg) { - System.out.println("DEBUG: " + msg); - } - - @Override - public void d(String msg, Throwable tr) { - System.out.println("DEBUG: " + msg); - System.out.println("DEBUG: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void i(String msg) { - System.out.println("INFO: " + msg); - } - - @Override - public void i(String msg, Throwable tr) { - System.out.println("INFO: " + msg); - System.out.println("INFO: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void w(String msg) { - System.out.println("WARN: " + msg); - } - - @Override - public void w(String msg, Throwable tr) { - System.out.println("WARN: " + msg); - System.out.println("WARN: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void w(Throwable tr) { - System.out.println("WARN: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void e(String msg) { - System.out.println("ERROR: " + msg); - } - - @Override - public void e(String msg, Throwable tr) { - System.out.println("ERROR: " + msg); - System.out.println("ERROR: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void wtf(String msg) { - System.out.println("WTF: " + msg); - } - - @Override - public void wtf(Throwable tr) { - System.out.println("WTF: " + tr.getMessage()); - tr.printStackTrace(System.out); - } - - @Override - public void wtf(String msg, Throwable tr) { - System.out.println("WTF: " + msg); - System.out.println("WTF: " + tr.getMessage()); - tr.printStackTrace(System.out); - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java index d989b361..ba5f263d 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java +++ b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java @@ -16,11 +16,11 @@ package org.greenrobot.eventbus.util; import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.log.EBLog; import java.lang.reflect.Constructor; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.logging.Level; /** * Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events of any @@ -117,7 +117,7 @@ public void run() { try { event = failureEventConstructor.newInstance(e); } catch (Exception e1) { - EBLog.e("Original exception:", e); + eventBus.getLogger().log(Level.SEVERE, "Original exception:", e); throw new RuntimeException("Could not create failure event", e1); } if (event instanceof HasExecutionScope) { diff --git a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java index b334c13c..a3bb67f3 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java +++ b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java @@ -16,7 +16,7 @@ package org.greenrobot.eventbus.util; -import org.greenrobot.eventbus.log.EBLog; +import android.util.Log; import java.util.HashMap; import java.util.Map; @@ -50,7 +50,7 @@ public Integer mapThrowable(final Throwable throwable) { throwableToCheck = throwableToCheck.getCause(); depthToGo--; if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) { - EBLog.d("No specific message resource ID found for " + throwable); + Log.d("EventBus", "No specific message resource ID found for " + throwable); // return config.defaultErrorMsgId; return null; } From 6fb7b67622c8d51e5085dffac5676adfe27b57ad Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 29 Feb 2016 18:17:06 +0100 Subject: [PATCH 019/128] MainThreadSupport interface as a single place for main thread support --- .../src/org/greenrobot/eventbus/EventBus.java | 28 ++++++++++----- .../greenrobot/eventbus/EventBusBuilder.java | 2 +- .../greenrobot/eventbus/HandlerPoster.java | 6 ++-- .../eventbus/MainThreadSupport.java | 33 +++++++++++++++++ .../org/greenrobot/eventbus/SyncPoster.java | 35 ------------------- .../eventbus/util/AndroidMTCalculator.java | 16 --------- .../eventbus/util/MainThreadCalculator.java | 14 -------- .../eventbus/util/NonAndroidMTCalculator.java | 12 ------- 8 files changed, 57 insertions(+), 89 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/SyncPoster.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 8312a983..2518946b 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -15,9 +15,7 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.util.AndroidMTCalculator; -import org.greenrobot.eventbus.util.MainThreadCalculator; -import org.greenrobot.eventbus.util.NonAndroidMTCalculator; +import android.os.Looper; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -61,12 +59,14 @@ protected PostingThreadState initialValue() { } }; + // @Nullable + private final MainThreadSupport mainThreadSupport; + // @Nullable private final Poster mainThreadPoster; private final BackgroundPoster backgroundPoster; private final AsyncPoster asyncPoster; private final SubscriberMethodFinder subscriberMethodFinder; private final ExecutorService executorService; - private final MainThreadCalculator mtCalculator; private final boolean throwSubscriberException; private final boolean logSubscriberExceptions; @@ -113,7 +113,10 @@ public EventBus() { subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); - mainThreadPoster = (builder.nonAndroidEnvironment ? new SyncPoster(this) : new HandlerPoster(this, 10)); + mainThreadSupport = builder.mainThreadSupport != null ? builder.mainThreadSupport : + Logger.AndroidLogger.isAndroidLogAvailable() ? + new MainThreadSupport.AndroidHandlerMainThreadSupport(Looper.getMainLooper()) : null; + mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; backgroundPoster = new BackgroundPoster(this); asyncPoster = new AsyncPoster(this); indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0; @@ -126,7 +129,6 @@ public EventBus() { throwSubscriberException = builder.throwSubscriberException; eventInheritance = builder.eventInheritance; executorService = builder.executorService; - mtCalculator = (builder.nonAndroidEnvironment ? new NonAndroidMTCalculator() : new AndroidMTCalculator()); } /** @@ -202,10 +204,20 @@ private void checkPostStickyEventToSubscription(Subscription newSubscription, Ob if (stickyEvent != null) { // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state) // --> Strange corner case, which we don't take care of here. - postToSubscription(newSubscription, stickyEvent, mtCalculator.isMainThread()); + postToSubscription(newSubscription, stickyEvent, isMainThread()); } } + /** + * Checks if the current thread is running in the main thread. + * If there is no main thread support (e.g. non-Android), "true" is always returned. In that case MAIN thread + * subscribers are always called in posting thread, and BACKGROUND subscribers are always called from a background + * poster. + */ + private boolean isMainThread() { + return mainThreadSupport != null? mainThreadSupport.isMainThread(): true; + } + public synchronized boolean isRegistered(Object subscriber) { return typesBySubscriber.containsKey(subscriber); } @@ -247,7 +259,7 @@ public void post(Object event) { eventQueue.add(event); if (!postingState.isPosting) { - postingState.isMainThread = mtCalculator.isMainThread(); + postingState.isMainThread = isMainThread(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index b12a7f38..90e53eb0 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -41,7 +41,7 @@ public class EventBusBuilder { List> skipMethodVerificationForClasses; List subscriberInfoIndexes; Logger logger; - boolean nonAndroidEnvironment; + MainThreadSupport mainThreadSupport; EventBusBuilder() { } diff --git a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java index 3596c47a..95309547 100644 --- a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java @@ -20,15 +20,15 @@ import android.os.Message; import android.os.SystemClock; -final class HandlerPoster extends Handler implements Poster { +public class HandlerPoster extends Handler implements Poster { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; private final EventBus eventBus; private boolean handlerActive; - HandlerPoster(EventBus eventBus, int maxMillisInsideHandleMessage) { - super(Looper.getMainLooper()); + protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { + super(looper); this.eventBus = eventBus; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); diff --git a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java new file mode 100644 index 00000000..6c77fde8 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java @@ -0,0 +1,33 @@ +package org.greenrobot.eventbus; + +import android.os.Looper; + +/** + * Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used. + */ +public interface MainThreadSupport { + + boolean isMainThread(); + + Poster createPoster(EventBus eventBus); + + class AndroidHandlerMainThreadSupport implements MainThreadSupport { + + private final Looper looper; + + public AndroidHandlerMainThreadSupport(Looper looper) { + this.looper = looper; + } + + @Override + public boolean isMainThread() { + return looper == Looper.myLooper(); + } + + @Override + public Poster createPoster(EventBus eventBus) { + return new HandlerPoster(eventBus, looper, 10); + } + } + +} diff --git a/EventBus/src/org/greenrobot/eventbus/SyncPoster.java b/EventBus/src/org/greenrobot/eventbus/SyncPoster.java deleted file mode 100644 index 29e5c0cf..00000000 --- a/EventBus/src/org/greenrobot/eventbus/SyncPoster.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 Markus Junginger, greenrobot (http://greenrobot.de) - * - * 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 - * - * 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 org.greenrobot.eventbus; - - -/** - * Posts events in the current Thread. - * - * @author William Ferguson - */ -class SyncPoster implements Poster { - - private final EventBus eventBus; - - SyncPoster(EventBus eventBus) { - this.eventBus = eventBus; - } - - public void enqueue(Subscription subscription, Object event) { - eventBus.invokeSubscriber(subscription, event); - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java deleted file mode 100644 index 23ce5753..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/AndroidMTCalculator.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.greenrobot.eventbus.util; - -import android.os.Looper; - -/** - * Returns true if the current Thread is the Android Main Looper Thread. - * - * @author William Ferguson - */ -public class AndroidMTCalculator implements MainThreadCalculator { - - @Override - public boolean isMainThread() { - return Looper.getMainLooper() == Looper.myLooper(); - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java deleted file mode 100644 index 6feeb21d..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/MainThreadCalculator.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.greenrobot.eventbus.util; - -/** - * Determines whether the current Thread is the Android Main Looper Thread. - * - * @author William Ferguson - */ -public interface MainThreadCalculator { - - /** - * @return true if the current Thread is the Android Main Looper Thread. - */ - boolean isMainThread(); -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java b/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java deleted file mode 100644 index 2a7897ee..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/NonAndroidMTCalculator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.greenrobot.eventbus.util; - -/** - * Always returns false as the Main Looper Thread only occurs within Android. - */ -public class NonAndroidMTCalculator implements MainThreadCalculator { - - @Override - public boolean isMainThread() { - return false; - } -} From 481357cce44f841a6bc4fa5877bb4636e208b2c7 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 29 Feb 2016 20:11:32 +0100 Subject: [PATCH 020/128] update copyright header --- EventBus/src/org/greenrobot/eventbus/Logger.java | 15 +++++++++++++++ .../greenrobot/eventbus/MainThreadSupport.java | 15 +++++++++++++++ EventBus/src/org/greenrobot/eventbus/Poster.java | 8 ++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index 7a1ad232..6609b61b 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; import android.util.Log; diff --git a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java index 6c77fde8..d5655533 100644 --- a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java +++ b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; import android.os.Looper; diff --git a/EventBus/src/org/greenrobot/eventbus/Poster.java b/EventBus/src/org/greenrobot/eventbus/Poster.java index 3ebe24f4..a69a078d 100644 --- a/EventBus/src/org/greenrobot/eventbus/Poster.java +++ b/EventBus/src/org/greenrobot/eventbus/Poster.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Markus Junginger, greenrobot (http://greenrobot.de) + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ /** * Posts events. - * + * * @author William Ferguson */ interface Poster { @@ -25,8 +25,8 @@ interface Poster { /** * Enqueue an event to be posted for a particular subscription. * - * @param subscription Subscription which will receive the event. - * @param event Event that will be posted to subscribers. + * @param subscription Subscription which will receive the event. + * @param event Event that will be posted to subscribers. */ void enqueue(Subscription subscription, Object event); } From 6d9e15d8b17d71666be3a88eac15530b47245663 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 29 Feb 2016 21:45:18 +0100 Subject: [PATCH 021/128] remove AsyncExecutor.buildForActivityScope --- EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java index ba5f263d..9c0433e8 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java +++ b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java @@ -57,10 +57,6 @@ public AsyncExecutor build() { return buildForScope(null); } - public AsyncExecutor buildForActivityScope(Object activity) { - return buildForScope(activity.getClass()); - } - public AsyncExecutor buildForScope(Object executionContext) { if (eventBus == null) { eventBus = EventBus.getDefault(); From 5f62d8bae73fa1f0fb432735f5084914d8690d8e Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 13:17:15 +0100 Subject: [PATCH 022/128] make AbstractEventBusTest independent from Android --- EventBusTest/build.gradle | 1 + .../eventbus/AbstractAndroidEventBusTest.java | 72 +++++++++++++++++++ .../EventBusBackgroundThreadTest.java | 2 +- .../eventbus/EventBusBuilderTest.java | 2 +- .../EventBusCancelEventDeliveryTest.java | 2 +- .../EventBusFallbackToReflectionTest.java | 2 +- .../eventbus/EventBusGenericsTest.java | 2 +- .../EventBusMainThreadRacingTest.java | 2 +- .../eventbus/EventBusMainThreadTest.java | 2 +- .../eventbus/EventBusMethodModifiersTest.java | 2 +- .../eventbus/EventBusMultithreadedTest.java | 2 +- .../EventBusNoSubscriberEventTest.java | 2 +- .../EventBusOrderedSubscriptionsTest.java | 2 +- .../EventBusRegistrationRacingTest.java | 2 +- .../eventbus/EventBusStickyEventTest.java | 2 +- .../EventBusSubscriberExceptionTest.java | 2 +- .../eventbus/EventBusSubscriberLegalTest.java | 2 +- EventBusTestJava/build.gradle | 21 ++++++ .../eventbus/AbstractEventBusTest.java | 41 ++--------- settings.gradle | 1 + 20 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java create mode 100644 EventBusTestJava/build.gradle rename {EventBusTest => EventBusTestJava}/src/org/greenrobot/eventbus/AbstractEventBusTest.java (76%) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index e92f19aa..ff7208e5 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -21,6 +21,7 @@ repositories { dependencies { androidTestApt project(':EventBusAnnotationProcessor') androidTestCompile project(':EventBus') + androidTestCompile project(':EventBusTestJava') compile fileTree(dir: 'libs', include: '*.jar') androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support.test:rules:0.5' diff --git a/EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java b/EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java new file mode 100644 index 00000000..13178206 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +import android.annotation.SuppressLint; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.runner.RunWith; + + +import static org.junit.Assert.assertFalse; + +/** + * @author Markus Junginger, greenrobot + */ +@RunWith(AndroidJUnit4.class) +public abstract class AbstractAndroidEventBusTest extends AbstractEventBusTest { + private EventPostHandler mainPoster; + + public AbstractAndroidEventBusTest() { + this(false); + } + + public AbstractAndroidEventBusTest(boolean collectEventsReceived) { + super(collectEventsReceived); + } + + @Before + public void setUpAndroid() throws Exception { + mainPoster = new EventPostHandler(Looper.getMainLooper()); + assertFalse(Looper.getMainLooper().getThread().equals(Thread.currentThread())); + } + + protected void postInMainThread(Object event) { + mainPoster.post(event); + } + + @SuppressLint("HandlerLeak") + class EventPostHandler extends Handler { + public EventPostHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + eventBus.post(msg.obj); + } + + void post(Object event) { + sendMessage(obtainMessage(0, event)); + } + + } + +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java index 5a57f744..6ccb6025 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java @@ -25,7 +25,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusBackgroundThreadTest extends AbstractEventBusTest { +public class EventBusBackgroundThreadTest extends AbstractAndroidEventBusTest { @Test public void testPostInCurrentThread() throws InterruptedException { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java index 42d919de..4c15ca16 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java @@ -23,7 +23,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusBuilderTest extends AbstractEventBusTest { +public class EventBusBuilderTest extends AbstractAndroidEventBusTest { @Test public void testThrowSubscriberException() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java index 869da70e..d2aa168f 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java @@ -26,7 +26,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusCancelEventDeliveryTest extends AbstractEventBusTest { +public class EventBusCancelEventDeliveryTest extends AbstractAndroidEventBusTest { private Throwable failed; diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java index 4b884ef4..d9fe5c66 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertEquals; -public class EventBusFallbackToReflectionTest extends AbstractEventBusTest { +public class EventBusFallbackToReflectionTest extends AbstractAndroidEventBusTest { private class PrivateEvent { } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusGenericsTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusGenericsTest.java index 59f8a37b..9e4cc0d8 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusGenericsTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusGenericsTest.java @@ -18,7 +18,7 @@ import org.junit.Test; -public class EventBusGenericsTest extends AbstractEventBusTest { +public class EventBusGenericsTest extends AbstractAndroidEventBusTest { public static class GenericEvent { T value; } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java index a598220e..8ed637e8 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java @@ -26,7 +26,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusMainThreadRacingTest extends AbstractEventBusTest { +public class EventBusMainThreadRacingTest extends AbstractAndroidEventBusTest { private static final int ITERATIONS = LONG_TESTS ? 100000 : 1000; diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java index 2195d10f..d20f2c27 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java @@ -29,7 +29,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusMainThreadTest extends AbstractEventBusTest { +public class EventBusMainThreadTest extends AbstractAndroidEventBusTest { private BackgroundPoster backgroundPoster; diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java index e974e73a..2818d85d 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java @@ -25,7 +25,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusMethodModifiersTest extends AbstractEventBusTest { +public class EventBusMethodModifiersTest extends AbstractAndroidEventBusTest { @Test public void testRegisterForEventTypeAndPost() throws InterruptedException { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java index f3e7bd50..f84ee893 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java @@ -30,7 +30,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusMultithreadedTest extends AbstractEventBusTest { +public class EventBusMultithreadedTest extends AbstractAndroidEventBusTest { private static final int COUNT = LONG_TESTS ? 100000 : 1000; diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java index b358f8c3..d666a504 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java @@ -23,7 +23,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusNoSubscriberEventTest extends AbstractEventBusTest { +public class EventBusNoSubscriberEventTest extends AbstractAndroidEventBusTest { @Test public void testNoSubscriberEvent() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java index f6f97201..3acb119a 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java @@ -27,7 +27,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusOrderedSubscriptionsTest extends AbstractEventBusTest { +public class EventBusOrderedSubscriptionsTest extends AbstractAndroidEventBusTest { int lastPrio = Integer.MAX_VALUE; final List registered = new ArrayList(); diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java index 7d09d7ad..295066ca 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java @@ -28,7 +28,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusRegistrationRacingTest extends AbstractEventBusTest { +public class EventBusRegistrationRacingTest extends AbstractAndroidEventBusTest { // On a Nexus 5, bad synchronization always failed on the first iteration or went well completely. // So a high number of iterations do not guarantee a better probability of finding bugs. diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java index ec426745..e1a5a9f2 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java @@ -22,7 +22,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusStickyEventTest extends AbstractEventBusTest { +public class EventBusStickyEventTest extends AbstractAndroidEventBusTest { @Test public void testPostSticky() throws InterruptedException { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java index f0dea680..c16f820e 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java @@ -23,7 +23,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusSubscriberExceptionTest extends AbstractEventBusTest { +public class EventBusSubscriberExceptionTest extends AbstractAndroidEventBusTest { @Test public void testSubscriberExceptionEvent() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java index c362e900..be02c65c 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java @@ -22,7 +22,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusSubscriberLegalTest extends AbstractEventBusTest { +public class EventBusSubscriberLegalTest extends AbstractAndroidEventBusTest { @Test public void testSubscriberLegal() { diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle new file mode 100644 index 00000000..717037a7 --- /dev/null +++ b/EventBusTestJava/build.gradle @@ -0,0 +1,21 @@ +apply plugin: 'java' + +sourceCompatibility = 1.7 + +repositories { + jcenter() +} + +dependencies { + compile project(':EventBus') + compile 'junit:junit:4.12' +} + +sourceSets { + main { + java { + srcDir 'src' + // exclude 'de/greenrobot/event/util/**' + } + } +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/AbstractEventBusTest.java b/EventBusTestJava/src/org/greenrobot/eventbus/AbstractEventBusTest.java similarity index 76% rename from EventBusTest/src/org/greenrobot/eventbus/AbstractEventBusTest.java rename to EventBusTestJava/src/org/greenrobot/eventbus/AbstractEventBusTest.java index 867cada1..dbd20d68 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/AbstractEventBusTest.java +++ b/EventBusTestJava/src/org/greenrobot/eventbus/AbstractEventBusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,7 @@ */ package org.greenrobot.eventbus; -import android.annotation.SuppressLint; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.support.test.runner.AndroidJUnit4; - -import org.greenrobot.eventbus.EventBus; import org.junit.Before; -import org.junit.runner.RunWith; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -31,12 +23,14 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import static org.junit.Assert.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author Markus Junginger, greenrobot */ -@RunWith(AndroidJUnit4.class) public abstract class AbstractEventBusTest { /** Activates long(er) running tests e.g. testing multi-threading more thoroughly. */ protected static final boolean LONG_TESTS = false; @@ -49,8 +43,6 @@ public abstract class AbstractEventBusTest { protected volatile Object lastEvent; protected volatile Thread lastThread; - private EventPostHandler mainPoster; - public AbstractEventBusTest() { this(false); } @@ -67,12 +59,6 @@ public AbstractEventBusTest(boolean collectEventsReceived) { public void setUpBase() throws Exception { EventBus.clearCaches(); eventBus = new EventBus(); - mainPoster = new EventPostHandler(Looper.getMainLooper()); - assertFalse(Looper.getMainLooper().getThread().equals(Thread.currentThread())); - } - - protected void postInMainThread(Object event) { - mainPoster.post(event); } protected void waitForEventCount(int expectedCount, int maxMillis) { @@ -104,23 +90,6 @@ protected void trackEvent(Object event) { eventCount.incrementAndGet(); } - @SuppressLint("HandlerLeak") - class EventPostHandler extends Handler { - public EventPostHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - eventBus.post(msg.obj); - } - - void post(Object event) { - sendMessage(obtainMessage(0, event)); - } - - } - protected void assertEventCount(int expectedEventCount) { assertEquals(expectedEventCount, eventCount.intValue()); } diff --git a/settings.gradle b/settings.gradle index a11c17d8..f78cf550 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,6 @@ include 'EventBus' include 'EventBusAnnotationProcessor' +include 'EventBusTestJava' include 'EventBusTest' include 'EventBusTestSubscriberInJar' include 'EventBusPerformance' From 934786788242c5f54ab87356fdf7cb0b3d8ef345 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:03:52 +0100 Subject: [PATCH 023/128] check main looper to see if we have "good" Android classes (not Stubs etc.) --- .../src/org/greenrobot/eventbus/EventBus.java | 10 ++----- .../greenrobot/eventbus/EventBusBuilder.java | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 2518946b..712b3ff9 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -15,8 +15,6 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; - import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; @@ -109,13 +107,11 @@ public EventBus() { } EventBus(EventBusBuilder builder) { - logger = builder.initLogger(); + logger = builder.getLogger(); subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); - mainThreadSupport = builder.mainThreadSupport != null ? builder.mainThreadSupport : - Logger.AndroidLogger.isAndroidLogAvailable() ? - new MainThreadSupport.AndroidHandlerMainThreadSupport(Looper.getMainLooper()) : null; + mainThreadSupport = builder.getMainThreadSupport(); mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; backgroundPoster = new BackgroundPoster(this); asyncPoster = new AsyncPoster(this); @@ -215,7 +211,7 @@ private void checkPostStickyEventToSubscription(Subscription newSubscription, Ob * poster. */ private boolean isMainThread() { - return mainThreadSupport != null? mainThreadSupport.isMainThread(): true; + return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true; } public synchronized boolean isRegistered(Object subscriber) { diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 90e53eb0..895b57a9 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -15,6 +15,8 @@ */ package org.greenrobot.eventbus; +import android.os.Looper; + import org.greenrobot.eventbus.meta.SubscriberInfoIndex; import java.util.ArrayList; @@ -150,15 +152,39 @@ public EventBusBuilder logger(Logger logger) { return this; } - Logger initLogger() { + Logger getLogger() { if (logger != null) { return logger; } else { - return Logger.AndroidLogger.isAndroidLogAvailable() ? new Logger.AndroidLogger("EventBus") : + // also check main looper to see if we have "good" Android classes (not Stubs etc.) + return Logger.AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null + ? new Logger.AndroidLogger("EventBus") : new Logger.SystemOutLogger(); } } + + MainThreadSupport getMainThreadSupport() { + if (mainThreadSupport != null) { + return mainThreadSupport; + } else if (Logger.AndroidLogger.isAndroidLogAvailable()) { + Object looperOrNull = getAndroidMainLooperOrNull(); + return looperOrNull == null ? null : + new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull); + } else { + return null; + } + } + + Object getAndroidMainLooperOrNull() { + try { + return Looper.getMainLooper(); + } catch (RuntimeException e) { + // Not really a functional Android (e.g. "Stub!" maven dependencies) + return null; + } + } + /** * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be * done only once before the first usage of the default EventBus. From 2cbf0e0d7cb039c48c71e5b77f97c0a943a74146 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:05:55 +0100 Subject: [PATCH 024/128] default dir layout for java tests --- EventBusTestJava/build.gradle | 12 +- .../eventbus/AbstractEventBusTest.java | 0 .../eventbus/EventBusBuilderTest.java | 103 ++++++++++++++++++ 3 files changed, 106 insertions(+), 9 deletions(-) rename EventBusTestJava/src/{ => main/java}/org/greenrobot/eventbus/AbstractEventBusTest.java (100%) create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 717037a7..4b35cfe6 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -7,15 +7,9 @@ repositories { } dependencies { - compile project(':EventBus') + compile(project(':EventBus')) { + exclude group: "com.google.android" // Does not seem to work... + } compile 'junit:junit:4.12' } -sourceSets { - main { - java { - srcDir 'src' - // exclude 'de/greenrobot/event/util/**' - } - } -} diff --git a/EventBusTestJava/src/org/greenrobot/eventbus/AbstractEventBusTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java similarity index 100% rename from EventBusTestJava/src/org/greenrobot/eventbus/AbstractEventBusTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java new file mode 100644 index 00000000..05a60362 --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Markus Junginger, greenrobot + */ +public class EventBusBuilderTest extends AbstractEventBusTest { + + @Test + public void testThrowSubscriberException() { + eventBus = EventBus.builder().throwSubscriberException(true).build(); + eventBus.register(new SubscriberExceptionEventTracker()); + eventBus.register(new ThrowingSubscriber()); + try { + eventBus.post("Foo"); + fail("Should have thrown"); + } catch (EventBusException e) { + // Expected + } + } + + @Test + public void testDoNotSendSubscriberExceptionEvent() { + eventBus = EventBus.builder().logSubscriberExceptions(false).sendSubscriberExceptionEvent(false).build(); + eventBus.register(new SubscriberExceptionEventTracker()); + eventBus.register(new ThrowingSubscriber()); + eventBus.post("Foo"); + assertEventCount(0); + } + + @Test + public void testDoNotSendNoSubscriberEvent() { + eventBus = EventBus.builder().logNoSubscriberMessages(false).sendNoSubscriberEvent(false).build(); + eventBus.register(new NoSubscriberEventTracker()); + eventBus.post("Foo"); + assertEventCount(0); + } + + @Test + public void testInstallDefaultEventBus() { + EventBusBuilder builder = EventBus.builder(); + try { + // Either this should throw when another unit test got the default event bus... + eventBus = builder.installDefaultEventBus(); + Assert.assertEquals(eventBus, EventBus.getDefault()); + + // ...or this should throw + eventBus = builder.installDefaultEventBus(); + fail("Should have thrown"); + } catch (EventBusException e) { + // Expected + } + } + + @Test + public void testEventInheritance() { + eventBus = EventBus.builder().eventInheritance(false).build(); + eventBus.register(new ThrowingSubscriber()); + eventBus.post("Foo"); + } + + public class SubscriberExceptionEventTracker { + @Subscribe + public void onEvent(SubscriberExceptionEvent event) { + trackEvent(event); + } + } + + public class NoSubscriberEventTracker { + @Subscribe + public void onEvent(NoSubscriberEvent event) { + trackEvent(event); + } + } + + public class ThrowingSubscriber { + @Subscribe + public void onEvent(Object event) { + throw new RuntimeException(); + } + } + +} From 6dbbd767bb1fc754f76ba682709a567d9975ddc0 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:06:14 +0100 Subject: [PATCH 025/128] Gradle does not pick up tests in src dir, so help Gradle with a suite --- .../src/test/java/EventBusTestSuite.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 EventBusTestJava/src/test/java/EventBusTestSuite.java diff --git a/EventBusTestJava/src/test/java/EventBusTestSuite.java b/EventBusTestJava/src/test/java/EventBusTestSuite.java new file mode 100644 index 00000000..812b8867 --- /dev/null +++ b/EventBusTestJava/src/test/java/EventBusTestSuite.java @@ -0,0 +1,13 @@ +import org.greenrobot.eventbus.EventBusBuilderTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +// Gradle does not pick up tests in src dir, so help Gradle with a suite +// (Tests are in main src so we can use them for Android too) +@RunWith(Suite.class) +@SuiteClasses({ + EventBusBuilderTest.class +}) +public class EventBusTestSuite { +} From d72244a73fa282fa9046d0003ac28e01799dd257 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:40:03 +0100 Subject: [PATCH 026/128] V3.1.0-SNAPSHOT --- EventBus/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 50637de7..daaa3163 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'idea' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.0.0' +version = '3.1.0-SNAPSHOT' sourceCompatibility = 1.7 def isSnapshot = version.endsWith('-SNAPSHOT') From e9cad5b25083aa97d7951e35bbefb039afba8e6c Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:43:54 +0100 Subject: [PATCH 027/128] compileSdkVersion 25 for perf app --- EventBusPerformance/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 0aab22b0..a76c1899 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -30,7 +30,7 @@ apt { android { buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml - compileSdkVersion 19 + compileSdkVersion 25 sourceSets { main { From 57e214f5b32e9221701ead0f653e2a6bb1eaf492 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 14:47:14 +0100 Subject: [PATCH 028/128] moved EventBusBasicTest to java tests --- .../eventbus/EventBusAndroidActivityTest.java | 71 ++++++++++++ .../eventbus/EventBusBuilderTest.java | 102 ------------------ .../eventbus/AbstractEventBusTest.java | 5 + .../eventbus/EventBusBasicTest.java | 50 ++++----- .../src/test/java/EventBusTestSuite.java | 2 + 5 files changed, 97 insertions(+), 133 deletions(-) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java delete mode 100644 EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusBasicTest.java (87%) diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java new file mode 100644 index 00000000..364a3936 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +import android.app.Activity; +import android.support.test.annotation.UiThreadTest; +import android.support.test.rule.UiThreadTestRule; +import android.util.Log; + +import org.junit.Rule; +import org.junit.Test; + + +import static org.junit.Assert.assertEquals; + +/** + * @author Markus Junginger, greenrobot + */ +// Do not extend from AbstractAndroidEventBusTest, because it asserts test may not be in main thread +public class EventBusAndroidActivityTest extends AbstractEventBusTest { + + public static class WithIndex extends EventBusBasicTest { + @Test + public void dummy() { + } + + } + + @Rule + public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); + + @Test + @UiThreadTest + public void testRegisterAndPost() { + // Use an activity to test real life performance + TestActivity testActivity = new TestActivity(); + String event = "Hello"; + + long start = System.currentTimeMillis(); + eventBus.register(testActivity); + long time = System.currentTimeMillis() - start; + Log.d(EventBus.TAG, "Registered in " + time + "ms"); + + eventBus.post(event); + + assertEquals(event, testActivity.lastStringEvent); + } + + public static class TestActivity extends Activity { + public String lastStringEvent; + + @Subscribe + public void onEvent(String event) { + lastStringEvent = event; + } + } + +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java deleted file mode 100644 index 4c15ca16..00000000 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusBuilderTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) - * - * 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 - * - * 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 org.greenrobot.eventbus; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * @author Markus Junginger, greenrobot - */ -public class EventBusBuilderTest extends AbstractAndroidEventBusTest { - - @Test - public void testThrowSubscriberException() { - eventBus = EventBus.builder().throwSubscriberException(true).build(); - eventBus.register(new SubscriberExceptionEventTracker()); - eventBus.register(new ThrowingSubscriber()); - try { - eventBus.post("Foo"); - fail("Should have thrown"); - } catch (EventBusException e) { - // Expected - } - } - - @Test - public void testDoNotSendSubscriberExceptionEvent() { - eventBus = EventBus.builder().logSubscriberExceptions(false).sendSubscriberExceptionEvent(false).build(); - eventBus.register(new SubscriberExceptionEventTracker()); - eventBus.register(new ThrowingSubscriber()); - eventBus.post("Foo"); - assertEventCount(0); - } - - @Test - public void testDoNotSendNoSubscriberEvent() { - eventBus = EventBus.builder().logNoSubscriberMessages(false).sendNoSubscriberEvent(false).build(); - eventBus.register(new NoSubscriberEventTracker()); - eventBus.post("Foo"); - assertEventCount(0); - } - - @Test - public void testInstallDefaultEventBus() { - EventBusBuilder builder = EventBus.builder(); - try { - // Either this should throw when another unit test got the default event bus... - eventBus = builder.installDefaultEventBus(); - assertEquals(eventBus, EventBus.getDefault()); - - // ...or this should throw - eventBus = builder.installDefaultEventBus(); - fail("Should have thrown"); - } catch (EventBusException e) { - // Expected - } - } - - @Test - public void testEventInheritance() { - eventBus = EventBus.builder().eventInheritance(false).build(); - eventBus.register(new ThrowingSubscriber()); - eventBus.post("Foo"); - } - - public class SubscriberExceptionEventTracker { - @Subscribe - public void onEvent(SubscriberExceptionEvent event) { - trackEvent(event); - } - } - - public class NoSubscriberEventTracker { - @Subscribe - public void onEvent(NoSubscriberEvent event) { - trackEvent(event); - } - } - - public class ThrowingSubscriber { - @Subscribe - public void onEvent(Object event) { - throw new RuntimeException(); - } - } - -} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java index dbd20d68..dc488dce 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java @@ -22,6 +22,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; import static org.junit.Assert.assertEquals; @@ -107,4 +108,8 @@ protected void awaitLatch(CountDownLatch latch, long seconds) { } } + protected void log(String msg) { + eventBus.getLogger().log(Level.FINE, msg); + } + } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusBasicTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java similarity index 87% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusBasicTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java index d6af1eb4..c00b04bd 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusBasicTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,35 +15,28 @@ */ package org.greenrobot.eventbus; -import android.app.Activity; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.util.Log; - -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import static org.junit.Assert.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author Markus Junginger, greenrobot */ -@RunWith(AndroidJUnit4.class) -public class EventBusBasicTest { +@SuppressWarnings({"WeakerAccess", "UnusedParameters", "unused"}) +public class EventBusBasicTest extends AbstractEventBusTest { public static class WithIndex extends EventBusBasicTest { @Test - public void dummy() {} + public void dummy() { + } } - @Rule - public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule(); - - protected EventBus eventBus; private String lastStringEvent; private int countStringEvent; private int countIntEvent; @@ -52,26 +45,20 @@ public void dummy() {} private int countMyEvent; private int countMyEvent2; - @Before - public void setUp() throws Exception { - eventBus = new EventBus(); - } - @Test - @UiThreadTest public void testRegisterAndPost() { // Use an activity to test real life performance - TestActivity testActivity = new TestActivity(); + StringEventSubscriber stringEventSubscriber = new StringEventSubscriber(); String event = "Hello"; long start = System.currentTimeMillis(); - eventBus.register(testActivity); + eventBus.register(stringEventSubscriber); long time = System.currentTimeMillis() - start; - Log.d(EventBus.TAG, "Registered in " + time + "ms"); + log("Registered in " + time + "ms"); eventBus.post(event); - assertEquals(event, testActivity.lastStringEvent); + assertEquals(event, stringEventSubscriber.lastStringEvent); } @Test @@ -90,12 +77,13 @@ public void testUnregisterWithoutRegister() { public void testUnregisterNotLeaking() { int heapMBytes = (int) (Runtime.getRuntime().maxMemory() / (1024L * 1024L)); for (int i = 0; i < heapMBytes * 2; i++) { + @SuppressWarnings("unused") EventBusBasicTest subscriber = new EventBusBasicTest() { byte[] expensiveObject = new byte[1024 * 1024]; }; eventBus.register(subscriber); eventBus.unregister(subscriber); - Log.d("Test", "Iteration " + i + " / max heap: " + heapMBytes); + log("Iteration " + i + " / max heap: " + heapMBytes); } } @@ -142,7 +130,7 @@ public void testPostMultipleTimes() { } // Debug.stopMethodTracing(); long time = System.currentTimeMillis() - start; - Log.d(EventBus.TAG, "Posted " + count + " events in " + time + "ms"); + log("Posted " + count + " events in " + time + "ms"); assertEquals(count, countMyEvent); } @@ -268,7 +256,7 @@ public void onEvent(MyEventExtended event) { countMyEventExtended++; } - public static class TestActivity extends Activity { + public static class StringEventSubscriber { public String lastStringEvent; @Subscribe diff --git a/EventBusTestJava/src/test/java/EventBusTestSuite.java b/EventBusTestJava/src/test/java/EventBusTestSuite.java index 812b8867..ccd20b0a 100644 --- a/EventBusTestJava/src/test/java/EventBusTestSuite.java +++ b/EventBusTestJava/src/test/java/EventBusTestSuite.java @@ -1,3 +1,4 @@ +import org.greenrobot.eventbus.EventBusBasicTest; import org.greenrobot.eventbus.EventBusBuilderTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -7,6 +8,7 @@ // (Tests are in main src so we can use them for Android too) @RunWith(Suite.class) @SuiteClasses({ + EventBusBasicTest.class, EventBusBuilderTest.class }) public class EventBusTestSuite { From a6ab96c329c770cc1f147ac49a6c15f086d74d46 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 15:40:01 +0100 Subject: [PATCH 029/128] eventbus 3.1.0-RC --- EventBus/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index daaa3163..e2167121 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'idea' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.1.0-SNAPSHOT' +version = '3.1.0-RC' sourceCompatibility = 1.7 def isSnapshot = version.endsWith('-SNAPSHOT') From 38b127c8d060c9ff6d88af3c49e12287f7028e7e Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 16 Sep 2017 15:40:56 +0100 Subject: [PATCH 030/128] updated README.md for 3.1.0-RC --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0c154d32..103ac25c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ EventBus ======== -EventBus is a publish/subscribe event bus optimized for Android.
+EventBus is a publish/subscribe event bus for Android and Java.
EventBus... @@ -62,7 +62,7 @@ Add EventBus to your project Via Gradle: ```gradle -compile 'org.greenrobot:eventbus:3.0.0' +compile 'org.greenrobot:eventbus:3.1.0-RC' ``` Via Maven: @@ -70,7 +70,7 @@ Via Maven: org.greenrobot eventbus - 3.0.0 + 3.1.0-RC ``` @@ -94,12 +94,14 @@ How does EventBus compare to other solutions, like Otto from Square? Check this License ------- -Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) +Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org) EventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE). More Open Source by greenrobot ============================== +[__ObjectBox__](https://github.com/objectbox/objectbox-java) is a new superfast object-oriented database for mobile. + [__greenrobot-common__](https://github.com/greenrobot/greenrobot-common) is a set of utility classes and hash functions for Android & Java projects. [__greenDAO__](https://github.com/greenrobot/greenDAO) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. From 0ed611d465b6695c6f85cc58e29c6084f4c2bf3d Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 12:13:45 +0200 Subject: [PATCH 031/128] Add main src dir to test source set so tests are picked up. - By default Gradle (Java plugin) only looks in the test source set for tests. But we need to share them with the Android test module, so they have to be in the main source set. --- EventBusTestJava/build.gradle | 10 ++++++++++ .../src/test/java/EventBusTestSuite.java | 15 --------------- 2 files changed, 10 insertions(+), 15 deletions(-) delete mode 100644 EventBusTestJava/src/test/java/EventBusTestSuite.java diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 4b35cfe6..6171b530 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -6,6 +6,16 @@ repositories { jcenter() } +// we have tests in the main source set so they can be shared with the Android test module +// to make Gradle pick them up, add the dir to the test source set +sourceSets { + test { + java { + srcDirs += ['src/main/java'] + } + } +} + dependencies { compile(project(':EventBus')) { exclude group: "com.google.android" // Does not seem to work... diff --git a/EventBusTestJava/src/test/java/EventBusTestSuite.java b/EventBusTestJava/src/test/java/EventBusTestSuite.java deleted file mode 100644 index ccd20b0a..00000000 --- a/EventBusTestJava/src/test/java/EventBusTestSuite.java +++ /dev/null @@ -1,15 +0,0 @@ -import org.greenrobot.eventbus.EventBusBasicTest; -import org.greenrobot.eventbus.EventBusBuilderTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -// Gradle does not pick up tests in src dir, so help Gradle with a suite -// (Tests are in main src so we can use them for Android too) -@RunWith(Suite.class) -@SuiteClasses({ - EventBusBasicTest.class, - EventBusBuilderTest.class -}) -public class EventBusTestSuite { -} From 85973302e983b48195e9c171872500ebd089d214 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 13:05:24 +0200 Subject: [PATCH 032/128] Move tests not requiring Android API to Java tests. --- EventBusTestJava/build.gradle | 1 + .../libs/EventBusTestSubscriberInJar-3.0.0.jar | Bin 0 -> 2761 bytes .../EventBusFallbackToReflectionTest.java | 2 +- .../eventbus/EventBusGenericsTest.java | 2 +- .../greenrobot/eventbus/EventBusIndexTest.java | 2 +- .../EventBusInheritanceDisabledTest.java | 4 ---- .../eventbus/EventBusInheritanceTest.java | 11 ++++++----- .../eventbus/EventBusNoSubscriberEventTest.java | 2 +- .../EventBusOrderedSubscriptionsTest.java | 8 +++----- .../eventbus/EventBusRegistrationRacingTest.java | 2 +- .../eventbus/EventBusStickyEventTest.java | 2 +- .../EventBusSubscriberExceptionTest.java | 2 +- .../eventbus/EventBusSubscriberInJarTest.java | 9 ++------- .../eventbus/EventBusSubscriberLegalTest.java | 2 +- .../org/greenrobot/eventbus/IntTestEvent.java | 0 15 files changed, 20 insertions(+), 29 deletions(-) create mode 100644 EventBusTestJava/libs/EventBusTestSubscriberInJar-3.0.0.jar rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java (98%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusGenericsTest.java (97%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusIndexTest.java (100%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java (98%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusInheritanceTest.java (97%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java (96%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java (95%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java (97%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusStickyEventTest.java (98%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java (96%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java (84%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java (96%) rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/IntTestEvent.java (100%) diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 6171b530..13013aac 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -17,6 +17,7 @@ sourceSets { } dependencies { + compile fileTree(dir: 'libs', include: '*.jar') compile(project(':EventBus')) { exclude group: "com.google.android" // Does not seem to work... } diff --git a/EventBusTestJava/libs/EventBusTestSubscriberInJar-3.0.0.jar b/EventBusTestJava/libs/EventBusTestSubscriberInJar-3.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..47b80ef0fe4946e43f2fad4cb34f4c2a94833b76 GIT binary patch literal 2761 zcma)83pkVeAD>%jHO`Q^R&v*nNK0tB)C{?dC6r;D6^6Ow-q0k`(O8&EG90-}TGNe1 zuA`I~6-ukWzjPwxRL;An|LN5F*K@w_^ZwrN`#hh|=l4AC_x*jIj}ux%bS(%ZApxqW zM(zgzCCp!dk_2uC8w?VTar1-GW`A&a#R6 zo50}I6Woj&dHHW?)uS0=rRfDQ?wK5X!mk^~LxUgVX&qGuK5EoT`8zt4tPB#57I5@M z)$-cbEh%%%mk>M)USaRR(<3*9^4k4WkrE-IhLdC&s_OWioNMD#p>(#2szF6&OiFpFOE5o3Ktn<3ZeTxqf@KG1P}FU`kY?^F-# z_udzCtb4eiZagJhrYztAKHE3gZcaO=8nbO{5l(H~?V@{t5n-JvYgd=Fww-NtHf~3J zAElhS8qFlK9xaHPS+sur4(iJTP+jvcx(7UA8U>{7qI zWJos_c_^oU_lJJrOgirR&b0Z%3#Csp5DY|LT;mBF165r5=3yHrHO6Qy+BYU6q{Hw% zQ8cEKvHxyZr{gZtgY1wn-B@;ljZsT;zap#tg3f7-VK_y<+NPjKbIgQ_LUnr4ZZMNK zQznP#H^g3`66tTMc&$G5SoH1C2xQ}ALu^d#NZ@Y3w2U#Z(zOn%G-$EU($L1rSg5VK-a^6_(< zYR_LN@Db_>%~NNaocS$Ha*@m^^0y>+KnDHT(L1qImV+`+{ojB1)x9_O|$Wxjssx?QxQU{h`zd`4NNEoz^p=9bHi3Ahq05XI{oq^s4j8 z8JVE8P-5zBGvyF$YgYpoUVF+bH7{TGRG7yk!?GREHp}^akowj! zG&<#!8ihchtH24@`gbSmC@uu|n*WsxUp8xsCp8qwmqOl_5a zo>lPf+>X&#C2vevh5Zv@{p&HwiXxw!%B&sWM%qd2i==!rs<7*(TrvM~Xr8xirk+^+ znnU_?Rgjp?XJVgutkL9>Eq_@)YD~N#21D1%dxW9HmiJ&yi^d>ZmfUbvl#Ly&>)d%<3Yyezm^QyA%t)IO&!I5G_7!o9m)|^Ga%@+2Y2e}% z*H!M|jV+~I@GcVRl+T3<>v)n1m<3Gc-e6q~5nu=_fOykatWZd=3 z4bp1IO0STk6LkuuyI<}yK2(X9eoAdQ(LQ0^B!k!kDI2j(68d)PK5vKGp8-?P2Rs%2 zlc~E#`jY&@3BGv1Q~_uGY^s^(f{)1{rSGoNyNmS zTf?pJc+83BBg-7>S z+y=MJsp}|EsGe{G(F`!6GM*o-dJwwB)#m8pr&@{xz0pwXO7WsNI~FT-wC&bH({=}vx%>gf zZ2z#`tkkUBMhn)$GBmozB#D@BpRzw!5QQO61%fJoyOpTv-U3jm+xvLhJ;%;_* z6V0kn)gv+gZ0}3?4-P@j6uf!G;}R$@QEKbwPla@0h^$=)6?OKlw@hQHh;F)0qC$x~TtjLc82=L1QB@LQI@}FPg zh#*Zcj_|?!Vvu!!^$YE*a3ZL{NB^CC_!;DL@i&eFT7Dw=8H1llJ{O-+0JMC@SNY^; zWPU#RTzqmj&hq!mFG!L;(X4udQNoVg#V2xb>SRY9lzN7WPfGXFxA@7sc+f=2L< csPmd1i~e6*a6*d#6d { T value; } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusIndexTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java similarity index 100% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusIndexTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java index d5acc814..c3923346 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusIndexTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java @@ -26,8 +26,8 @@ public class EventBusIndexTest { private String value; - @Test /** Ensures the index is actually used and no reflection fall-back kicks in. */ + @Test public void testManualIndexWithoutAnnotation() { SubscriberInfoIndex index = new SubscriberInfoIndex() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java similarity index 98% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java index 80638e8b..44109b04 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java @@ -15,18 +15,14 @@ */ package org.greenrobot.eventbus; -import android.support.test.runner.AndroidJUnit4; - import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import static junit.framework.Assert.assertEquals; /** * @author Markus Junginger, greenrobot */ -@RunWith(AndroidJUnit4.class) public class EventBusInheritanceDisabledTest { protected EventBus eventBus; diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java similarity index 97% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java index f9619bed..405037c5 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusInheritanceTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java @@ -15,14 +15,15 @@ */ package org.greenrobot.eventbus; -import junit.framework.TestCase; - +import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * @author Markus Junginger, greenrobot */ -public class EventBusInheritanceTest extends TestCase { +public class EventBusInheritanceTest { protected EventBus eventBus; @@ -32,8 +33,8 @@ public class EventBusInheritanceTest extends TestCase { private int countMyEventInterface; private int countMyEventInterfaceExtended; - protected void setUp() throws Exception { - super.setUp(); + @Before + public void setUp() throws Exception { eventBus = new EventBus(); } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java similarity index 96% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java index d666a504..b358f8c3 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java @@ -23,7 +23,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusNoSubscriberEventTest extends AbstractAndroidEventBusTest { +public class EventBusNoSubscriberEventTest extends AbstractEventBusTest { @Test public void testNoSubscriberEvent() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java similarity index 95% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java index 3acb119a..e8d0d796 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java @@ -15,8 +15,6 @@ */ package org.greenrobot.eventbus; -import android.util.Log; - import org.junit.Test; import java.util.ArrayList; @@ -27,7 +25,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusOrderedSubscriptionsTest extends AbstractAndroidEventBusTest { +public class EventBusOrderedSubscriptionsTest extends AbstractEventBusTest { int lastPrio = Integer.MAX_VALUE; final List registered = new ArrayList(); @@ -137,7 +135,7 @@ protected void handleEvent(int prio, Object event) { } lastPrio = prio; - Log.d(EventBus.TAG, "Subscriber " + prio + " got: " + event); + log("Subscriber " + prio + " got: " + event); trackEvent(event); } @@ -206,7 +204,7 @@ protected void handleEvent(int prio, Object event) { } lastPrio = prio; - Log.d(EventBus.TAG, "Subscriber " + prio + " got: " + event); + log("Subscriber " + prio + " got: " + event); trackEvent(event); } diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java similarity index 97% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java index 295066ca..7d09d7ad 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java @@ -28,7 +28,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusRegistrationRacingTest extends AbstractAndroidEventBusTest { +public class EventBusRegistrationRacingTest extends AbstractEventBusTest { // On a Nexus 5, bad synchronization always failed on the first iteration or went well completely. // So a high number of iterations do not guarantee a better probability of finding bugs. diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java similarity index 98% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java index e1a5a9f2..ec426745 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusStickyEventTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java @@ -22,7 +22,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusStickyEventTest extends AbstractAndroidEventBusTest { +public class EventBusStickyEventTest extends AbstractEventBusTest { @Test public void testPostSticky() throws InterruptedException { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java similarity index 96% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java index c16f820e..f0dea680 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java @@ -23,7 +23,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusSubscriberExceptionTest extends AbstractAndroidEventBusTest { +public class EventBusSubscriberExceptionTest extends AbstractEventBusTest { @Test public void testSubscriberExceptionEvent() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java similarity index 84% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java index 5b013eb9..a553e7bc 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java @@ -16,15 +16,10 @@ package org.greenrobot.eventbus; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.greenrobot.eventbus.EventBus; +import org.junit.Assert; import org.junit.Test; -import org.greenrobot.eventbus.SubscriberInJar; - -public class EventBusSubscriberInJarTest extends TestCase { +public class EventBusSubscriberInJarTest { protected EventBus eventBus = EventBus.builder().build(); @Test diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java similarity index 96% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java index be02c65c..c362e900 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java @@ -22,7 +22,7 @@ /** * @author Markus Junginger, greenrobot */ -public class EventBusSubscriberLegalTest extends AbstractAndroidEventBusTest { +public class EventBusSubscriberLegalTest extends AbstractEventBusTest { @Test public void testSubscriberLegal() { diff --git a/EventBusTest/src/org/greenrobot/eventbus/IntTestEvent.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java similarity index 100% rename from EventBusTest/src/org/greenrobot/eventbus/IntTestEvent.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java From 8ee4073c789ee58a3b4087ac91ac5ee6acdb678c Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 13:11:45 +0200 Subject: [PATCH 033/128] Experimental: generate index for Java tests for use in Android tests. --- .../org/greenrobot/eventbus/indexed/Indexed.java | 7 ++++++- EventBusTestJava/build.gradle | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java b/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java index 1fcda4e3..196038e8 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java +++ b/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java @@ -17,10 +17,15 @@ package org.greenrobot.eventbus.indexed; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.EventBusJavaTestsIndex; import org.greenrobot.eventbus.EventBusTestsIndex; public class Indexed { static EventBus build() { - return EventBus.builder().addIndex(new EventBusTestsIndex()).build(); + // TODO ut: remove index of this module once all tests moved to Java module + return EventBus.builder() + .addIndex(new EventBusTestsIndex()) + .addIndex(new EventBusJavaTestsIndex()) + .build(); } } diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 13013aac..fe0140c8 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -1,4 +1,15 @@ +buildscript { + repositories { + maven { url "https://plugins.gradle.org/m2/" } + } + + dependencies { + classpath "net.ltgt.gradle:gradle-apt-plugin:0.12" + } +} + apply plugin: 'java' +apply plugin: 'net.ltgt.apt-idea' sourceCompatibility = 1.7 @@ -21,6 +32,10 @@ dependencies { compile(project(':EventBus')) { exclude group: "com.google.android" // Does not seem to work... } + apt project(':EventBusAnnotationProcessor') compile 'junit:junit:4.12' } +tasks.withType(JavaCompile) { + options.compilerArgs += [ "-AeventBusIndex=org.greenrobot.eventbus.EventBusJavaTestsIndex" ] +} From 74a37523a1035943519c43ee7a34db2e47b2147f Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 13:37:39 +0200 Subject: [PATCH 034/128] Fix JUnit error: (inline) test classes have to be public. --- .../greenrobot/eventbus/EventBusInheritanceDisabledTest.java | 2 +- .../java/org/greenrobot/eventbus/EventBusInheritanceTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java index 44109b04..97b14497 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java @@ -172,7 +172,7 @@ public void onEvent(MyEvent event) { } } - static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceDisabledTest { + public static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceDisabledTest { } public class StickySubscriber { diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java index 405037c5..089a3220 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java @@ -172,7 +172,7 @@ public void onEvent(MyEvent event) { } } - static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceTest { + public static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceTest { } public class StickySubscriber { From 88f2173a854c275d2b4fd14ed07f0626388a03b0 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 14:14:15 +0200 Subject: [PATCH 035/128] Add note about Java apt plugin. --- EventBusTestJava/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index fe0140c8..19aba56f 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -9,6 +9,7 @@ buildscript { } apply plugin: 'java' +// plugin to make it easier/safer to use EventBus annotation processor apply plugin: 'net.ltgt.apt-idea' sourceCompatibility = 1.7 From e8b7d4e4e647a6894d277c2f4092ccaf7afa2edf Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 14:31:02 +0200 Subject: [PATCH 036/128] Extract Java-only tests from cancel event delivery tests. --- ...ventBusAndroidCancelEventDeliveryTest.java | 41 +++++++++++++++++++ .../EventBusCancelEventDeliveryTest.java | 24 +++-------- 2 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java (86%) diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java new file mode 100644 index 00000000..781ceda2 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.support.test.runner.AndroidJUnit4; +import android.test.UiThreadTest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(AndroidJUnit4.class) +public class EventBusAndroidCancelEventDeliveryTest extends EventBusCancelEventDeliveryTest { + + @UiThreadTest + @Test + public void testCancelInMainThread() { + SubscriberMainThread subscriber = new SubscriberMainThread(); + eventBus.register(subscriber); + eventBus.post("42"); + awaitLatch(subscriber.done, 10); + assertEquals(0, eventCount.intValue()); + assertNotNull(failed); + } + +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java similarity index 86% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java index d2aa168f..aeed8fdd 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java @@ -15,20 +15,17 @@ */ package org.greenrobot.eventbus; -import android.test.UiThreadTest; - import org.junit.Test; import java.util.concurrent.CountDownLatch; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; -/** - * @author Markus Junginger, greenrobot - */ -public class EventBusCancelEventDeliveryTest extends AbstractAndroidEventBusTest { +public class EventBusCancelEventDeliveryTest extends AbstractEventBusTest { - private Throwable failed; + Throwable failed; @Test public void testCancel() { @@ -71,17 +68,6 @@ public void testCancelWrongEvent() { assertNotNull(failed); } - @UiThreadTest - @Test - public void testCancelInMainThread() { - SubscriberMainThread subscriber = new SubscriberMainThread(); - eventBus.register(subscriber); - eventBus.post("42"); - awaitLatch(subscriber.done, 10); - assertEquals(0, eventCount.intValue()); - assertNotNull(failed); - } - public class Subscriber { private final int prio; private final boolean cancel; From a10111767ebd9f6b268c54a8d11551bdeb3d5ef1 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 14:44:35 +0200 Subject: [PATCH 037/128] Support logging exceptions in AbstractEventBusTest. --- .../java/org/greenrobot/eventbus/AbstractEventBusTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java index dc488dce..fbbcf265 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java @@ -112,4 +112,8 @@ protected void log(String msg) { eventBus.getLogger().log(Level.FINE, msg); } + protected void log(String msg, Throwable e) { + eventBus.getLogger().log(Level.FINE, msg, e); + } + } From 794096aa09bb854dae45e662711454f7b1570cc8 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 14:52:45 +0200 Subject: [PATCH 038/128] Extract Java-only tests from multi-threaded tests. --- .../EventBusAndroidMultithreadedTest.java | 100 +++++++++++++++++ .../eventbus/EventBusMultithreadedTest.java | 101 +++--------------- 2 files changed, 114 insertions(+), 87 deletions(-) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java rename {EventBusTest/src => EventBusTestJava/src/main/java}/org/greenrobot/eventbus/EventBusMultithreadedTest.java (65%) diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java new file mode 100644 index 00000000..8be31cc1 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.os.Looper; +import android.support.test.runner.AndroidJUnit4; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +@RunWith(AndroidJUnit4.class) +public class EventBusAndroidMultithreadedTest extends EventBusMultithreadedTest { + + @Test + public void testSubscribeUnSubscribeAndPostMixedEventType() throws InterruptedException { + List threads = new ArrayList(); + + // Debug.startMethodTracing("testSubscribeUnSubscribeAndPostMixedEventType"); + for (int i = 0; i < 5; i++) { + SubscribeUnsubscribeThread thread = new SubscribeUnsubscribeThread(); + thread.start(); + threads.add(thread); + } + // This test takes a bit longer, so just use fraction the regular count + runThreadsMixedEventType(COUNT / 4, 5); + for (SubscribeUnsubscribeThread thread : threads) { + thread.shutdown(); + } + for (SubscribeUnsubscribeThread thread : threads) { + thread.join(); + } + // Debug.stopMethodTracing(); + } + + public class SubscribeUnsubscribeThread extends Thread { + boolean running = true; + + public void shutdown() { + running = false; + } + + @Override + public void run() { + try { + while (running) { + eventBus.register(this); + double random = Math.random(); + if (random > 0.6d) { + Thread.sleep(0, (int) (1000000 * Math.random())); + } else if (random > 0.3d) { + Thread.yield(); + } + eventBus.unregister(this); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEventMainThread(String event) { + assertSame(Looper.getMainLooper(), Looper.myLooper()); + } + + @Subscribe(threadMode = ThreadMode.BACKGROUND) + public void onEventBackgroundThread(Integer event) { + assertNotSame(Looper.getMainLooper(), Looper.myLooper()); + } + + @Subscribe + public void onEvent(Object event) { + assertNotSame(Looper.getMainLooper(), Looper.myLooper()); + } + + @Subscribe(threadMode = ThreadMode.ASYNC) + public void onEventAsync(Object event) { + assertNotSame(Looper.getMainLooper(), Looper.myLooper()); + } + } + +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java similarity index 65% rename from EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java rename to EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java index f84ee893..e1c1576c 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMultithreadedTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java @@ -15,9 +15,6 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; -import android.util.Log; - import org.junit.Test; import java.util.ArrayList; @@ -25,24 +22,21 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; -/** - * @author Markus Junginger, greenrobot - */ -public class EventBusMultithreadedTest extends AbstractAndroidEventBusTest { +public class EventBusMultithreadedTest extends AbstractEventBusTest { - private static final int COUNT = LONG_TESTS ? 100000 : 1000; + static final int COUNT = LONG_TESTS ? 100000 : 1000; - private final AtomicInteger countStringEvent = new AtomicInteger(); - private final AtomicInteger countIntegerEvent = new AtomicInteger(); - private final AtomicInteger countObjectEvent = new AtomicInteger(); - private final AtomicInteger countIntTestEvent = new AtomicInteger(); + final AtomicInteger countStringEvent = new AtomicInteger(); + final AtomicInteger countIntegerEvent = new AtomicInteger(); + final AtomicInteger countObjectEvent = new AtomicInteger(); + final AtomicInteger countIntTestEvent = new AtomicInteger(); - private String lastStringEvent; - private Integer lastIntegerEvent; + String lastStringEvent; + Integer lastIntegerEvent; - private IntTestEvent lastIntTestEvent; + IntTestEvent lastIntTestEvent; @Test public void testPost01Thread() throws InterruptedException { @@ -74,27 +68,6 @@ public void testPostMixedEventType40Threads() throws InterruptedException { runThreadsMixedEventType(40); } - @Test - public void testSubscribeUnSubscribeAndPostMixedEventType() throws InterruptedException { - List threads = new ArrayList(); - - // Debug.startMethodTracing("testSubscribeUnSubscribeAndPostMixedEventType"); - for (int i = 0; i < 5; i++) { - SubscribeUnsubscribeThread thread = new SubscribeUnsubscribeThread(); - thread.start(); - threads.add(thread); - } - // This test takes a bit longer, so just use fraction the regular count - runThreadsMixedEventType(COUNT / 4, 5); - for (SubscribeUnsubscribeThread thread : threads) { - thread.shutdown(); - } - for (SubscribeUnsubscribeThread thread : threads) { - thread.join(); - } - // Debug.stopMethodTracing(); - } - private void runThreadsSingleEventType(int threadCount) throws InterruptedException { int iterations = COUNT / threadCount; eventBus.register(this); @@ -103,7 +76,7 @@ private void runThreadsSingleEventType(int threadCount) throws InterruptedExcept List threads = startThreads(latch, threadCount, iterations, "Hello"); long time = triggerAndWaitForThreads(threads, latch); - Log.d(EventBus.TAG, threadCount + " threads posted " + iterations + " events each in " + time + "ms"); + log(threadCount + " threads posted " + iterations + " events each in " + time + "ms"); waitForEventCount(COUNT * 2, 5000); @@ -117,7 +90,7 @@ private void runThreadsMixedEventType(int threadCount) throws InterruptedExcepti runThreadsMixedEventType(COUNT, threadCount); } - private void runThreadsMixedEventType(int count, int threadCount) throws InterruptedException { + void runThreadsMixedEventType(int count, int threadCount) throws InterruptedException { eventBus.register(this); int eventTypeCount = 3; int iterations = count / threadCount / eventTypeCount; @@ -133,7 +106,7 @@ private void runThreadsMixedEventType(int count, int threadCount) throws Interru threads.addAll(threadsIntTestEvent); long time = triggerAndWaitForThreads(threads, latch); - Log.d(EventBus.TAG, threadCount * eventTypeCount + " mixed threads posted " + iterations + " events each in " + log(threadCount * eventTypeCount + " mixed threads posted " + iterations + " events each in " + time + "ms"); int expectedCountEach = threadCount * iterations; @@ -219,7 +192,7 @@ public void run() { try { startLatch.await(); } catch (InterruptedException e) { - Log.w(EventBus.TAG, "Unexpeced interrupt", e); + log("Unexpected interrupt", e); } for (int i = 0; i < iterations; i++) { @@ -228,50 +201,4 @@ public void run() { } } - public class SubscribeUnsubscribeThread extends Thread { - boolean running = true; - - public void shutdown() { - running = false; - } - - @Override - public void run() { - try { - while (running) { - eventBus.register(this); - double random = Math.random(); - if (random > 0.6d) { - Thread.sleep(0, (int) (1000000 * Math.random())); - } else if (random > 0.3d) { - Thread.yield(); - } - eventBus.unregister(this); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(String event) { - assertSame(Looper.getMainLooper(), Looper.myLooper()); - } - - @Subscribe(threadMode = ThreadMode.BACKGROUND) - public void onEventBackgroundThread(Integer event) { - assertNotSame(Looper.getMainLooper(), Looper.myLooper()); - } - - @Subscribe - public void onEvent(Object event) { - assertNotSame(Looper.getMainLooper(), Looper.myLooper()); - } - - @Subscribe(threadMode = ThreadMode.ASYNC) - public void onEventAsync(Object event) { - assertNotSame(Looper.getMainLooper(), Looper.myLooper()); - } - } - } From 8a192b4c8d04b6c2d48bf2a03a5dfa81a36cbdc2 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 14:53:41 +0200 Subject: [PATCH 039/128] For now keep both Java and Android module index. --- .../eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java | 2 +- .../greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java | 2 +- EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java index 00e38203..b1f316a1 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java +++ b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java @@ -30,6 +30,6 @@ public void overwriteEventBus() throws Exception { @Test public void testIndex() { - assertTrue(eventBus.toString().contains("indexCount=1")); + assertTrue(eventBus.toString().contains("indexCount=2")); } } diff --git a/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java index 4237ce8e..662a70b8 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java +++ b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java @@ -30,6 +30,6 @@ public void overwriteEventBus() throws Exception { @Test public void testIndex() { - assertTrue(eventBus.toString().contains("indexCount=1")); + assertTrue(eventBus.toString().contains("indexCount=2")); } } diff --git a/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java b/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java index 196038e8..4aec1ef6 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java +++ b/EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java @@ -22,7 +22,6 @@ public class Indexed { static EventBus build() { - // TODO ut: remove index of this module once all tests moved to Java module return EventBus.builder() .addIndex(new EventBusTestsIndex()) .addIndex(new EventBusJavaTestsIndex()) From a90093491d652001d1d8c04cfc7a691d9bc468ca Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 15:16:48 +0200 Subject: [PATCH 040/128] Move inner test classes to upper level so Android runner picks them up. --- ...BusInheritanceDisabledSubclassNoMethod.java | 5 +++++ ...ventBusInheritanceDisabledSubclassTest.java | 13 +++++++++++++ .../EventBusInheritanceDisabledTest.java | 18 ++++-------------- ...ventBusInheritanceSubclassNoMethodTest.java | 5 +++++ .../EventBusInheritanceSubclassTest.java | 12 ++++++++++++ .../eventbus/EventBusInheritanceTest.java | 17 +++-------------- 6 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java new file mode 100644 index 00000000..0fcc73cf --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java @@ -0,0 +1,5 @@ +package org.greenrobot.eventbus; + +// Need to use upper class or Android test runner does not pick it up +public class EventBusInheritanceDisabledSubclassNoMethod extends EventBusInheritanceDisabledTest { +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java new file mode 100644 index 00000000..b5a51591 --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java @@ -0,0 +1,13 @@ +package org.greenrobot.eventbus; + +// Need to use upper class or Android test runner does not pick it up +public class EventBusInheritanceDisabledSubclassTest extends EventBusInheritanceDisabledTest { + + int countMyEventOverwritten; + + @Subscribe + public void onEvent(MyEvent event) { + countMyEventOverwritten++; + } + +} \ No newline at end of file diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java index 97b14497..4b026719 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java @@ -90,7 +90,8 @@ public void testEventSuperInterfaceHierarchy() { @Test public void testSubscriberClassHierarchy() { - SubscriberExtended subscriber = new SubscriberExtended(); + EventBusInheritanceDisabledSubclassTest + subscriber = new EventBusInheritanceDisabledSubclassTest(); eventBus.register(subscriber); eventBus.post("Hello"); @@ -110,7 +111,8 @@ public void testSubscriberClassHierarchy() { @Test public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() { - SubscriberExtendedWithoutNewSubscriberMethod subscriber = new SubscriberExtendedWithoutNewSubscriberMethod(); + EventBusInheritanceDisabledSubclassNoMethod + subscriber = new EventBusInheritanceDisabledSubclassNoMethod(); eventBus.register(subscriber); eventBus.post("Hello"); @@ -163,18 +165,6 @@ public static interface MyEventInterfaceExtended extends MyEventInterface { public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended { } - public static class SubscriberExtended extends EventBusInheritanceDisabledTest { - private int countMyEventOverwritten; - - @Subscribe - public void onEvent(MyEvent event) { - countMyEventOverwritten++; - } - } - - public static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceDisabledTest { - } - public class StickySubscriber { @Subscribe(sticky = true) public void onEvent(Object event) { diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java new file mode 100644 index 00000000..a9f6da47 --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java @@ -0,0 +1,5 @@ +package org.greenrobot.eventbus; + +// Need to use upper class or Android test runner does not pick it up +public class EventBusInheritanceSubclassNoMethodTest extends EventBusInheritanceTest { +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java new file mode 100644 index 00000000..3edbe890 --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java @@ -0,0 +1,12 @@ +package org.greenrobot.eventbus; + +// Need to use upper class or Android test runner does not pick it up +public class EventBusInheritanceSubclassTest extends EventBusInheritanceTest { + int countMyEventOverwritten; + + @Subscribe + public void onEvent(MyEvent event) { + countMyEventOverwritten++; + } + +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java index 089a3220..9fd52288 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java @@ -90,7 +90,7 @@ public void testEventSuperInterfaceHierarchy() { @Test public void testSubscriberClassHierarchy() { - SubscriberExtended subscriber = new SubscriberExtended(); + EventBusInheritanceSubclassTest subscriber = new EventBusInheritanceSubclassTest(); eventBus.register(subscriber); eventBus.post("Hello"); @@ -110,7 +110,8 @@ public void testSubscriberClassHierarchy() { @Test public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() { - SubscriberExtendedWithoutNewSubscriberMethod subscriber = new SubscriberExtendedWithoutNewSubscriberMethod(); + EventBusInheritanceSubclassNoMethodTest + subscriber = new EventBusInheritanceSubclassNoMethodTest(); eventBus.register(subscriber); eventBus.post("Hello"); @@ -163,18 +164,6 @@ public static interface MyEventInterfaceExtended extends MyEventInterface { public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended { } - public static class SubscriberExtended extends EventBusInheritanceTest { - private int countMyEventOverwritten; - - @Subscribe - public void onEvent(MyEvent event) { - countMyEventOverwritten++; - } - } - - public static class SubscriberExtendedWithoutNewSubscriberMethod extends EventBusInheritanceTest { - } - public class StickySubscriber { @Subscribe(sticky = true) public void onEvent(Object event) { From a5ef8974110ee4ac8a530ef8447ac455c725ad41 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 18 Sep 2017 15:17:35 +0200 Subject: [PATCH 041/128] Temporarily ignore failing subclass inheritance tests. --- .../eventbus/EventBusInheritanceDisabledSubclassTest.java | 7 +++++++ .../eventbus/EventBusInheritanceSubclassTest.java | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java index b5a51591..6ab86d23 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java @@ -1,5 +1,7 @@ package org.greenrobot.eventbus; +import org.junit.Ignore; + // Need to use upper class or Android test runner does not pick it up public class EventBusInheritanceDisabledSubclassTest extends EventBusInheritanceDisabledTest { @@ -10,4 +12,9 @@ public void onEvent(MyEvent event) { countMyEventOverwritten++; } + @Override + @Ignore + public void testEventClassHierarchy() { + // TODO fix test in super, then remove this + } } \ No newline at end of file diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java index 3edbe890..8b3d4e4d 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java @@ -1,5 +1,7 @@ package org.greenrobot.eventbus; +import org.junit.Ignore; + // Need to use upper class or Android test runner does not pick it up public class EventBusInheritanceSubclassTest extends EventBusInheritanceTest { int countMyEventOverwritten; @@ -9,4 +11,9 @@ public void onEvent(MyEvent event) { countMyEventOverwritten++; } + @Override + @Ignore + public void testEventClassHierarchy() { + // TODO fix test in super, then remove this + } } From 965acb1d01efaac1131ab354cf92e45d5a692afa Mon Sep 17 00:00:00 2001 From: William Ferguson Date: Wed, 11 May 2016 20:36:39 +1000 Subject: [PATCH 042/128] Added ThreadMode.MAIN_ASYNC to allow a subscriber to declare that it wants to be called in the Main UI thread but the events should be queued for delivery in the order in which they are posted. Ie MAIN_ASYNC subscribers never received delivery directly from the poster's thread, even if it is the Main UI thread. --- EventBus/src/org/greenrobot/eventbus/EventBus.java | 3 +++ EventBus/src/org/greenrobot/eventbus/ThreadMode.java | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 712b3ff9..fc558b0b 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -436,6 +436,9 @@ private void postToSubscription(Subscription subscription, Object event, boolean mainThreadPoster.enqueue(subscription, event); } break; + case MAIN_ASYNC: + mainThreadPoster.enqueue(subscription, event); + break; case BACKGROUND: if (isMainThread) { backgroundPoster.enqueue(subscription, event); diff --git a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java index 79d5dc43..72a8e01f 100644 --- a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java +++ b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java @@ -38,6 +38,12 @@ public enum ThreadMode { */ MAIN, + /** + * Event will be queued for delivery and the subscriber will be called in Android's main thread (sometimes referred to as UI thread). + * This ensures that the poster does not block and that the subscriber is called by Android's main thread so can update UI. + */ + MAIN_ASYNC, + /** * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single From b1a0581199238f3162bebeb4869a524c0397cc32 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Sep 2017 08:22:07 +0200 Subject: [PATCH 043/128] Rename new thread mode to MAIN_ORDERED to differentiate from ASYNC. - Update ThreadMode docs: always use subscriber instead of event handler, add differences if not used on Android. --- .../src/org/greenrobot/eventbus/EventBus.java | 2 +- .../org/greenrobot/eventbus/ThreadMode.java | 33 ++++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index fc558b0b..3b0fffeb 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -436,7 +436,7 @@ private void postToSubscription(Subscription subscription, Object event, boolean mainThreadPoster.enqueue(subscription, event); } break; - case MAIN_ASYNC: + case MAIN_ORDERED: mainThreadPoster.enqueue(subscription, event); break; case BACKGROUND: diff --git a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java index 72a8e01f..b8ee7d53 100644 --- a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java +++ b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java @@ -16,7 +16,7 @@ package org.greenrobot.eventbus; /** - * Each event handler method has a thread mode, which determines in which thread the method is to be called by EventBus. + * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus. * EventBus takes care of threading independently from the posting thread. * * @see EventBus#register(Object) @@ -24,40 +24,41 @@ */ public enum ThreadMode { /** - * Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery + * Subscriber will be called directly in the same thread, which is posting the event. This is the default. Event delivery * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for - * simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers + * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread. */ POSTING, /** - * Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is - * the main thread, event handler methods will be called directly. Event handlers using this mode must return - * quickly to avoid blocking the main thread. + * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is + * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event + * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread. + * If not on Android, behaves the same as {@link #POSTING}. */ MAIN, /** - * Event will be queued for delivery and the subscriber will be called in Android's main thread (sometimes referred to as UI thread). - * This ensures that the poster does not block and that the subscriber is called by Android's main thread so can update UI. + * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN}, + * the event will always be queued for delivery. This ensures that the post call is non-blocking. */ - MAIN_ASYNC, + MAIN_ORDERED, /** - * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods + * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single - * background thread, that will deliver all its events sequentially. Event handlers using this mode should try to - * return quickly to avoid blocking the background thread. + * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to + * return quickly to avoid blocking the background thread. If not on Android, always uses a background thread. */ BACKGROUND, /** - * Event handler methods are called in a separate thread. This is always independent from the posting thread and the - * main thread. Posting events never wait for event handler methods using this mode. Event handler methods should + * Subscriber will be called in a separate thread. This is always independent from the posting thread and the + * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number - * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus - * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications. + * of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus + * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications. */ ASYNC } \ No newline at end of file From dfc6198136a5de39e8f59744a45e8353812ef13c Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Sep 2017 09:32:21 +0200 Subject: [PATCH 044/128] Add tests for MAIN vs MAIN_ORDERED behavior. From main thread: create background thread that posts, then post event also. Observe that event posted by main thread is delivered immediately (MAIN) or queued for delivery on main thread (MAIN_ORDERED). --- .../eventbus/EventBusAndroidOrderTest.java | 91 +++++++++++++++++++ .../eventbus/EventBusMainThreadTest.java | 70 +------------- .../eventbus/TestBackgroundPoster.java | 70 ++++++++++++++ 3 files changed, 163 insertions(+), 68 deletions(-) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java create mode 100644 EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java new file mode 100644 index 00000000..ff348e1d --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java @@ -0,0 +1,91 @@ +package org.greenrobot.eventbus; + +import android.os.Handler; +import android.os.Looper; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +import static org.junit.Assert.assertEquals; + +public class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest { + + private TestBackgroundPoster backgroundPoster; + private Handler handler; + + @Before + public void setUp() throws Exception { + handler = new Handler(Looper.getMainLooper()); + backgroundPoster = new TestBackgroundPoster(eventBus); + backgroundPoster.start(); + } + + @After + public void tearDown() throws Exception { + backgroundPoster.shutdown(); + backgroundPoster.join(); + } + + @Test + public void backgroundAndMainUnordered() { + eventBus.register(this); + + handler.post(new Runnable() { + @Override + public void run() { + // post from non-main thread + backgroundPoster.post("non-main"); + // post from main thread + eventBus.post("main"); + } + }); + + waitForEventCount(2, 1000); + + // observe that event from *main* thread is posted FIRST + // NOT in posting order + assertEquals("non-main", lastEvent); + } + + @Test + public void backgroundAndMainOrdered() { + eventBus.register(this); + + handler.post(new Runnable() { + @Override + public void run() { + // post from non-main thread + backgroundPoster.post(new OrderedEvent("non-main")); + // post from main thread + eventBus.post(new OrderedEvent("main")); + } + }); + + waitForEventCount(2, 1000); + + // observe that event from *main* thread is posted LAST + // IN posting order + assertEquals("main", ((OrderedEvent) lastEvent).thread); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(String event) { + trackEvent(event); + } + + @Subscribe(threadMode = ThreadMode.MAIN_ORDERED) + public void onEvent(OrderedEvent event) { + trackEvent(event); + } + + static class OrderedEvent { + String thread; + + OrderedEvent(String thread) { + this.thread = thread; + } + } + +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java index d20f2c27..953edb6c 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java @@ -21,8 +21,6 @@ import org.junit.Before; import org.junit.Test; -import java.util.ArrayList; -import java.util.List; import static org.junit.Assert.assertEquals; @@ -31,11 +29,11 @@ */ public class EventBusMainThreadTest extends AbstractAndroidEventBusTest { - private BackgroundPoster backgroundPoster; + private TestBackgroundPoster backgroundPoster; @Before public void setUp() throws Exception { - backgroundPoster = new BackgroundPoster(); + backgroundPoster = new TestBackgroundPoster(eventBus); backgroundPoster.start(); } @@ -69,68 +67,4 @@ public void onEventMainThread(String event) { trackEvent(event); } - class BackgroundPoster extends Thread { - volatile boolean running = true; - private final List eventQ = new ArrayList(); - private final List eventsDone = new ArrayList(); - - public BackgroundPoster() { - super("BackgroundPoster"); - } - - @Override - public void run() { - while (running) { - Object event = pollEvent(); - if (event != null) { - eventBus.post(event); - synchronized (eventsDone) { - eventsDone.add(event); - eventsDone.notifyAll(); - } - } - } - } - - private synchronized Object pollEvent() { - Object event = null; - synchronized (eventQ) { - if (eventQ.isEmpty()) { - try { - eventQ.wait(1000); - } catch (InterruptedException e) { - } - } - if(!eventQ.isEmpty()) { - event = eventQ.remove(0); - } - } - return event; - } - - void shutdown() { - running = false; - synchronized (eventQ) { - eventQ.notifyAll(); - } - } - - void post(Object event) { - synchronized (eventQ) { - eventQ.add(event); - eventQ.notifyAll(); - } - synchronized (eventsDone) { - while (!eventsDone.remove(event)) { - try { - eventsDone.wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - } - - } - } diff --git a/EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java b/EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java new file mode 100644 index 00000000..a40eefd9 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java @@ -0,0 +1,70 @@ +package org.greenrobot.eventbus; + +import java.util.ArrayList; +import java.util.List; + +public class TestBackgroundPoster extends Thread { + private final EventBus eventBus; + volatile boolean running = true; + private final List eventQ = new ArrayList<>(); + private final List eventsDone = new ArrayList<>(); + + TestBackgroundPoster(EventBus eventBus) { + super("BackgroundPoster"); + this.eventBus = eventBus; + } + + @Override + public void run() { + while (running) { + Object event = pollEvent(); + if (event != null) { + eventBus.post(event); + synchronized (eventsDone) { + eventsDone.add(event); + eventsDone.notifyAll(); + } + } + } + } + + private synchronized Object pollEvent() { + Object event = null; + synchronized (eventQ) { + if (eventQ.isEmpty()) { + try { + eventQ.wait(1000); + } catch (InterruptedException ignored) { + } + } + if(!eventQ.isEmpty()) { + event = eventQ.remove(0); + } + } + return event; + } + + void shutdown() { + running = false; + synchronized (eventQ) { + eventQ.notifyAll(); + } + } + + void post(Object event) { + synchronized (eventQ) { + eventQ.add(event); + eventQ.notifyAll(); + } + synchronized (eventsDone) { + while (!eventsDone.remove(event)) { + try { + eventsDone.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + } + +} From 618a4f17f13751539c0879ca79d7f534631fdd99 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Sep 2017 10:33:14 +0200 Subject: [PATCH 045/128] Fix regression: test fails if poster set-up out of method. Not sure why, but event is not received if background poster is set up using field. Setting up inside test method works fine. Also works fine in EventBusAndroidOrderTest. --- .../eventbus/EventBusMainThreadTest.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java index 953edb6c..34c29ee6 100644 --- a/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java +++ b/EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java @@ -17,8 +17,6 @@ import android.os.Looper; -import org.junit.After; -import org.junit.Before; import org.junit.Test; @@ -29,20 +27,6 @@ */ public class EventBusMainThreadTest extends AbstractAndroidEventBusTest { - private TestBackgroundPoster backgroundPoster; - - @Before - public void setUp() throws Exception { - backgroundPoster = new TestBackgroundPoster(eventBus); - backgroundPoster.start(); - } - - @After - public void tearDown() throws Exception { - backgroundPoster.shutdown(); - backgroundPoster.join(); - } - @Test public void testPost() throws InterruptedException { eventBus.register(this); @@ -55,11 +39,17 @@ public void testPost() throws InterruptedException { @Test public void testPostInBackgroundThread() throws InterruptedException { + TestBackgroundPoster backgroundPoster = new TestBackgroundPoster(eventBus); + backgroundPoster.start(); + eventBus.register(this); backgroundPoster.post("Hello"); waitForEventCount(1, 1000); assertEquals("Hello", lastEvent); assertEquals(Looper.getMainLooper().getThread(), lastThread); + + backgroundPoster.shutdown(); + backgroundPoster.join(); } @Subscribe(threadMode = ThreadMode.MAIN) From 19c6edb2ce5c1e8ed995423ad8ab34af37e1f057 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Sep 2017 11:04:09 +0200 Subject: [PATCH 046/128] Use same targetSdkVersion if running Android tests with Gradle. - Define min and target SDK, version in Gradle config. - Ignore manifest warnings. --- EventBusTest/AndroidManifest.xml | 10 ++++------ EventBusTest/build.gradle | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/EventBusTest/AndroidManifest.xml b/EventBusTest/AndroidManifest.xml index 03275fde..657ad878 100644 --- a/EventBusTest/AndroidManifest.xml +++ b/EventBusTest/AndroidManifest.xml @@ -1,16 +1,14 @@ - - + xmlns:tools="http://schemas.android.com/tools" + package="org.greenrobot.eventbus"> + android:label="EventBus Test" + tools:ignore="GoogleAppIndexingWarning,MissingApplicationIcon"> \ No newline at end of file diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index ff7208e5..1a413744 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -47,6 +47,11 @@ android { } defaultConfig { + minSdkVersion 8 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + testApplicationId "de.greenrobot.event.test" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } From 0be66fb1b12c480a3247992febe0a9ea52a193c8 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Sep 2017 11:11:37 +0200 Subject: [PATCH 047/128] Do not crash if using MAIN_ORDERED on non-Android. Temporarily just directly invoke the subscriber if no main thread poster is available. Technically this breaks the promised decoupling of poster and subscriber. --- EventBus/src/org/greenrobot/eventbus/EventBus.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 3b0fffeb..247cbb27 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -437,7 +437,12 @@ private void postToSubscription(Subscription subscription, Object event, boolean } break; case MAIN_ORDERED: - mainThreadPoster.enqueue(subscription, event); + if (mainThreadPoster != null) { + mainThreadPoster.enqueue(subscription, event); + } else { + // temporary: technically not correct as poster not decoupled from subscriber + invokeSubscriber(subscription, event); + } break; case BACKGROUND: if (isMainThread) { From 7f5e0cec0a7c021af9a9feb513fba14b1e0855a4 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 17 Oct 2017 10:56:56 +0200 Subject: [PATCH 048/128] Use annotationProcessor instead of android-apt. --- EventBusPerformance/build.gradle | 17 ++++++++--------- EventBusTest/build.gradle | 19 +++++++------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index a76c1899..99b54771 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -5,12 +5,10 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.3.3' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } apply plugin: 'com.android.application' -apply plugin: 'com.neenbedankt.android-apt' repositories { jcenter() @@ -18,16 +16,10 @@ repositories { dependencies { compile project(':EventBus') - apt project(':EventBusAnnotationProcessor') + annotationProcessor project(':EventBusAnnotationProcessor') compile 'com.squareup:otto:1.3.8' } -apt { - arguments { - eventBusIndex "org.greenrobot.eventbusperf.MyEventBusIndex" - } -} - android { buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml compileSdkVersion 25 @@ -40,4 +32,11 @@ android { } } + defaultConfig { + javaCompileOptions { + annotationProcessorOptions { + arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex'] + } + } + } } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 1a413744..e631ce3f 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -5,23 +5,19 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.3.3' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } apply plugin: 'com.android.application' -apply plugin: 'com.neenbedankt.android-apt' - -sourceCompatibility = 1.7 repositories { jcenter() } dependencies { - androidTestApt project(':EventBusAnnotationProcessor') androidTestCompile project(':EventBus') androidTestCompile project(':EventBusTestJava') + androidTestAnnotationProcessor project(':EventBusAnnotationProcessor') compile fileTree(dir: 'libs', include: '*.jar') androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support.test:rules:0.5' @@ -54,6 +50,12 @@ android { testApplicationId "de.greenrobot.event.test" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + javaCompileOptions { + annotationProcessorOptions { + arguments = [ eventBusIndex : 'org.greenrobot.eventbus.EventBusTestsIndex' ] + } + } } lintOptions { @@ -64,10 +66,3 @@ android { abortOnError false } } - -apt { - arguments { - eventBusIndex "org.greenrobot.eventbus.EventBusTestsIndex" - } -} - From e6d912b0614b453e8cb4474e4498b1ddc25746be Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 17 Oct 2017 11:01:44 +0200 Subject: [PATCH 049/128] Gradle 4.1 - Fixes issues with dependencies not getting recognized by Android Studio. --- build.gradle | 3 ++- gradle/wrapper/gradle-wrapper.jar | Bin 54783 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- gradlew | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 2243fd1d..fc18b763 100644 --- a/build.gradle +++ b/build.gradle @@ -7,5 +7,6 @@ if (JavaVersion.current().isJava8Compatible()) { } task wrapper(type: Wrapper) { - gradleVersion = '3.5' + gradleVersion = '4.1' + distributionType = org.gradle.api.tasks.wrapper.Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 79eb0160bc80b1a4d113f3147ed7755989a9ad29..7a3265ee94c0ab25cf079ac8ccdf87f41d455d42 100644 GIT binary patch delta 17061 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 Date: Tue, 17 Oct 2017 11:10:56 +0200 Subject: [PATCH 050/128] EventBusTest: Update testing support library to 1.0.1. - Requires minSdk 9 (was 8), Google repo. --- EventBusTest/build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index e631ce3f..068c640a 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -12,6 +12,7 @@ apply plugin: 'com.android.application' repositories { jcenter() + google() } dependencies { @@ -19,8 +20,8 @@ dependencies { androidTestCompile project(':EventBusTestJava') androidTestAnnotationProcessor project(':EventBusAnnotationProcessor') compile fileTree(dir: 'libs', include: '*.jar') - androidTestCompile 'com.android.support.test:runner:0.5' - androidTestCompile 'com.android.support.test:rules:0.5' + androidTestCompile 'com.android.support.test:runner:1.0.1' + androidTestCompile 'com.android.support.test:rules:1.0.1' } android { @@ -43,7 +44,7 @@ android { } defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 25 versionCode 1 versionName "1.0" From fb0e64c249dc97a3820daa894a44f84a7d4a8cd4 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 6 Nov 2017 11:27:11 +0100 Subject: [PATCH 051/128] README.md: updated links, added survey link --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 103ac25c..fa176e78 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +Hey, do have a minute for a [quick survey](https://docs.google.com/forms/d/e/1FAIpQLSePA8NqA9Jlbvh28xcFVbmIGUzHW3dnsxuxi23-ZDPPfkWMSQ/viewform) on how we are doing with EventBus? + EventBus ======== EventBus is a publish/subscribe event bus for Android and Java.
@@ -100,10 +102,10 @@ EventBus binaries and source code can be used according to the [Apache License, More Open Source by greenrobot ============================== -[__ObjectBox__](https://github.com/objectbox/objectbox-java) is a new superfast object-oriented database for mobile. +[__ObjectBox__](http://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database for mobile. -[__greenrobot-common__](https://github.com/greenrobot/greenrobot-common) is a set of utility classes and hash functions for Android & Java projects. +[__Essentials__](http://greenrobot.org/essentials/) ([GitHub](https://github.com/greenrobot/essentials)) is a set of utility classes and hash functions for Android & Java projects. -[__greenDAO__](https://github.com/greenrobot/greenDAO) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. +[__greenDAO__](http://greenrobot.org/greendao/) ([GitHub](https://github.com/greenrobot/greenDAO)) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. [Follow us on Google+](https://plus.google.com/b/114381455741141514652/+GreenrobotDe/posts) or check our [homepage](http://greenrobot.org/) to stay up to date. From 0be1c4d492576266e6586d6c18c0704f10c609a6 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 7 Nov 2017 14:56:55 +0100 Subject: [PATCH 052/128] 3.1.1 / 3.1.0 --- EventBus/build.gradle | 4 ++-- EventBusAnnotationProcessor/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index e2167121..122e3616 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'idea' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.1.0-RC' +version = '3.1.1' sourceCompatibility = 1.7 def isSnapshot = version.endsWith('-SNAPSHOT') @@ -56,7 +56,7 @@ javadoc { failOnError = false classpath += configurations.provided title = "EventBus ${version} API" - options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2012-2016 greenrobot.org. All Rights Reserved.' + options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2012-2017 greenrobot.org. All Rights Reserved.' } task javadocJar(type: Jar, dependsOn: javadoc) { diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 4dfa5eca..24d7f34f 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'signing' archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' -version = '3.0.1' +version = '3.1.0' sourceCompatibility = 1.7 From 761731122af864fc4b925e926a6827510a7f07c0 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 7 Nov 2017 17:06:03 +0100 Subject: [PATCH 053/128] README.md: set gradle dependency to 3.1.1 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa176e78..3eb738c6 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Add EventBus to your project Via Gradle: ```gradle -compile 'org.greenrobot:eventbus:3.1.0-RC' +compile 'org.greenrobot:eventbus:3.1.1' ``` Via Maven: @@ -72,7 +72,7 @@ Via Maven: org.greenrobot eventbus - 3.1.0-RC + 3.1.1 ``` From 69417b5af70cd280b90462fe835d649f43bd9cf3 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 13 Nov 2017 13:36:15 +0100 Subject: [PATCH 054/128] Fix uploadArchives task naming issues. - Rename EventBus and EventBusAnnotationProcessor module to fix uploadArchives task. - Drop duplicate settings.gradle file for processor. - Enable uploading to local repository. --- EventBus/build.gradle | 6 +++++- EventBusAnnotationProcessor/build.gradle | 8 ++++++-- EventBusAnnotationProcessor/settings.gradle | 1 - EventBusPerformance/build.gradle | 4 ++-- EventBusTest/build.gradle | 4 ++-- EventBusTestJava/build.gradle | 4 ++-- EventBusTestSubscriberInJar/build.gradle | 4 ++-- settings.gradle | 15 +++++++++------ 8 files changed, 28 insertions(+), 18 deletions(-) delete mode 100644 EventBusAnnotationProcessor/settings.gradle diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 122e3616..16f57190 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -87,7 +87,11 @@ signing { uploadArchives { repositories { mavenDeployer { - if(project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') + if (project.hasProperty('preferedRepo')) println "preferedRepo = $preferedRepo" + if (project.hasProperty('preferedRepo') && preferedRepo == 'local') { + println "Deploying to local repo (aka install)..." + repository url: repositories.mavenLocal().url + } else if(project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') && project.hasProperty('preferedPassword')) { configuration = configurations.deployerJars repository(url: preferedRepo) { diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 24d7f34f..1c454f1b 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -28,7 +28,7 @@ configurations { } dependencies { - compile project(':EventBus') + compile project(':eventbus') compile 'de.greenrobot:java-common:2.3.1' deployerJars 'org.apache.maven.wagon:wagon-webdav:1.0-beta-2' } @@ -79,7 +79,11 @@ signing { uploadArchives { repositories { mavenDeployer { - if (project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') + if (project.hasProperty('preferedRepo')) println "preferedRepo = $preferedRepo" + if (project.hasProperty('preferedRepo') && preferedRepo == 'local') { + println "Deploying to local repo (aka install)..." + repository url: repositories.mavenLocal().url + } else if (project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') && project.hasProperty('preferedPassword')) { configuration = configurations.deployerJars repository(url: preferedRepo) { diff --git a/EventBusAnnotationProcessor/settings.gradle b/EventBusAnnotationProcessor/settings.gradle deleted file mode 100644 index 51ebbb79..00000000 --- a/EventBusAnnotationProcessor/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'eventbus-annotation-processor' \ No newline at end of file diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 99b54771..c60bf493 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -15,8 +15,8 @@ repositories { } dependencies { - compile project(':EventBus') - annotationProcessor project(':EventBusAnnotationProcessor') + compile project(':eventbus') + annotationProcessor project(':eventbus-annotation-processor') compile 'com.squareup:otto:1.3.8' } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 068c640a..d3b951c3 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -16,9 +16,9 @@ repositories { } dependencies { - androidTestCompile project(':EventBus') + androidTestCompile project(':eventbus') androidTestCompile project(':EventBusTestJava') - androidTestAnnotationProcessor project(':EventBusAnnotationProcessor') + androidTestAnnotationProcessor project(':eventbus-annotation-processor') compile fileTree(dir: 'libs', include: '*.jar') androidTestCompile 'com.android.support.test:runner:1.0.1' androidTestCompile 'com.android.support.test:rules:1.0.1' diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 19aba56f..0e7f18f2 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -30,10 +30,10 @@ sourceSets { dependencies { compile fileTree(dir: 'libs', include: '*.jar') - compile(project(':EventBus')) { + compile(project(':eventbus')) { exclude group: "com.google.android" // Does not seem to work... } - apt project(':EventBusAnnotationProcessor') + apt project(':eventbus-annotation-processor') compile 'junit:junit:4.12' } diff --git a/EventBusTestSubscriberInJar/build.gradle b/EventBusTestSubscriberInJar/build.gradle index 26adc98b..9211bcfb 100644 --- a/EventBusTestSubscriberInJar/build.gradle +++ b/EventBusTestSubscriberInJar/build.gradle @@ -13,8 +13,8 @@ configurations { } dependencies { - compile project(':EventBus') - provided project(':EventBusAnnotationProcessor') + compile project(':eventbus') + provided project(':eventbus-annotation-processor') } sourceSets { diff --git a/settings.gradle b/settings.gradle index f78cf550..c25cd47e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,9 @@ -include 'EventBus' -include 'EventBusAnnotationProcessor' -include 'EventBusTestJava' -include 'EventBusTest' -include 'EventBusTestSubscriberInJar' -include 'EventBusPerformance' +include ':EventBus' +include ':EventBusAnnotationProcessor' +include ':EventBusTestJava' +include ':EventBusTest' +include ':EventBusTestSubscriberInJar' +include ':EventBusPerformance' + +project(":EventBus").name = "eventbus" +project(":EventBusAnnotationProcessor").name = "eventbus-annotation-processor" \ No newline at end of file From 66fbde49d58670f7b46ff010da22d01e3c4d5b72 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 13 Nov 2017 14:45:55 +0100 Subject: [PATCH 055/128] Add index tests for MAIN vs MAIN_ORDERED behavior. --- .../indexed/EventBusAndroidOrderTestWithIndex.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java diff --git a/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java new file mode 100644 index 00000000..9e1f2318 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java @@ -0,0 +1,13 @@ +package org.greenrobot.eventbus.indexed; + +import org.greenrobot.eventbus.EventBusAndroidOrderTest; + +public class EventBusAndroidOrderTestWithIndex extends EventBusAndroidOrderTest { + + @Override + public void setUp() throws Exception { + eventBus = Indexed.build(); + super.setUp(); + } + +} From d459d1340d5621829b8821f751d1e00be125f5cf Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 14 Nov 2017 09:37:00 +0100 Subject: [PATCH 056/128] android 26 --- .travis.yml | 4 ++-- EventBusTest/build.gradle | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94fcd6f9..2210eda2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,9 @@ jdk: android: components: - tools - - build-tools-25.0.3 + - build-tools-26.0.3 - android-10 - - android-25 + - android-26 - extra-android-m2repository before_script: diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index d3b951c3..8e2966ce 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -19,14 +19,16 @@ dependencies { androidTestCompile project(':eventbus') androidTestCompile project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') + // Trying to repro bug: +// androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0' compile fileTree(dir: 'libs', include: '*.jar') androidTestCompile 'com.android.support.test:runner:1.0.1' androidTestCompile 'com.android.support.test:rules:1.0.1' } android { - buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml - compileSdkVersion 25 + buildToolsVersion '26.0.3' // When updating, don't forget to adjust .travis.yml + compileSdkVersion 26 compileOptions { sourceCompatibility = JavaVersion.VERSION_1_7 @@ -45,7 +47,7 @@ android { defaultConfig { minSdkVersion 9 - targetSdkVersion 25 + targetSdkVersion 26 versionCode 1 versionName "1.0" From bbe35ff77d736e4a38072ddc3659b122c46367c1 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 12:47:55 +0100 Subject: [PATCH 057/128] Move AndroidLogger to android package. --- .../greenrobot/eventbus/EventBusBuilder.java | 7 +- .../src/org/greenrobot/eventbus/Logger.java | 57 -------------- .../eventbus/android/AndroidLogger.java | 78 +++++++++++++++++++ 3 files changed, 82 insertions(+), 60 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 895b57a9..3e2b5c9c 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -17,6 +17,7 @@ import android.os.Looper; +import org.greenrobot.eventbus.android.AndroidLogger; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; import java.util.ArrayList; @@ -157,8 +158,8 @@ Logger getLogger() { return logger; } else { // also check main looper to see if we have "good" Android classes (not Stubs etc.) - return Logger.AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null - ? new Logger.AndroidLogger("EventBus") : + return AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null + ? new AndroidLogger("EventBus") : new Logger.SystemOutLogger(); } } @@ -167,7 +168,7 @@ Logger getLogger() { MainThreadSupport getMainThreadSupport() { if (mainThreadSupport != null) { return mainThreadSupport; - } else if (Logger.AndroidLogger.isAndroidLogAvailable()) { + } else if (AndroidLogger.isAndroidLogAvailable()) { Object looperOrNull = getAndroidMainLooperOrNull(); return looperOrNull == null ? null : new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull); diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index 6609b61b..602e0b51 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -15,8 +15,6 @@ */ package org.greenrobot.eventbus; -import android.util.Log; - import java.util.logging.Level; public interface Logger { @@ -25,61 +23,6 @@ public interface Logger { void log(Level level, String msg, Throwable th); - public static class AndroidLogger implements Logger { - static final boolean ANDROID_LOG_AVAILABLE; - - static { - boolean android = false; - try { - android = Class.forName("android.util.Log") != null; - } catch (ClassNotFoundException e) { - // OK - } - ANDROID_LOG_AVAILABLE = android; - } - - public static boolean isAndroidLogAvailable() { - return ANDROID_LOG_AVAILABLE; - } - - - private final String tag; - - public AndroidLogger(String tag) { - this.tag = tag; - } - - public void log(Level level, String msg) { - if (level != Level.OFF) { - Log.println(mapLevel(level), tag, msg); - } - } - - public void log(Level level, String msg, Throwable th) { - if (level != Level.OFF) { - // That's how Log does it internally - Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th)); - } - } - - protected int mapLevel(Level level) { - int value = level.intValue(); - if (value < 800) { // below INFO - if (value < 500) { // below FINE - return Log.VERBOSE; - } else { - return Log.DEBUG; - } - } else if (value < 900) { // below WARNING - return Log.INFO; - } else if (value < 1000) { // below ERROR - return Log.WARN; - } else { - return Log.ERROR; - } - } - } - public static class JavaLogger implements Logger { protected final java.util.logging.Logger logger; diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java new file mode 100644 index 00000000..fc14fe7d --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * + * 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 + * + * 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 org.greenrobot.eventbus.android; + +import android.util.Log; + +import org.greenrobot.eventbus.Logger; + +import java.util.logging.Level; + +public class AndroidLogger implements Logger { + + private static final boolean ANDROID_LOG_AVAILABLE; + + static { + boolean android = false; + try { + android = Class.forName("android.util.Log") != null; + } catch (ClassNotFoundException e) { + // OK + } + ANDROID_LOG_AVAILABLE = android; + } + + public static boolean isAndroidLogAvailable() { + return ANDROID_LOG_AVAILABLE; + } + + + private final String tag; + + public AndroidLogger(String tag) { + this.tag = tag; + } + + public void log(Level level, String msg) { + if (level != Level.OFF) { + Log.println(mapLevel(level), tag, msg); + } + } + + public void log(Level level, String msg, Throwable th) { + if (level != Level.OFF) { + // That's how Log does it internally + Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th)); + } + } + + private int mapLevel(Level level) { + int value = level.intValue(); + if (value < 800) { // below INFO + if (value < 500) { // below FINE + return Log.VERBOSE; + } else { + return Log.DEBUG; + } + } else if (value < 900) { // below WARNING + return Log.INFO; + } else if (value < 1000) { // below ERROR + return Log.WARN; + } else { + return Log.ERROR; + } + } +} From 1ba2f43a298d16b140f0629df35a8f8be3bc69e6 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 12:56:40 +0100 Subject: [PATCH 058/128] Use common build tools version and compileSdk (for Travis). --- EventBusPerformance/build.gradle | 4 ++-- EventBusTest/build.gradle | 4 ++-- build.gradle | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index c60bf493..a62ff46f 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -21,8 +21,8 @@ dependencies { } android { - buildToolsVersion '25.0.3' // When updating, don't forget to adjust .travis.yml - compileSdkVersion 25 + buildToolsVersion _buildToolsVersion + compileSdkVersion _compileSdkVersion sourceSets { main { diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 8e2966ce..cc426c8b 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -27,8 +27,8 @@ dependencies { } android { - buildToolsVersion '26.0.3' // When updating, don't forget to adjust .travis.yml - compileSdkVersion 26 + buildToolsVersion _buildToolsVersion + compileSdkVersion _compileSdkVersion compileOptions { sourceCompatibility = JavaVersion.VERSION_1_7 diff --git a/build.gradle b/build.gradle index fc18b763..80607751 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,10 @@ +buildscript { + ext { + _buildToolsVersion = '26.0.2' // When updating, don't forget to adjust .travis.yml + _compileSdkVersion = 26 + } +} + if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { From 5428a2b095d83012663dfa0629f81f925c156d6d Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 13:02:49 +0100 Subject: [PATCH 059/128] Actually use same build tools version as Travis (26.0.3). --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 80607751..ee1b1ef3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - _buildToolsVersion = '26.0.2' // When updating, don't forget to adjust .travis.yml + _buildToolsVersion = '26.0.3' // When updating, don't forget to adjust .travis.yml _compileSdkVersion = 26 } } From 66fed14fbe3b77330567981657f95cf5b38673dc Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 13:31:24 +0100 Subject: [PATCH 060/128] Define repositories once in root build file. --- EventBus/build.gradle | 4 ---- EventBusAnnotationProcessor/build.gradle | 4 ---- EventBusPerformance/build.gradle | 4 ---- EventBusTest/build.gradle | 5 ----- EventBusTestJava/build.gradle | 4 ---- EventBusTestSubscriberInJar/build.gradle | 4 ---- build.gradle | 8 ++++++++ 7 files changed, 8 insertions(+), 25 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 16f57190..4f3c246e 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -16,10 +16,6 @@ if(isSnapshot) { sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" } -repositories { - mavenCentral() -} - // Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 // Like this, it won't appear at all in the POM configurations { diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 1c454f1b..644ea215 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -16,10 +16,6 @@ if (isSnapshot) { sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" } -repositories { - mavenCentral() -} - // Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 // Like this, it won't appear at all in the POM configurations { diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index a62ff46f..fb2cc52f 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -10,10 +10,6 @@ buildscript { apply plugin: 'com.android.application' -repositories { - jcenter() -} - dependencies { compile project(':eventbus') annotationProcessor project(':eventbus-annotation-processor') diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index cc426c8b..ab6b884c 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -10,11 +10,6 @@ buildscript { apply plugin: 'com.android.application' -repositories { - jcenter() - google() -} - dependencies { androidTestCompile project(':eventbus') androidTestCompile project(':EventBusTestJava') diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 0e7f18f2..5fec7913 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -14,10 +14,6 @@ apply plugin: 'net.ltgt.apt-idea' sourceCompatibility = 1.7 -repositories { - jcenter() -} - // we have tests in the main source set so they can be shared with the Android test module // to make Gradle pick them up, add the dir to the test source set sourceSets { diff --git a/EventBusTestSubscriberInJar/build.gradle b/EventBusTestSubscriberInJar/build.gradle index 9211bcfb..b75da33b 100644 --- a/EventBusTestSubscriberInJar/build.gradle +++ b/EventBusTestSubscriberInJar/build.gradle @@ -4,10 +4,6 @@ group = 'de.greenrobot' version = '3.0.0' sourceCompatibility = 1.7 -repositories { - jcenter() -} - configurations { provided } diff --git a/build.gradle b/build.gradle index ee1b1ef3..f7b81bdf 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,14 @@ buildscript { } } +allprojects { + repositories { + jcenter() + mavenCentral() + google() + } +} + if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { From b035bf56be70ec039a493abb8e5c0235881250e6 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 13:35:35 +0100 Subject: [PATCH 061/128] Update Android Gradle Plugin to 3.0.0. --- EventBusPerformance/build.gradle | 8 ++++---- EventBusTest/build.gradle | 16 +++++++--------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index fb2cc52f..0dd5d1d3 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -1,19 +1,19 @@ buildscript { repositories { - jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } apply plugin: 'com.android.application' dependencies { - compile project(':eventbus') + implementation project(':eventbus') annotationProcessor project(':eventbus-annotation-processor') - compile 'com.squareup:otto:1.3.8' + implementation 'com.squareup:otto:1.3.8' } android { diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index ab6b884c..5015100f 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -1,24 +1,22 @@ buildscript { repositories { - jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } apply plugin: 'com.android.application' dependencies { - androidTestCompile project(':eventbus') - androidTestCompile project(':EventBusTestJava') + androidTestImplementation project(':eventbus') + androidTestImplementation project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') - // Trying to repro bug: -// androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0' - compile fileTree(dir: 'libs', include: '*.jar') - androidTestCompile 'com.android.support.test:runner:1.0.1' - androidTestCompile 'com.android.support.test:rules:1.0.1' + implementation fileTree(dir: 'libs', include: '*.jar') + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test:rules:1.0.1' } android { From 0e32fcea992a0a1159033d0c3bbaf160707756c3 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 13:42:44 +0100 Subject: [PATCH 062/128] EventBusPerformance: add MAIN_ORDERED. - Remove redundant findViewById casts. --- EventBusPerformance/res/values/strings.xml | 1 + .../eventbusperf/TestRunnerActivity.java | 2 +- .../eventbusperf/TestSetupActivity.java | 22 ++++++++--------- .../testsubject/PerfTestEventBus.java | 24 +++++++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/EventBusPerformance/res/values/strings.xml b/EventBusPerformance/res/values/strings.xml index feed5953..49148076 100644 --- a/EventBusPerformance/res/values/strings.xml +++ b/EventBusPerformance/res/values/strings.xml @@ -21,6 +21,7 @@ POSTING MAIN + MAIN_ORDERED BACKGROUND ASYNC diff --git a/EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java b/EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java index e22631c1..b21efabf 100644 --- a/EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java +++ b/EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java @@ -42,7 +42,7 @@ public class TestRunnerActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_runtests); - textViewResult = (TextView) findViewById(R.id.textViewResult); + textViewResult = findViewById(R.id.textViewResult); controlBus = new EventBus(); controlBus.register(this); } diff --git a/EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java b/EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java index 3488b8da..626f8a0b 100644 --- a/EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java +++ b/EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java @@ -50,7 +50,7 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_setuptests); - Spinner spinnerRun = (Spinner) findViewById(R.id.spinnerTestToRun); + Spinner spinnerRun = findViewById(R.id.spinnerTestToRun); spinnerRun.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView adapter, View v, int pos, long lng) { @@ -65,15 +65,15 @@ public void onNothingSelected(AdapterView arg0) { } public void checkEventBus(View v) { - Spinner spinnerThread = (Spinner) findViewById(R.id.spinnerThread); - CheckBox checkBoxEventBus = (CheckBox) findViewById(R.id.checkBoxEventBus); + Spinner spinnerThread = findViewById(R.id.spinnerThread); + CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus); int visibility = checkBoxEventBus.isChecked() ? View.VISIBLE : View.GONE; spinnerThread.setVisibility(visibility); } public void startClick(View v) { TestParams params = new TestParams(); - Spinner spinnerThread = (Spinner) findViewById(R.id.spinnerThread); + Spinner spinnerThread = findViewById(R.id.spinnerThread); String threadModeStr = spinnerThread.getSelectedItem().toString(); ThreadMode threadMode = ThreadMode.valueOf(threadModeStr); params.setThreadMode(threadMode); @@ -81,13 +81,13 @@ public void startClick(View v) { params.setEventInheritance(((CheckBox) findViewById(R.id.checkBoxEventBusEventHierarchy)).isChecked()); params.setIgnoreGeneratedIndex(((CheckBox) findViewById(R.id.checkBoxEventBusIgnoreGeneratedIndex)).isChecked()); - EditText editTextEvent = (EditText) findViewById(R.id.editTextEvent); + EditText editTextEvent = findViewById(R.id.editTextEvent); params.setEventCount(Integer.parseInt(editTextEvent.getText().toString())); - EditText editTextSubscriber = (EditText) findViewById(R.id.editTextSubscribe); + EditText editTextSubscriber = findViewById(R.id.editTextSubscribe); params.setSubscriberCount(Integer.parseInt(editTextSubscriber.getText().toString())); - Spinner spinnerTestToRun = (Spinner) findViewById(R.id.spinnerTestToRun); + Spinner spinnerTestToRun = findViewById(R.id.spinnerTestToRun); int testPos = spinnerTestToRun.getSelectedItemPosition(); params.setTestNumber(testPos + 1); ArrayList> testClasses = initTestClasses(testPos); @@ -103,10 +103,10 @@ public void startClick(View v) { private ArrayList> initTestClasses(int testPos) { ArrayList> testClasses = new ArrayList>(); // the attributes are putted in the intent (eventbus, otto, broadcast, local broadcast) - final CheckBox checkBoxEventBus = (CheckBox) findViewById(R.id.checkBoxEventBus); - final CheckBox checkBoxOtto = (CheckBox) findViewById(R.id.checkBoxOtto); - final CheckBox checkBoxBroadcast = (CheckBox) findViewById(R.id.checkBoxBroadcast); - final CheckBox checkBoxLocalBroadcast = (CheckBox) findViewById(R.id.checkBoxLocalBroadcast); + final CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus); + final CheckBox checkBoxOtto = findViewById(R.id.checkBoxOtto); + final CheckBox checkBoxBroadcast = findViewById(R.id.checkBoxBroadcast); + final CheckBox checkBoxLocalBroadcast = findViewById(R.id.checkBoxLocalBroadcast); if (checkBoxEventBus.isChecked()) { testClasses.add(TEST_CLASSES_EVENTBUS[testPos]); } diff --git a/EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java b/EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java index 7ceb8e6d..f0a5e2f8 100644 --- a/EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java +++ b/EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java @@ -66,6 +66,8 @@ private Class getSubscriberClassForThreadMode() { switch (params.getThreadMode()) { case MAIN: return SubscribeClassEventBusMain.class; + case MAIN_ORDERED: + return SubscribeClassEventBusMainOrdered.class; case BACKGROUND: return SubscribeClassEventBusBackground.class; case ASYNC: @@ -227,6 +229,28 @@ public void dummy5() { } } + public class SubscribeClassEventBusMainOrdered { + @Subscribe(threadMode = ThreadMode.MAIN_ORDERED) + public void onEvent(TestEvent event) { + eventsReceivedCount.incrementAndGet(); + } + + public void dummy() { + } + + public void dummy2() { + } + + public void dummy3() { + } + + public void dummy4() { + } + + public void dummy5() { + } + } + public class SubscribeClassEventBusBackground { @Subscribe(threadMode = ThreadMode.BACKGROUND) public void onEventBackgroundThread(TestEvent event) { From b98135699ab8bcd9622f74172df22e586850feed Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 14 Nov 2017 13:54:13 +0100 Subject: [PATCH 063/128] Revert: Update Android Gradle Plugin to 3.0.0. - IntelliJ 2017.2 does not yet support this version, wait for 2017.3. - https://stackoverflow.com/questions/44796375/is-it-possible-to-use-android-gradle-plugin-3-0-0-with-intellij --- EventBusPerformance/build.gradle | 8 ++++---- EventBusTest/build.gradle | 16 +++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 0dd5d1d3..fb2cc52f 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -1,19 +1,19 @@ buildscript { repositories { - google() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0' + classpath 'com.android.tools.build:gradle:2.3.3' } } apply plugin: 'com.android.application' dependencies { - implementation project(':eventbus') + compile project(':eventbus') annotationProcessor project(':eventbus-annotation-processor') - implementation 'com.squareup:otto:1.3.8' + compile 'com.squareup:otto:1.3.8' } android { diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 5015100f..ab6b884c 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -1,22 +1,24 @@ buildscript { repositories { - google() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0' + classpath 'com.android.tools.build:gradle:2.3.3' } } apply plugin: 'com.android.application' dependencies { - androidTestImplementation project(':eventbus') - androidTestImplementation project(':EventBusTestJava') + androidTestCompile project(':eventbus') + androidTestCompile project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') - implementation fileTree(dir: 'libs', include: '*.jar') - androidTestImplementation 'com.android.support.test:runner:1.0.1' - androidTestImplementation 'com.android.support.test:rules:1.0.1' + // Trying to repro bug: +// androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0' + compile fileTree(dir: 'libs', include: '*.jar') + androidTestCompile 'com.android.support.test:runner:1.0.1' + androidTestCompile 'com.android.support.test:rules:1.0.1' } android { From 3670d97835f15d0966e29fb8f52785ca3e87c2af Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 11 Dec 2017 21:02:25 +0100 Subject: [PATCH 064/128] over-engineering getDefault() (aka item 71 effective Java, 2nd ed.) --- EventBus/src/org/greenrobot/eventbus/EventBus.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 247cbb27..e35ecd38 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -78,14 +78,16 @@ protected PostingThreadState initialValue() { /** Convenience singleton for apps using a process-wide EventBus instance. */ public static EventBus getDefault() { - if (defaultInstance == null) { + EventBus instance = defaultInstance; + if (instance == null) { synchronized (EventBus.class) { - if (defaultInstance == null) { - defaultInstance = new EventBus(); + instance = EventBus.defaultInstance; + if (instance == null) { + instance = EventBus.defaultInstance = new EventBus(); } } } - return defaultInstance; + return instance; } public static EventBusBuilder builder() { From d52a0de2acc545a1c6cf94c43fee70cb9b059378 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 27 Aug 2018 14:59:20 +0200 Subject: [PATCH 065/128] README: use new dependency config, update Central search link. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3eb738c6..d66c0d57 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,11 @@ Read the full [getting started guide](http://greenrobot.org/eventbus/documentati Add EventBus to your project ---------------------------- - + Via Gradle: ```gradle -compile 'org.greenrobot:eventbus:3.1.1' +implementation 'org.greenrobot:eventbus:3.1.1' ``` Via Maven: From 2e7c0461106a3c261859579ec6fdcb5353ed31a4 Mon Sep 17 00:00:00 2001 From: greenrobot Team <13865709+greenrobot-team@users.noreply.github.com> Date: Tue, 12 Mar 2019 11:52:00 +0100 Subject: [PATCH 066/128] README: drop Google+ link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d66c0d57..cf9275f8 100644 --- a/README.md +++ b/README.md @@ -108,4 +108,4 @@ More Open Source by greenrobot [__greenDAO__](http://greenrobot.org/greendao/) ([GitHub](https://github.com/greenrobot/greenDAO)) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. -[Follow us on Google+](https://plus.google.com/b/114381455741141514652/+GreenrobotDe/posts) or check our [homepage](http://greenrobot.org/) to stay up to date. +Check our [homepage](http://greenrobot.org/) to stay up to date. From be4462eab6b29a25b8bc8f3ccbdcb7e0e4b5ee5f Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 14:42:40 +0100 Subject: [PATCH 067/128] Update Gradle [4.1->5.6.3]. --- build.gradle | 3 +-- gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 22 +++++++++++++++++++--- gradlew.bat | 18 +++++++++++++++++- 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index f7b81bdf..15b35417 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,6 @@ if (JavaVersion.current().isJava8Compatible()) { } } -task wrapper(type: Wrapper) { - gradleVersion = '4.1' +wrapper { distributionType = org.gradle.api.tasks.wrapper.Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch literal 55616 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

_x$+l{{cH8$W#CT diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bf1b63c3..3a54a333 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip diff --git a/gradlew b/gradlew index cccdd3d5..83f2acfd 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/gradlew.bat b/gradlew.bat index e95643d6..24467a14 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome From 7a993aed191d24aac84077f04f9ba2783ca77996 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 14:43:31 +0100 Subject: [PATCH 068/128] Drop apt plugin, use Gradle annotationProcessor instead. --- EventBusTestJava/build.gradle | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index 5fec7913..f19e3b19 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -1,16 +1,4 @@ -buildscript { - repositories { - maven { url "https://plugins.gradle.org/m2/" } - } - - dependencies { - classpath "net.ltgt.gradle:gradle-apt-plugin:0.12" - } -} - apply plugin: 'java' -// plugin to make it easier/safer to use EventBus annotation processor -apply plugin: 'net.ltgt.apt-idea' sourceCompatibility = 1.7 @@ -29,7 +17,7 @@ dependencies { compile(project(':eventbus')) { exclude group: "com.google.android" // Does not seem to work... } - apt project(':eventbus-annotation-processor') + annotationProcessor project(':eventbus-annotation-processor') compile 'junit:junit:4.12' } From 9c5e2e5a60ecef3cc83e8f6934a187b1832698ee Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 14:46:59 +0100 Subject: [PATCH 069/128] Update Android Gradle Plugin [2.3.3->3.5.2]. --- EventBusPerformance/AndroidManifest.xml | 8 +------- EventBusPerformance/build.gradle | 12 ++++++++---- EventBusTest/build.gradle | 14 +++++++------- build.gradle | 3 +-- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/EventBusPerformance/AndroidManifest.xml b/EventBusPerformance/AndroidManifest.xml index af353b5d..530cafeb 100644 --- a/EventBusPerformance/AndroidManifest.xml +++ b/EventBusPerformance/AndroidManifest.xml @@ -1,12 +1,6 @@ - - + package="org.greenrobot.eventbusperf"> Date: Tue, 19 Nov 2019 15:06:08 +0100 Subject: [PATCH 070/128] Update Travis config. --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2210eda2..e0364a93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,10 @@ jdk: # http://docs.travis-ci.com/user/languages/android/ android: components: - - tools - - build-tools-26.0.3 - - android-10 + - build-tools-28.0.3 - android-26 - - extra-android-m2repository + licenses: + - 'android-sdk-license-.+' before_script: - chmod +x gradlew From 7e363a6bc9ff7a9d242cec24da13db4932ff9042 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 15:41:11 +0100 Subject: [PATCH 071/128] EventBusPerformance: target SDK 26. --- EventBusPerformance/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index e89f9c51..47db03ce 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -30,7 +30,7 @@ android { defaultConfig { minSdkVersion 7 - targetSdkVersion 17 + targetSdkVersion 26 versionCode 1 versionName "2.0.0" javaCompileOptions { From ffeff4d6c92d9d19a13ff51c86ef4c4a42d7b043 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 15:48:43 +0100 Subject: [PATCH 072/128] Travis: add caching. --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index e0364a93..b22ae054 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,12 @@ before_script: script: - TERM=dumb ./gradlew check + +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ + - $HOME/.android/build-cache From 32992a66059b5953eb6c2d45d788e36576f58d17 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 9 Dec 2019 15:23:59 +0100 Subject: [PATCH 073/128] Extract common publishing setup to publish.gradle. --- EventBus/build.gradle | 79 ++------------------ EventBusAnnotationProcessor/build.gradle | 75 +------------------ gradle/publish.gradle | 95 ++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 146 deletions(-) create mode 100644 gradle/publish.gradle diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 4f3c246e..69569215 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -1,6 +1,4 @@ apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'signing' apply plugin: 'idea' archivesBaseName = 'eventbus' @@ -8,19 +6,10 @@ group = 'org.greenrobot' version = '3.1.1' sourceCompatibility = 1.7 -def isSnapshot = version.endsWith('-SNAPSHOT') -def sonatypeRepositoryUrl -if(isSnapshot) { - sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/" -} else { - sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - // Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 // Like this, it won't appear at all in the POM configurations { provided - deployerJars } dependencies { @@ -28,8 +17,6 @@ dependencies { provided 'com.google.android:android-test:4.1.1.4' provided 'com.google.android:annotations:4.1.1.4' provided 'com.google.android:support-v4:r7' - // deployerJars 'org.apache.maven.wagon:wagon-webdav-jackrabbit:2.4' - deployerJars 'org.apache.maven.wagon:wagon-webdav:1.0-beta-2' } sourceSets { @@ -48,6 +35,8 @@ idea { } } +apply from: rootProject.file("gradle/publish.gradle") + javadoc { failOnError = false classpath += configurations.provided @@ -71,72 +60,14 @@ artifacts { archives sourcesJar } -signing { - if(project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && - project.hasProperty('signing.secretKeyRingFile')) { - sign configurations.archives - } else { - println "Signing information missing/incomplete for ${project.name}" - } -} - uploadArchives { repositories { mavenDeployer { - if (project.hasProperty('preferedRepo')) println "preferedRepo = $preferedRepo" - if (project.hasProperty('preferedRepo') && preferedRepo == 'local') { - println "Deploying to local repo (aka install)..." - repository url: repositories.mavenLocal().url - } else if(project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') - && project.hasProperty('preferedPassword')) { - configuration = configurations.deployerJars - repository(url: preferedRepo) { - authentication(userName: preferedUsername, password: preferedPassword) - } - } else if(project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - repository(url: sonatypeRepositoryUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - } else { - println "Settings sonatypeUsername/sonatypePassword missing/incomplete for ${project.name}" - } + // Common setup is defined in publish.gradle. + pom.project { name 'EventBus' - packaging 'jar' - description 'EventBus is a publish/subscribe event bus optimized for Android .' - url 'http://greenrobot.org/eventbus/' - - scm { - url 'https://github.com/greenrobot/EventBus' - connection 'scm:git@github.com:greenrobot/EventBus.git' - developerConnection 'scm:git@github.com:greenrobot/EventBus.git' - } - - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - - developers { - developer { - id 'greenrobot' - name 'greenrobot' - } - } - - issueManagement { - system 'GitHub Issues' - url 'https://github.com/greenrobot/EventBus/issues' - } - - organization { - name 'greenrobot' - url 'http://greenrobot.org' - } + description 'EventBus is a publish/subscribe event bus optimized for Android.' } } } diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 644ea215..7c1e53a4 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -1,6 +1,4 @@ apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'signing' archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' @@ -8,25 +6,15 @@ version = '3.1.0' sourceCompatibility = 1.7 -def isSnapshot = version.endsWith('-SNAPSHOT') -def sonatypeRepositoryUrl -if (isSnapshot) { - sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/" -} else { - sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - // Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 // Like this, it won't appear at all in the POM configurations { provided - deployerJars } dependencies { compile project(':eventbus') compile 'de.greenrobot:java-common:2.3.1' - deployerJars 'org.apache.maven.wagon:wagon-webdav:1.0-beta-2' } sourceSets { @@ -41,6 +29,8 @@ sourceSets { } } +apply from: rootProject.file("gradle/publish.gradle") + javadoc { classpath += configurations.provided title = "EventBus Annotation Processor ${version} API" @@ -63,73 +53,14 @@ artifacts { archives sourcesJar } -signing { - if (project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && - project.hasProperty('signing.secretKeyRingFile')) { - sign configurations.archives - } else { - println "Signing information missing/incomplete for ${project.name}" - } -} - uploadArchives { repositories { mavenDeployer { - if (project.hasProperty('preferedRepo')) println "preferedRepo = $preferedRepo" - if (project.hasProperty('preferedRepo') && preferedRepo == 'local') { - println "Deploying to local repo (aka install)..." - repository url: repositories.mavenLocal().url - } else if (project.hasProperty('preferedRepo') && project.hasProperty('preferedUsername') - && project.hasProperty('preferedPassword')) { - configuration = configurations.deployerJars - repository(url: preferedRepo) { - authentication(userName: preferedUsername, password: preferedPassword) - } - } else if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - repository(url: sonatypeRepositoryUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - } else { - println "Settings sonatypeUsername/sonatypePassword missing/incomplete for ${project.name}" - } + // Common setup is defined in publish.gradle. pom.project { name 'EventBus Annotation Processor' - packaging 'jar' description 'Precompiler for EventBus Annotations.' - url 'http://greenrobot.org/eventbus/' - - scm { - url 'https://github.com/greenrobot/EventBus' - connection 'scm:git@github.com:greenrobot/EventBus.git' - developerConnection 'scm:git@github.com:greenrobot/EventBus.git' - } - - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - - developers { - developer { - id 'greenrobot' - name 'greenrobot' - } - } - - issueManagement { - system 'GitHub Issues' - url 'https://github.com/greenrobot/EventBus/issues' - } - - organization { - name 'greenrobot' - url 'http://greenrobot.org' - } } } } diff --git a/gradle/publish.gradle b/gradle/publish.gradle new file mode 100644 index 00000000..236b4afe --- /dev/null +++ b/gradle/publish.gradle @@ -0,0 +1,95 @@ +// Configures common publishing settings. + +apply plugin: "maven" +apply plugin: "signing" + +configurations { + deployerJars +} + +dependencies { + // Using an older version to remain compatible with Wagon API used by Gradle/Maven. + deployerJars 'org.apache.maven.wagon:wagon-webdav-jackrabbit:3.2.0' + deployerJars 'org.apache.maven.wagon:wagon-ftp:3.3.2' +} + +signing { + if (project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && + project.hasProperty('signing.secretKeyRingFile')) { + sign configurations.archives + } else { + println "Signing information missing/incomplete for ${project.name}." + } +} + +// Use afterEvaluate or dependencies might be lost in the generated POM. +afterEvaluate { project -> + uploadArchives { + repositories { + mavenDeployer { + def preferredRepo = project.findProperty('preferredRepo') + println "preferredRepo=$preferredRepo" + + if (preferredRepo == 'local') { + repository url: repositories.mavenLocal().url + } else if (preferredRepo != null + && project.hasProperty('preferredUsername') + && project.hasProperty('preferredPassword')) { + configuration = configurations.deployerJars + repository(url: repositoryUrl) { + authentication(userName: preferredUsername, password: preferredPassword) + } + } else if (project.hasProperty('sonatypeUsername') + && project.hasProperty('sonatypePassword')) { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + def isSnapshot = version.endsWith('-SNAPSHOT') + def sonatypeRepositoryUrl = isSnapshot + ? "https://oss.sonatype.org/content/repositories/snapshots/" + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + repository(url: sonatypeRepositoryUrl) { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + } else { + println "Deployment settings missing/incomplete for ${project.name}." + } + + // Common properties, projects still need to set name and description. + pom.project { + packaging 'jar' + url 'http://greenrobot.org/eventbus/' + + scm { + url 'https://github.com/greenrobot/EventBus' + connection 'scm:git@github.com:greenrobot/EventBus.git' + developerConnection 'scm:git@github.com:greenrobot/EventBus.git' + } + + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'greenrobot' + name 'greenrobot' + } + } + + issueManagement { + system 'GitHub Issues' + url 'https://github.com/greenrobot/EventBus/issues' + } + + organization { + name 'greenrobot' + url 'http://greenrobot.org' + } + } + } + } + } +} From 6c95dbcd4304218a6ff3eb4bcb4e7e27f32ab492 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 9 Dec 2019 15:35:35 +0100 Subject: [PATCH 074/128] Change provided->compileOnly and compile->implementation. --- EventBus/build.gradle | 23 ++++------------------- EventBusAnnotationProcessor/build.gradle | 12 ++---------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 69569215..621f2409 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -1,27 +1,19 @@ apply plugin: 'java' -apply plugin: 'idea' archivesBaseName = 'eventbus' group = 'org.greenrobot' version = '3.1.1' sourceCompatibility = 1.7 -// Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 -// Like this, it won't appear at all in the POM -configurations { - provided -} - dependencies { - provided 'com.google.android:android:4.1.1.4' - provided 'com.google.android:android-test:4.1.1.4' - provided 'com.google.android:annotations:4.1.1.4' - provided 'com.google.android:support-v4:r7' + compileOnly 'com.google.android:android:4.1.1.4' + compileOnly 'com.google.android:android-test:4.1.1.4' + compileOnly 'com.google.android:annotations:4.1.1.4' + compileOnly 'com.google.android:support-v4:r7' } sourceSets { main { - compileClasspath += configurations.provided java { srcDir 'src' // exclude 'de/greenrobot/event/util/**' @@ -29,17 +21,10 @@ sourceSets { } } -idea { - module { - scopes.PROVIDED.plus += [configurations.provided] - } -} - apply from: rootProject.file("gradle/publish.gradle") javadoc { failOnError = false - classpath += configurations.provided title = "EventBus ${version} API" options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2012-2017 greenrobot.org. All Rights Reserved.' } diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 7c1e53a4..2a5e4b02 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -6,20 +6,13 @@ version = '3.1.0' sourceCompatibility = 1.7 -// Still unsupported, see http://issues.gradle.org/browse/GRADLE-784 -// Like this, it won't appear at all in the POM -configurations { - provided -} - dependencies { - compile project(':eventbus') - compile 'de.greenrobot:java-common:2.3.1' + implementation project(':eventbus') + implementation 'de.greenrobot:java-common:2.3.1' } sourceSets { main { - compileClasspath += configurations.provided java { srcDir 'src' } @@ -32,7 +25,6 @@ sourceSets { apply from: rootProject.file("gradle/publish.gradle") javadoc { - classpath += configurations.provided title = "EventBus Annotation Processor ${version} API" options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2015-2016 greenrobot.org. All Rights Reserved.' } From 2a9310ef7319238b106302ea70ccc2a208aff2c7 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 21 Jan 2020 08:03:14 +0100 Subject: [PATCH 075/128] README: add R8 rules. --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf9275f8..0e7fa29b 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,24 @@ Via Maven: Or download [the latest JAR](https://search.maven.org/remote_content?g=org.greenrobot&a=eventbus&v=LATEST) from Maven Central. +R8, ProGuard +------------ + +If your project uses R8 or ProGuard add the following rules: + +```bash +-keepattributes *Annotation* +-keepclassmembers class * { + @org.greenrobot.eventbus.Subscribe ; +} +-keep enum org.greenrobot.eventbus.ThreadMode { *; } + +# And if you use AsyncExecutor: +-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { + (java.lang.Throwable); +} +``` + Homepage, Documentation, Links ------------------------------ For more details please check the [EventBus website](http://greenrobot.org/eventbus). Here are some direct links you may find useful: @@ -86,8 +104,6 @@ For more details please check the [EventBus website](http://greenrobot.org/event [Documentation](http://greenrobot.org/eventbus/documentation/) -[ProGuard](http://greenrobot.org/eventbus/documentation/proguard) - [Changelog](http://greenrobot.org/eventbus/changelog/) [FAQ](http://greenrobot.org/eventbus/documentation/faq/) From 5778314e0168c6fb2983c03dceadf4064b94278e Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 21 Jan 2020 08:08:23 +0100 Subject: [PATCH 076/128] README: drop broken Central JAR link. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e7fa29b..ac5baa2a 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,8 @@ Add EventBus to your project ---------------------------- +Available on Maven Central. + Via Gradle: ```gradle implementation 'org.greenrobot:eventbus:3.1.1' @@ -76,8 +78,6 @@ Via Maven: ``` -Or download [the latest JAR](https://search.maven.org/remote_content?g=org.greenrobot&a=eventbus&v=LATEST) from Maven Central. - R8, ProGuard ------------ From 0e0dc21bf3e6c8ba2d96b5cf2fb5c25406981c15 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 21 Jan 2020 08:13:06 +0100 Subject: [PATCH 077/128] README: update links (TLS). --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ac5baa2a..56dcd901 100644 --- a/README.md +++ b/README.md @@ -118,10 +118,8 @@ EventBus binaries and source code can be used according to the [Apache License, More Open Source by greenrobot ============================== -[__ObjectBox__](http://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database for mobile. +[__ObjectBox__](https://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database for mobile. -[__Essentials__](http://greenrobot.org/essentials/) ([GitHub](https://github.com/greenrobot/essentials)) is a set of utility classes and hash functions for Android & Java projects. +[__Essentials__](https://github.com/greenrobot/essentials) is a set of utility classes and hash functions for Android & Java projects. -[__greenDAO__](http://greenrobot.org/greendao/) ([GitHub](https://github.com/greenrobot/greenDAO)) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. - -Check our [homepage](http://greenrobot.org/) to stay up to date. +[__greenDAO__](https://github.com/greenrobot/greenDAO) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. From 9fed85f8243067dd66dda3f99038c0fcb82c52e0 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 21 Jan 2020 08:16:04 +0100 Subject: [PATCH 078/128] README: link to examples. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 56dcd901..f32d7afd 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ EventBus in 3 steps Read the full [getting started guide](http://greenrobot.org/eventbus/documentation/how-to-get-started/). +There are also some [examples](https://github.com/greenrobot-team/greenrobot-examples). + Add EventBus to your project ---------------------------- From f644d281233d57d4e83d9a57b5030f519027aeeb Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 19 Nov 2019 15:25:27 +0100 Subject: [PATCH 079/128] Mark annotation processor as aggregating. --- EventBusAnnotationProcessor/build.gradle | 5 +++++ .../EventBusAnnotationProcessor.java | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 2a5e4b02..224b7bda 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -9,6 +9,11 @@ sourceCompatibility = 1.7 dependencies { implementation project(':eventbus') implementation 'de.greenrobot:java-common:2.3.1' + + // Generates the required META-INF descriptor to make the processor incremental. + def incap = '0.2' + compileOnly "net.ltgt.gradle.incap:incap:$incap" + annotationProcessor "net.ltgt.gradle.incap:incap-processor:$incap" } sourceSets { diff --git a/EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java b/EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java index c37c18a5..058bc36e 100644 --- a/EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java +++ b/EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java @@ -15,6 +15,8 @@ */ package org.greenrobot.eventbus.annotationprocessor; +import net.ltgt.gradle.incap.IncrementalAnnotationProcessor; + import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -46,8 +48,16 @@ import de.greenrobot.common.ListMap; + +import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING; + +/** + * Is an aggregating processor as it writes a single file, the subscriber index file, + * based on found elements with the @Subscriber annotation. + */ @SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe") @SupportedOptions(value = {"eventBusIndex", "verbose"}) +@IncrementalAnnotationProcessor(AGGREGATING) public class EventBusAnnotationProcessor extends AbstractProcessor { public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex"; public static final String OPTION_VERBOSE = "verbose"; From 9b1aeddcd3bab713b094d00e8043a2399bb97000 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 3 Feb 2020 17:49:01 +0100 Subject: [PATCH 080/128] 3.1.2-RC: minor version updates, etc. --- EventBus/build.gradle | 4 ++-- .../src/org/greenrobot/eventbus/EventBus.java | 19 ++++++++++--------- .../greenrobot/eventbus/EventBusBuilder.java | 5 +++-- EventBusAnnotationProcessor/build.gradle | 4 ++-- EventBusPerformance/build.gradle | 2 +- EventBusTest/build.gradle | 6 +++--- README.md | 4 +--- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 621f2409..def4de6b 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.1.1' +version = '3.1.2-RC' sourceCompatibility = 1.7 dependencies { @@ -26,7 +26,7 @@ apply from: rootProject.file("gradle/publish.gradle") javadoc { failOnError = false title = "EventBus ${version} API" - options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2012-2017 greenrobot.org. All Rights Reserved.' + options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2012-2020 greenrobot.org. All Rights Reserved.' } task javadocJar(type: Jar, dependsOn: javadoc) { diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index e35ecd38..aa6c5981 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,12 +27,13 @@ import java.util.logging.Level; /** - * EventBus is a central publish/subscribe event system for Android. Events are posted ({@link #post(Object)}) to the - * bus, which delivers it to subscribers that have a matching handler method for the event type. To receive events, - * subscribers must register themselves to the bus using {@link #register(Object)}. Once registered, subscribers - * receive events until {@link #unregister(Object)} is called. Event handling methods must be annotated by - * {@link Subscribe}, must be public, return nothing (void), and have exactly one parameter - * (the event). + * EventBus is a central publish/subscribe event system for Java and Android. + * Events are posted ({@link #post(Object)}) to the bus, which delivers it to subscribers that have a matching handler + * method for the event type. + * To receive events, subscribers must register themselves to the bus using {@link #register(Object)}. + * Once registered, subscribers receive events until {@link #unregister(Object)} is called. + * Event handling methods must be annotated by {@link Subscribe}, must be public, return nothing (void), + * and have exactly one parameter (the event). * * @author Markus Junginger, greenrobot */ @@ -213,7 +214,7 @@ private void checkPostStickyEventToSubscription(Subscription newSubscription, Ob * poster. */ private boolean isMainThread() { - return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true; + return mainThreadSupport == null || mainThreadSupport.isMainThread(); } public synchronized boolean isRegistered(Object subscriber) { @@ -408,7 +409,7 @@ private boolean postSingleEventForEventType(Object event, PostingThreadState pos for (Subscription subscription : subscriptions) { postingState.event = event; postingState.subscription = subscription; - boolean aborted = false; + boolean aborted; try { postToSubscription(subscription, event, postingState.isMainThread); aborted = postingState.canceled; diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 3e2b5c9c..64e30982 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance. * Create a new builder using {@link EventBus#builder()}. */ +@SuppressWarnings("unused") public class EventBusBuilder { private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool(); @@ -88,7 +89,7 @@ public EventBusBuilder throwSubscriberException(boolean throwSubscriberException * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified). * Switching this feature off will improve posting of events. For simple event classes extending Object directly, * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be - * >20%. + * greater than 20%. *

* However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app, * unless it is posting at high rates, e.g. hundreds/thousands of events per second. diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 224b7bda..8a0ba145 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' -version = '3.1.0' +version = '3.1.2-RC' sourceCompatibility = 1.7 @@ -31,7 +31,7 @@ apply from: rootProject.file("gradle/publish.gradle") javadoc { title = "EventBus Annotation Processor ${version} API" - options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2015-2016 greenrobot.org. All Rights Reserved.' + options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2015-2020 greenrobot.org. All Rights Reserved.' } task javadocJar(type: Jar, dependsOn: javadoc) { diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 47db03ce..7123513f 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:3.5.3' } } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 27d44045..22e77647 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:3.5.3' } } @@ -18,8 +18,8 @@ dependencies { // Trying to repro bug: // androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0' implementation fileTree(dir: 'libs', include: '*.jar') - androidTestImplementation 'com.android.support.test:runner:1.0.1' - androidTestImplementation 'com.android.support.test:rules:1.0.1' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test:rules:1.0.2' } android { diff --git a/README.md b/README.md index f32d7afd..ae3f8cab 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -Hey, do have a minute for a [quick survey](https://docs.google.com/forms/d/e/1FAIpQLSePA8NqA9Jlbvh28xcFVbmIGUzHW3dnsxuxi23-ZDPPfkWMSQ/viewform) on how we are doing with EventBus? - EventBus ======== EventBus is a publish/subscribe event bus for Android and Java.
@@ -114,7 +112,7 @@ How does EventBus compare to other solutions, like Otto from Square? Check this License ------- -Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org) +Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) EventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE). From 0d551f1a493710b92791b82bd915238310c6ed4e Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 4 Feb 2020 14:01:50 +0100 Subject: [PATCH 081/128] add Logger.Default and use it to make ExceptionToResourceMapping independent from Android --- EventBus/build.gradle | 2 +- .../greenrobot/eventbus/EventBusBuilder.java | 8 ++---- .../src/org/greenrobot/eventbus/Logger.java | 27 ++++++++++++++++--- .../util/ExceptionToResourceMapping.java | 8 +++--- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index def4de6b..ad4f88a4 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.1.2-RC' +version = '3.2.0-SNAPSHOT' sourceCompatibility = 1.7 dependencies { diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 64e30982..c091e05e 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -158,14 +158,10 @@ Logger getLogger() { if (logger != null) { return logger; } else { - // also check main looper to see if we have "good" Android classes (not Stubs etc.) - return AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null - ? new AndroidLogger("EventBus") : - new Logger.SystemOutLogger(); + return Logger.Default.get(); } } - MainThreadSupport getMainThreadSupport() { if (mainThreadSupport != null) { return mainThreadSupport; @@ -178,7 +174,7 @@ MainThreadSupport getMainThreadSupport() { } } - Object getAndroidMainLooperOrNull() { + static Object getAndroidMainLooperOrNull() { try { return Looper.getMainLooper(); } catch (RuntimeException e) { diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index 602e0b51..69d1063a 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,9 @@ */ package org.greenrobot.eventbus; +import android.os.Looper; +import org.greenrobot.eventbus.android.AndroidLogger; + import java.util.logging.Level; public interface Logger { @@ -23,7 +26,7 @@ public interface Logger { void log(Level level, String msg, Throwable th); - public static class JavaLogger implements Logger { + class JavaLogger implements Logger { protected final java.util.logging.Logger logger; public JavaLogger(String tag) { @@ -44,7 +47,7 @@ public void log(Level level, String msg, Throwable th) { } - public static class SystemOutLogger implements Logger { + class SystemOutLogger implements Logger { @Override public void log(Level level, String msg) { @@ -59,4 +62,22 @@ public void log(Level level, String msg, Throwable th) { } + class Default { + public static Logger get() { + // also check main looper to see if we have "good" Android classes (not Stubs etc.) + return AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null + ? new AndroidLogger("EventBus") : + new Logger.SystemOutLogger(); + } + + static Object getAndroidMainLooperOrNull() { + try { + return Looper.getMainLooper(); + } catch (RuntimeException e) { + // Not really a functional Android (e.g. "Stub!" maven dependencies) + return null; + } + } + } + } diff --git a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java index a3bb67f3..083bd394 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java +++ b/EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) + * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,13 @@ package org.greenrobot.eventbus.util; -import android.util.Log; +import org.greenrobot.eventbus.Logger; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.logging.Level; /** @@ -50,7 +51,8 @@ public Integer mapThrowable(final Throwable throwable) { throwableToCheck = throwableToCheck.getCause(); depthToGo--; if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) { - Log.d("EventBus", "No specific message resource ID found for " + throwable); + Logger logger = Logger.Default.get(); // No EventBus instance here + logger.log(Level.FINE, "No specific message resource ID found for " + throwable); // return config.defaultErrorMsgId; return null; } From 62abc54dec3bf3e1f8d2badc4752f61ff05e8eb3 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 4 Feb 2020 15:22:36 +0100 Subject: [PATCH 082/128] Skip also androidx.* super classes --- .../src/org/greenrobot/eventbus/SubscriberMethodFinder.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java index db5e0ad3..b688cc46 100644 --- a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java +++ b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java @@ -259,8 +259,10 @@ void moveToSuperclass() { } else { clazz = clazz.getSuperclass(); String clazzName = clazz.getName(); - /** Skip system classes, this just degrades performance. */ - if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) { + // Skip system classes, this degrades performance. + // Also we might avoid some ClassNotFoundException (see FAQ for background). + if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || + clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) { clazz = null; } } From bb5b149b556a6f295c3bad597a66edf83c2e73eb Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 4 Feb 2020 15:23:39 +0100 Subject: [PATCH 083/128] Provide additional info if Class.getMethods() fails --- .../eventbus/SubscriberMethodFinder.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java index b688cc46..37e001ff 100644 --- a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java +++ b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java @@ -15,6 +15,7 @@ */ package org.greenrobot.eventbus; +import android.annotation.TargetApi; import org.greenrobot.eventbus.meta.SubscriberInfo; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; @@ -25,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; class SubscriberMethodFinder { /* @@ -154,7 +156,14 @@ private void findUsingReflectionInSingleClass(FindState findState) { methods = findState.clazz.getDeclaredMethods(); } catch (Throwable th) { // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149 - methods = findState.clazz.getMethods(); + try { + methods = findState.clazz.getMethods(); + } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad... + String msg = "Could not inspect methods of " + findState.clazz.getName() + + ". Please consider using EventBus annotation processor to avoid reflection."; + throwLinkageError(error, msg); + return; + } findState.skipSuperClasses = true; } for (Method method : methods) { @@ -184,6 +193,16 @@ private void findUsingReflectionInSingleClass(FindState findState) { } } + @TargetApi(19) + private void throwLinkageError(LinkageError error, String msg) { + try { + error = new LinkageError(msg, error); // Wrapping only works with Java 7 / Android API 19 + } catch (Throwable ex) { + Logger.Default.get().log(Level.SEVERE, msg); // Can not wrap, log additional info + } + throw error; + } + static void clearCaches() { METHOD_CACHE.clear(); } From 34a1537af7364cec9444a24431c566d434d4d0b8 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 4 Feb 2020 17:04:52 +0100 Subject: [PATCH 084/128] Class.getMethods() failures: provide better info and use EventBusException instead of LinkageError --- .../eventbus/SubscriberMethodFinder.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java index 37e001ff..3f2812bc 100644 --- a/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java +++ b/EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java @@ -15,7 +15,6 @@ */ package org.greenrobot.eventbus; -import android.annotation.TargetApi; import org.greenrobot.eventbus.meta.SubscriberInfo; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; @@ -26,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; class SubscriberMethodFinder { /* @@ -159,10 +157,13 @@ private void findUsingReflectionInSingleClass(FindState findState) { try { methods = findState.clazz.getMethods(); } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad... - String msg = "Could not inspect methods of " + findState.clazz.getName() + - ". Please consider using EventBus annotation processor to avoid reflection."; - throwLinkageError(error, msg); - return; + String msg = "Could not inspect methods of " + findState.clazz.getName(); + if (ignoreGeneratedIndex) { + msg += ". Please consider using EventBus annotation processor to avoid reflection."; + } else { + msg += ". Please make this class visible to EventBus annotation processor to avoid reflection."; + } + throw new EventBusException(msg, error); } findState.skipSuperClasses = true; } @@ -193,16 +194,6 @@ private void findUsingReflectionInSingleClass(FindState findState) { } } - @TargetApi(19) - private void throwLinkageError(LinkageError error, String msg) { - try { - error = new LinkageError(msg, error); // Wrapping only works with Java 7 / Android API 19 - } catch (Throwable ex) { - Logger.Default.get().log(Level.SEVERE, msg); // Can not wrap, log additional info - } - throw error; - } - static void clearCaches() { METHOD_CACHE.clear(); } From ddaace5e2aa70fc2ea0128b2f46f81d8e70d5a56 Mon Sep 17 00:00:00 2001 From: Markus Date: Mon, 10 Feb 2020 10:05:45 +0100 Subject: [PATCH 085/128] 3.2.0 --- EventBus/build.gradle | 2 +- EventBusAnnotationProcessor/build.gradle | 2 +- README.md | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index ad4f88a4..869cfa92 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' archivesBaseName = 'eventbus' group = 'org.greenrobot' -version = '3.2.0-SNAPSHOT' +version = '3.2.0' sourceCompatibility = 1.7 dependencies { diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 8a0ba145..d00f28ea 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' -version = '3.1.2-RC' +version = '3.2.0' sourceCompatibility = 1.7 diff --git a/README.md b/README.md index ae3f8cab..b914c6a5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ EventBus ======== -EventBus is a publish/subscribe event bus for Android and Java.
+[EventBus](http://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.
+[![Build Status](https://travis-ci.org/greenrobot/EventBus.svg?branch=master)](https://travis-ci.org/greenrobot/EventBus) +[![Follow greenrobot on Twitter](https://img.shields.io/twitter/follow/greenrobot_de.svg?style=flat-square&logo=twitter)](https://twitter.com/greenrobot_de) + EventBus... * simplifies the communication between components @@ -11,11 +14,10 @@ EventBus... * avoids complex and error-prone dependencies and life cycle issues * makes your code simpler * is fast - * is tiny (~50k jar) - * is proven in practice by apps with 100,000,000+ installs + * is tiny (~60k jar) + * is proven in practice by apps with 1,000,000,000+ installs * has advanced features like delivery threads, subscriber priorities, etc. - [![Build Status](https://travis-ci.org/greenrobot/EventBus.svg?branch=master)](https://travis-ci.org/greenrobot/EventBus) EventBus in 3 steps ------------------- @@ -66,7 +68,7 @@ Available on +[EventBus](https://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.
[![Build Status](https://travis-ci.org/greenrobot/EventBus.svg?branch=master)](https://travis-ci.org/greenrobot/EventBus) @@ -28,7 +28,7 @@ EventBus in 3 steps ``` 2. Prepare subscribers: - Declare and annotate your subscribing method, optionally specify a [thread mode](http://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/): + Declare and annotate your subscribing method, optionally specify a [thread mode](https://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/): ```java @Subscribe(threadMode = ThreadMode.MAIN) @@ -56,7 +56,7 @@ EventBus in 3 steps EventBus.getDefault().post(new MessageEvent()); ``` -Read the full [getting started guide](http://greenrobot.org/eventbus/documentation/how-to-get-started/). +Read the full [getting started guide](https://greenrobot.org/eventbus/documentation/how-to-get-started/). There are also some [examples](https://github.com/greenrobot-team/greenrobot-examples). @@ -100,21 +100,21 @@ If your project uses R8 or ProGuard add the following rules: Homepage, Documentation, Links ------------------------------ -For more details please check the [EventBus website](http://greenrobot.org/eventbus). Here are some direct links you may find useful: +For more details please check the [EventBus website](https://greenrobot.org/eventbus). Here are some direct links you may find useful: -[Features](http://greenrobot.org/eventbus/features/) +[Features](https://greenrobot.org/eventbus/features/) -[Documentation](http://greenrobot.org/eventbus/documentation/) +[Documentation](https://greenrobot.org/eventbus/documentation/) -[Changelog](http://greenrobot.org/eventbus/changelog/) +[Changelog](https://greenrobot.org/eventbus/changelog/) -[FAQ](http://greenrobot.org/eventbus/documentation/faq/) +[FAQ](https://greenrobot.org/eventbus/documentation/faq/) How does EventBus compare to other solutions, like Otto from Square? Check this [comparison](COMPARISON.md). License ------- -Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org) +Copyright (C) 2012-2020 Markus Junginger, greenrobot (https://greenrobot.org) EventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE). diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 236b4afe..a887ff3a 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -56,7 +56,7 @@ afterEvaluate { project -> // Common properties, projects still need to set name and description. pom.project { packaging 'jar' - url 'http://greenrobot.org/eventbus/' + url 'https://greenrobot.org/eventbus/' scm { url 'https://github.com/greenrobot/EventBus' @@ -86,7 +86,7 @@ afterEvaluate { project -> organization { name 'greenrobot' - url 'http://greenrobot.org' + url 'https://greenrobot.org' } } } From 1d995077d0b620a6aae9c60a8b96443113752305 Mon Sep 17 00:00:00 2001 From: Markus Date: Tue, 11 Feb 2020 10:52:09 +0100 Subject: [PATCH 087/128] README.md: add recommendation to use subscriber index --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d911ac0..2a776233 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ EventBus... * is proven in practice by apps with 1,000,000,000+ installs * has advanced features like delivery threads, subscriber priorities, etc. - EventBus in 3 steps ------------------- 1. Define events: @@ -60,6 +59,9 @@ Read the full [getting started guide](https://greenrobot.org/eventbus/documentat There are also some [examples](https://github.com/greenrobot-team/greenrobot-examples). +**Note:** we highly recommend the [EventBus annotation processor with its subscriber index](https://greenrobot.org/eventbus/documentation/subscriber-index/). +This will avoid some reflection related problems seen in the wild. + Add EventBus to your project ----------------------------
From bf8e86164001f514ce74514de5d0034f3473ee0f Mon Sep 17 00:00:00 2001 From: Andrei Dobrescu Date: Mon, 10 May 2021 16:04:25 +0300 Subject: [PATCH 088/128] removed error dialog classes --- EventBus/build.gradle | 3 +- .../eventbus/util/ErrorDialogConfig.java | 82 ------ .../util/ErrorDialogFragmentFactory.java | 114 -------- .../eventbus/util/ErrorDialogFragments.java | 91 ------ .../eventbus/util/ErrorDialogManager.java | 262 ------------------ .../eventbus/util/ThrowableFailureEvent.java | 3 +- EventBusAnnotationProcessor/build.gradle | 3 +- EventBusPerformance/build.gradle | 4 +- EventBusTest/build.gradle | 4 +- EventBusTestJava/build.gradle | 3 +- EventBusTestSubscriberInJar/build.gradle | 3 +- build.gradle | 3 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 13 files changed, 15 insertions(+), 562 deletions(-) delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/ErrorDialogConfig.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragmentFactory.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragments.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/ErrorDialogManager.java diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 45e34b44..af93b5f2 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -3,7 +3,8 @@ apply plugin: 'java' archivesBaseName = 'eventbus' group = 'org.greenrobot' version = '3.2.0' -sourceCompatibility = 1.7 +java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.targetCompatibility = JavaVersion.VERSION_1_8 dependencies { compileOnly 'com.google.android:android:4.1.1.4' diff --git a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogConfig.java b/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogConfig.java deleted file mode 100644 index 95e84c72..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogConfig.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) - * - * 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 - * - * 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 org.greenrobot.eventbus.util; - -import android.content.res.Resources; -import android.util.Log; - -import org.greenrobot.eventbus.EventBus; - -public class ErrorDialogConfig { - final Resources resources; - final int defaultTitleId; - final int defaultErrorMsgId; - final ExceptionToResourceMapping mapping; - - EventBus eventBus; - boolean logExceptions = true; - String tagForLoggingExceptions; - int defaultDialogIconId; - Class defaultEventTypeOnDialogClosed; - - public ErrorDialogConfig(Resources resources, int defaultTitleId, int defaultMsgId) { - this.resources = resources; - this.defaultTitleId = defaultTitleId; - this.defaultErrorMsgId = defaultMsgId; - mapping = new ExceptionToResourceMapping(); - } - - public ErrorDialogConfig addMapping(Class clazz, int msgId) { - mapping.addMapping(clazz, msgId); - return this; - } - - public int getMessageIdForThrowable(final Throwable throwable) { - Integer resId = mapping.mapThrowable(throwable); - if (resId != null) { - return resId; - } else { - Log.d(EventBus.TAG, "No specific message ressource ID found for " + throwable); - return defaultErrorMsgId; - } - } - - public void setDefaultDialogIconId(int defaultDialogIconId) { - this.defaultDialogIconId = defaultDialogIconId; - } - - public void setDefaultEventTypeOnDialogClosed(Class defaultEventTypeOnDialogClosed) { - this.defaultEventTypeOnDialogClosed = defaultEventTypeOnDialogClosed; - } - - public void disableExceptionLogging() { - logExceptions = false; - } - - public void setTagForLoggingExceptions(String tagForLoggingExceptions) { - this.tagForLoggingExceptions = tagForLoggingExceptions; - } - - public void setEventBus(EventBus eventBus) { - this.eventBus = eventBus; - } - - /** eventBus!=null ? eventBus: EventBus.getDefault() */ - EventBus getEventBus() { - return eventBus!=null ? eventBus: EventBus.getDefault(); - } -} \ No newline at end of file diff --git a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragmentFactory.java b/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragmentFactory.java deleted file mode 100644 index 27ab963d..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragmentFactory.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) - * - * 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 - * - * 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 org.greenrobot.eventbus.util; - -import android.annotation.TargetApi; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.Fragment; - -/** - * Factory to allow injecting a more complex exception mapping; typically you would subclass one of {@link Honeycomb} or - * {@link Support}. - */ -public abstract class ErrorDialogFragmentFactory { - protected final ErrorDialogConfig config; - - protected ErrorDialogFragmentFactory(ErrorDialogConfig config) { - this.config = config; - } - - /** - * Prepares the fragment's arguments and creates the fragment. May be overridden to provide custom error fragments. - */ - protected T prepareErrorFragment(ThrowableFailureEvent event, boolean finishAfterDialog, - Bundle argumentsForErrorDialog) { - if (event.isSuppressErrorUi()) { - // Show nothing by default - return null; - } - Bundle bundle; - if (argumentsForErrorDialog != null) { - bundle = (Bundle) argumentsForErrorDialog.clone(); - } else { - bundle = new Bundle(); - } - - if (!bundle.containsKey(ErrorDialogManager.KEY_TITLE)) { - String title = getTitleFor(event, bundle); - bundle.putString(ErrorDialogManager.KEY_TITLE, title); - } - if (!bundle.containsKey(ErrorDialogManager.KEY_MESSAGE)) { - String message = getMessageFor(event, bundle); - bundle.putString(ErrorDialogManager.KEY_MESSAGE, message); - } - if (!bundle.containsKey(ErrorDialogManager.KEY_FINISH_AFTER_DIALOG)) { - bundle.putBoolean(ErrorDialogManager.KEY_FINISH_AFTER_DIALOG, finishAfterDialog); - } - if (!bundle.containsKey(ErrorDialogManager.KEY_EVENT_TYPE_ON_CLOSE) - && config.defaultEventTypeOnDialogClosed != null) { - bundle.putSerializable(ErrorDialogManager.KEY_EVENT_TYPE_ON_CLOSE, config.defaultEventTypeOnDialogClosed); - } - if (!bundle.containsKey(ErrorDialogManager.KEY_ICON_ID) && config.defaultDialogIconId != 0) { - bundle.putInt(ErrorDialogManager.KEY_ICON_ID, config.defaultDialogIconId); - } - return createErrorFragment(event, bundle); - } - - /** Returns either a new Honeycomb+ or a new support library DialogFragment. */ - protected abstract T createErrorFragment(ThrowableFailureEvent event, Bundle arguments); - - /** May be overridden to provide custom error title. */ - protected String getTitleFor(ThrowableFailureEvent event, Bundle arguments) { - return config.resources.getString(config.defaultTitleId); - } - - /** May be overridden to provide custom error messages. */ - protected String getMessageFor(ThrowableFailureEvent event, Bundle arguments) { - int msgResId = config.getMessageIdForThrowable(event.throwable); - return config.resources.getString(msgResId); - } - - public static class Support extends ErrorDialogFragmentFactory { - - public Support(ErrorDialogConfig config) { - super(config); - } - - protected Fragment createErrorFragment(ThrowableFailureEvent event, Bundle arguments) { - ErrorDialogFragments.Support errorFragment = new ErrorDialogFragments.Support(); - errorFragment.setArguments(arguments); - return errorFragment; - } - - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static class Honeycomb extends ErrorDialogFragmentFactory { - - public Honeycomb(ErrorDialogConfig config) { - super(config); - } - - protected android.app.Fragment createErrorFragment(ThrowableFailureEvent event, Bundle arguments) { - ErrorDialogFragments.Honeycomb errorFragment = new ErrorDialogFragments.Honeycomb(); - errorFragment.setArguments(arguments); - return errorFragment; - } - - } -} \ No newline at end of file diff --git a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragments.java b/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragments.java deleted file mode 100644 index 49174766..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogFragments.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) - * - * 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 - * - * 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 org.greenrobot.eventbus.util; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; - -import org.greenrobot.eventbus.EventBus; - -public class ErrorDialogFragments { - /** TODO Use config: Icon res ID to use for all error dialogs. May be configured by each app (optional). */ - public static int ERROR_DIALOG_ICON = 0; - - /** TODO Use config: Event class to be fired on dismissing the dialog by the user. May be configured by each app. */ - public static Class EVENT_TYPE_ON_CLICK; - - public static Dialog createDialog(Context context, Bundle arguments, OnClickListener onClickListener) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(arguments.getString(ErrorDialogManager.KEY_TITLE)); - builder.setMessage(arguments.getString(ErrorDialogManager.KEY_MESSAGE)); - if (ERROR_DIALOG_ICON != 0) { - builder.setIcon(ERROR_DIALOG_ICON); - } - builder.setPositiveButton(android.R.string.ok, onClickListener); - return builder.create(); - } - - public static void handleOnClick(DialogInterface dialog, int which, Activity activity, Bundle arguments) { - if (EVENT_TYPE_ON_CLICK != null) { - Object event; - try { - event = EVENT_TYPE_ON_CLICK.newInstance(); - } catch (Exception e) { - throw new RuntimeException("Event cannot be constructed", e); - } - EventBus eventBus = ErrorDialogManager.factory.config.getEventBus(); - eventBus.post(event); - } - boolean finish = arguments.getBoolean(ErrorDialogManager.KEY_FINISH_AFTER_DIALOG, false); - if (finish && activity != null) { - activity.finish(); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static class Honeycomb extends android.app.DialogFragment implements OnClickListener { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return createDialog(getActivity(), getArguments(), this); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - handleOnClick(dialog, which, getActivity(), getArguments()); - } - } - - public static class Support extends DialogFragment implements OnClickListener { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return createDialog(getActivity(), getArguments(), this); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - handleOnClick(dialog, which, getActivity(), getArguments()); - } - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogManager.java b/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogManager.java deleted file mode 100644 index 9d5ccf2c..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/ErrorDialogManager.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org) - * - * 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 - * - * 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 org.greenrobot.eventbus.util; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.Application; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.util.Log; - -import org.greenrobot.eventbus.EventBus; - -/** - * Central class for app that want to use event based error dialogs.
- *
- * How to use: - *

    - *
  1. Set the {@link #factory} to configure dialogs for your app, typically in {@link Application#onCreate()}
  2. - *
  3. Use one of {@link #attachTo(Activity)}, {@link #attachTo(Activity, boolean)} or - * {@link #attachTo(Activity, boolean, Bundle)} in your Activity, typically in onCreate.
  4. - *
- * - * For more complex mappings, you can supply your own {@link ErrorDialogFragmentFactory}. - * - * @author Markus - */ -public class ErrorDialogManager { - - public static class SupportManagerFragment extends Fragment { - protected boolean finishAfterDialog; - protected Bundle argumentsForErrorDialog; - private EventBus eventBus; - private boolean skipRegisterOnNextResume; - private Object executionScope; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - eventBus = ErrorDialogManager.factory.config.getEventBus(); - eventBus.register(this); - skipRegisterOnNextResume = true; - } - - @Override - public void onResume() { - super.onResume(); - if (skipRegisterOnNextResume) { - // registered in onCreate, skip registration in this run - skipRegisterOnNextResume = false; - } else { - eventBus = ErrorDialogManager.factory.config.getEventBus(); - eventBus.register(this); - } - } - - @Override - public void onPause() { - eventBus.unregister(this); - super.onPause(); - } - - public void onEventMainThread(ThrowableFailureEvent event) { - if (!isInExecutionScope(executionScope, event)) { - return; - } - checkLogException(event); - // Execute pending commits before finding to avoid multiple error fragments being shown - FragmentManager fm = getFragmentManager(); - fm.executePendingTransactions(); - - DialogFragment existingFragment = (DialogFragment) fm.findFragmentByTag(TAG_ERROR_DIALOG); - if (existingFragment != null) { - // Just show the latest error - existingFragment.dismiss(); - } - - android.support.v4.app.DialogFragment errorFragment = (android.support.v4.app.DialogFragment) factory - .prepareErrorFragment(event, finishAfterDialog, argumentsForErrorDialog); - if (errorFragment != null) { - errorFragment.show(fm, TAG_ERROR_DIALOG); - } - } - - public static void attachTo(Activity activity, Object executionScope, boolean finishAfterDialog, - Bundle argumentsForErrorDialog) { - FragmentManager fm = ((FragmentActivity) activity).getSupportFragmentManager(); - SupportManagerFragment fragment = (SupportManagerFragment) fm.findFragmentByTag(TAG_ERROR_DIALOG_MANAGER); - if (fragment == null) { - fragment = new SupportManagerFragment(); - fm.beginTransaction().add(fragment, TAG_ERROR_DIALOG_MANAGER).commit(); - fm.executePendingTransactions(); - } - fragment.finishAfterDialog = finishAfterDialog; - fragment.argumentsForErrorDialog = argumentsForErrorDialog; - fragment.executionScope = executionScope; - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static class HoneycombManagerFragment extends android.app.Fragment { - protected boolean finishAfterDialog; - protected Bundle argumentsForErrorDialog; - private EventBus eventBus; - private Object executionScope; - - @Override - public void onResume() { - super.onResume(); - eventBus = ErrorDialogManager.factory.config.getEventBus(); - eventBus.register(this); - } - - @Override - public void onPause() { - eventBus.unregister(this); - super.onPause(); - } - - public void onEventMainThread(ThrowableFailureEvent event) { - if (!isInExecutionScope(executionScope, event)) { - return; - } - checkLogException(event); - - // Execute pending commits before finding to avoid multiple error fragments being shown - android.app.FragmentManager fm = getFragmentManager(); - fm.executePendingTransactions(); - - android.app.DialogFragment existingFragment = (android.app.DialogFragment) fm - .findFragmentByTag(TAG_ERROR_DIALOG); - if (existingFragment != null) { - // Just show the latest error - existingFragment.dismiss(); - } - - android.app.DialogFragment errorFragment = (android.app.DialogFragment) factory.prepareErrorFragment(event, - finishAfterDialog, argumentsForErrorDialog); - if (errorFragment != null) { - errorFragment.show(fm, TAG_ERROR_DIALOG); - } - } - - public static void attachTo(Activity activity, Object executionScope, boolean finishAfterDialog, Bundle argumentsForErrorDialog) { - android.app.FragmentManager fm = activity.getFragmentManager(); - HoneycombManagerFragment fragment = (HoneycombManagerFragment) fm - .findFragmentByTag(TAG_ERROR_DIALOG_MANAGER); - if (fragment == null) { - fragment = new HoneycombManagerFragment(); - fm.beginTransaction().add(fragment, TAG_ERROR_DIALOG_MANAGER).commit(); - fm.executePendingTransactions(); - } - fragment.finishAfterDialog = finishAfterDialog; - fragment.argumentsForErrorDialog = argumentsForErrorDialog; - fragment.executionScope = executionScope; - } - } - - /** Must be set by the application. */ - public static ErrorDialogFragmentFactory factory; - - protected static final String TAG_ERROR_DIALOG = "de.greenrobot.eventbus.error_dialog"; - protected static final String TAG_ERROR_DIALOG_MANAGER = "de.greenrobot.eventbus.error_dialog_manager"; - - public static final String KEY_TITLE = "de.greenrobot.eventbus.errordialog.title"; - public static final String KEY_MESSAGE = "de.greenrobot.eventbus.errordialog.message"; - public static final String KEY_FINISH_AFTER_DIALOG = "de.greenrobot.eventbus.errordialog.finish_after_dialog"; - public static final String KEY_ICON_ID = "de.greenrobot.eventbus.errordialog.icon_id"; - public static final String KEY_EVENT_TYPE_ON_CLOSE = "de.greenrobot.eventbus.errordialog.event_type_on_close"; - - /** Scope is limited to the activity's class. */ - public static void attachTo(Activity activity) { - attachTo(activity, false, null); - } - - /** Scope is limited to the activity's class. */ - public static void attachTo(Activity activity, boolean finishAfterDialog) { - attachTo(activity, finishAfterDialog, null); - } - - /** Scope is limited to the activity's class. */ - public static void attachTo(Activity activity, boolean finishAfterDialog, Bundle argumentsForErrorDialog) { - Object executionScope = activity.getClass(); - attachTo(activity, executionScope, finishAfterDialog, argumentsForErrorDialog); - } - - public static void attachTo(Activity activity, Object executionScope, boolean finishAfterDialog, Bundle argumentsForErrorDialog) { - if (factory == null) { - throw new RuntimeException("You must set the static factory field to configure error dialogs for your app."); - } - if (isSupportActivity(activity)) { - SupportManagerFragment.attachTo(activity, executionScope, finishAfterDialog, argumentsForErrorDialog); - } else { - HoneycombManagerFragment.attachTo(activity, executionScope, finishAfterDialog, argumentsForErrorDialog); - } - } - - private static boolean isSupportActivity(Activity activity) { - boolean isSupport = false; - for (Class c = activity.getClass().getSuperclass();; c = c.getSuperclass()) { - if (c == null) { - throw new RuntimeException("Illegal activity type: " + activity.getClass()); - } - String name = c.getName(); - if (name.equals("android.support.v4.app.FragmentActivity")) { - isSupport = true; - break; - } else if (name.startsWith("com.actionbarsherlock.app") - && (name.endsWith(".SherlockActivity") || name.endsWith(".SherlockListActivity") || name - .endsWith(".SherlockPreferenceActivity"))) { - throw new RuntimeException("Please use SherlockFragmentActivity. Illegal activity: " + name); - } else if (name.equals("android.app.Activity")) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - throw new RuntimeException( - "Illegal activity without fragment support. Either use Android 3.0+ or android.support.v4.app.FragmentActivity."); - } - break; - } - } - return isSupport; - } - - protected static void checkLogException(ThrowableFailureEvent event) { - if (factory.config.logExceptions) { - String tag = factory.config.tagForLoggingExceptions; - if (tag == null) { - tag = EventBus.TAG; - } - Log.i(tag, "Error dialog manager received exception", event.throwable); - } - } - - private static boolean isInExecutionScope(Object executionScope, ThrowableFailureEvent event) { - if (event != null) { - Object eventExecutionScope = event.getExecutionScope(); - if (eventExecutionScope != null && !eventExecutionScope.equals(executionScope)) { - // Event not in our scope, do nothing - return false; - } - } - return true; - } - -} diff --git a/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java b/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java index 9b7b80b6..1b339fba 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java +++ b/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java @@ -16,8 +16,7 @@ package org.greenrobot.eventbus.util; /** - * A generic failure event, which can be used by apps to propagate thrown exceptions. Also used in conjunction with - * {@link ErrorDialogManager}. + * A generic failure event, which can be used by apps to propagate thrown exceptions. */ public class ThrowableFailureEvent implements HasExecutionScope { protected final Throwable throwable; diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index ac036ae4..4ccdbb94 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -4,7 +4,8 @@ archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' version = '3.2.0' -sourceCompatibility = 1.7 +java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.targetCompatibility = JavaVersion.VERSION_1_8 dependencies { implementation project(':eventbus') diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 7123513f..6acf599c 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -1,11 +1,11 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.2.0' } } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 22e77647..5a3b2a57 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -1,11 +1,11 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.2.0' } } diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index f19e3b19..ea5c4dd5 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'java' -sourceCompatibility = 1.7 +java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.targetCompatibility = JavaVersion.VERSION_1_8 // we have tests in the main source set so they can be shared with the Android test module // to make Gradle pick them up, add the dir to the test source set diff --git a/EventBusTestSubscriberInJar/build.gradle b/EventBusTestSubscriberInJar/build.gradle index b75da33b..b091c149 100644 --- a/EventBusTestSubscriberInJar/build.gradle +++ b/EventBusTestSubscriberInJar/build.gradle @@ -2,7 +2,8 @@ apply plugin: 'java' group = 'de.greenrobot' version = '3.0.0' -sourceCompatibility = 1.7 +java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.targetCompatibility = JavaVersion.VERSION_1_8 configurations { provided diff --git a/build.gradle b/build.gradle index 543d3d9d..b29b352e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ buildscript { allprojects { repositories { - jcenter() mavenCentral() google() } @@ -21,5 +20,5 @@ if (JavaVersion.current().isJava8Compatible()) { } wrapper { - distributionType = org.gradle.api.tasks.wrapper.Wrapper.DistributionType.ALL + distributionType = Wrapper.DistributionType.ALL } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3a54a333..1f3fdbc5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 915357634a435ccf7324284335846c559a624d20 Mon Sep 17 00:00:00 2001 From: Andrei Dobrescu Date: Mon, 10 May 2021 16:46:34 +0300 Subject: [PATCH 089/128] android sdk proxy --- EventBus/build.gradle | 7 -- .../greenrobot/eventbus/EventBusBuilder.java | 21 +--- .../greenrobot/eventbus/HandlerPoster.java | 19 ++-- .../src/org/greenrobot/eventbus/Logger.java | 19 +--- .../eventbus/MainThreadSupport.java | 12 ++- .../eventbus/android/AndroidLogger.java | 39 +++----- .../eventbus/android/AndroidSDK.java | 97 +++++++++++++++++++ .../eventbus/meta/AbstractSubscriberInfo.java | 1 + .../util/ExceptionStackTraceUtils.java | 15 +++ 9 files changed, 150 insertions(+), 80 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java create mode 100644 EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java diff --git a/EventBus/build.gradle b/EventBus/build.gradle index af93b5f2..47456d58 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -6,13 +6,6 @@ version = '3.2.0' java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 -dependencies { - compileOnly 'com.google.android:android:4.1.1.4' - compileOnly 'com.google.android:android-test:4.1.1.4' - compileOnly 'com.google.android:annotations:4.1.1.4' - compileOnly 'com.google.android:support-v4:r7' -} - sourceSets { main { java { diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index c091e05e..57a9f40a 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -15,11 +15,8 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; - -import org.greenrobot.eventbus.android.AndroidLogger; +import org.greenrobot.eventbus.android.AndroidSDK; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -165,24 +162,14 @@ Logger getLogger() { MainThreadSupport getMainThreadSupport() { if (mainThreadSupport != null) { return mainThreadSupport; - } else if (AndroidLogger.isAndroidLogAvailable()) { - Object looperOrNull = getAndroidMainLooperOrNull(); - return looperOrNull == null ? null : - new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull); + } else if (AndroidSDK.isAvailable()) { + return new MainThreadSupport.AndroidHandlerMainThreadSupport( + AndroidSDK.get().looper, AndroidSDK.get().systemClock); } else { return null; } } - static Object getAndroidMainLooperOrNull() { - try { - return Looper.getMainLooper(); - } catch (RuntimeException e) { - // Not really a functional Android (e.g. "Stub!" maven dependencies) - return null; - } - } - /** * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be * done only once before the first usage of the default EventBus. diff --git a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java index 95309547..bd285432 100644 --- a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java @@ -15,21 +15,22 @@ */ package org.greenrobot.eventbus; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; +import org.greenrobot.eventbus.android.AndroidSDK; -public class HandlerPoster extends Handler implements Poster { +public class HandlerPoster extends AndroidSDK.Handler implements Poster { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; + private final AndroidSDK.SystemClock systemClock; private final EventBus eventBus; private boolean handlerActive; - protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { + protected HandlerPoster(EventBus eventBus, AndroidSDK.Looper looper, + AndroidSDK.SystemClock systemClock, + int maxMillisInsideHandleMessage) { super(looper); this.eventBus = eventBus; + this.systemClock = systemClock; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); } @@ -48,10 +49,10 @@ public void enqueue(Subscription subscription, Object event) { } @Override - public void handleMessage(Message msg) { + public void handleMessage(AndroidSDK.Message msg) { boolean rescheduled = false; try { - long started = SystemClock.uptimeMillis(); + long started = systemClock.uptimeMillis(); while (true) { PendingPost pendingPost = queue.poll(); if (pendingPost == null) { @@ -65,7 +66,7 @@ public void handleMessage(Message msg) { } } eventBus.invokeSubscriber(pendingPost); - long timeInMethod = SystemClock.uptimeMillis() - started; + long timeInMethod = systemClock.uptimeMillis() - started; if (timeInMethod >= maxMillisInsideHandleMessage) { if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index 69d1063a..cc7e5f43 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -15,9 +15,8 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; import org.greenrobot.eventbus.android.AndroidLogger; - +import org.greenrobot.eventbus.android.AndroidSDK; import java.util.logging.Level; public interface Logger { @@ -64,19 +63,11 @@ public void log(Level level, String msg, Throwable th) { class Default { public static Logger get() { - // also check main looper to see if we have "good" Android classes (not Stubs etc.) - return AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null - ? new AndroidLogger("EventBus") : - new Logger.SystemOutLogger(); - } - - static Object getAndroidMainLooperOrNull() { - try { - return Looper.getMainLooper(); - } catch (RuntimeException e) { - // Not really a functional Android (e.g. "Stub!" maven dependencies) - return null; + if (AndroidSDK.isAvailable()) { + return new AndroidLogger(AndroidSDK.get(), "EventBus"); } + + return new SystemOutLogger(); } } diff --git a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java index d5655533..d45ace2f 100644 --- a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java +++ b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java @@ -15,7 +15,7 @@ */ package org.greenrobot.eventbus; -import android.os.Looper; +import org.greenrobot.eventbus.android.AndroidSDK; /** * Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used. @@ -28,20 +28,22 @@ public interface MainThreadSupport { class AndroidHandlerMainThreadSupport implements MainThreadSupport { - private final Looper looper; + private final AndroidSDK.Looper looper; + private final AndroidSDK.SystemClock systemClock; - public AndroidHandlerMainThreadSupport(Looper looper) { + public AndroidHandlerMainThreadSupport(AndroidSDK.Looper looper, AndroidSDK.SystemClock systemClock) { this.looper = looper; + this.systemClock = systemClock; } @Override public boolean isMainThread() { - return looper == Looper.myLooper(); + return looper == AndroidSDK.Looper.myLooper(); } @Override public Poster createPoster(EventBus eventBus) { - return new HandlerPoster(eventBus, looper, 10); + return new HandlerPoster(eventBus, looper, systemClock, 10); } } diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java index fc14fe7d..f79a8893 100644 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java @@ -15,47 +15,30 @@ */ package org.greenrobot.eventbus.android; -import android.util.Log; - import org.greenrobot.eventbus.Logger; - +import org.greenrobot.eventbus.util.ExceptionStackTraceUtils; import java.util.logging.Level; public class AndroidLogger implements Logger { - private static final boolean ANDROID_LOG_AVAILABLE; - - static { - boolean android = false; - try { - android = Class.forName("android.util.Log") != null; - } catch (ClassNotFoundException e) { - // OK - } - ANDROID_LOG_AVAILABLE = android; - } - - public static boolean isAndroidLogAvailable() { - return ANDROID_LOG_AVAILABLE; - } - - + private final AndroidSDK androidSDK; private final String tag; - public AndroidLogger(String tag) { + public AndroidLogger(AndroidSDK androidSDK, String tag) { + this.androidSDK = androidSDK; this.tag = tag; } public void log(Level level, String msg) { if (level != Level.OFF) { - Log.println(mapLevel(level), tag, msg); + androidSDK.log.println(mapLevel(level), tag, msg); } } public void log(Level level, String msg, Throwable th) { if (level != Level.OFF) { // That's how Log does it internally - Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th)); + androidSDK.log.println(mapLevel(level), tag, msg + "\n" + ExceptionStackTraceUtils.getStackTraceAsString(th)); } } @@ -63,16 +46,16 @@ private int mapLevel(Level level) { int value = level.intValue(); if (value < 800) { // below INFO if (value < 500) { // below FINE - return Log.VERBOSE; + return androidSDK.log.getLogLevels().verbose; } else { - return Log.DEBUG; + return androidSDK.log.getLogLevels().debug; } } else if (value < 900) { // below WARNING - return Log.INFO; + return androidSDK.log.getLogLevels().info; } else if (value < 1000) { // below ERROR - return Log.WARN; + return androidSDK.log.getLogLevels().warn; } else { - return Log.ERROR; + return androidSDK.log.getLogLevels().error; } } } diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java new file mode 100644 index 00000000..65e4a801 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java @@ -0,0 +1,97 @@ +package org.greenrobot.eventbus.android; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@SuppressWarnings("TryWithIdenticalCatches") +public final class AndroidSDK +{ + + private static final AndroidSDK implementation; + + static { + boolean isAndroidSDKAvailable = false; + + try { + Class looperClass = Class.forName("android.os.Looper"); + Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper"); + Object mainLooper = getMainLooper.invoke(null); + isAndroidSDKAvailable = mainLooper != null; + } + catch (ClassNotFoundException ignored) {} + catch (NoSuchMethodException ignored) {} + catch (IllegalAccessException ignored) {} + catch (InvocationTargetException ignored) {} + + implementation = isAndroidSDKAvailable ? new AndroidSDK() : null; + } + + public static boolean isAvailable() { + return implementation != null; + } + + public static AndroidSDK get() { + return implementation; + } + + public final Log log = new Log(); + public static final class Log { + + //android.util.Log + //public static int println(int priority, java.lang.String tag, java.lang.String msg) { throw new RuntimeException("Stub!"); } + public void println(int priority, String tag, String msg) { + } + + public LogLevels getLogLevels() { + return new LogLevels(); + } + + public static final class LogLevels { + + public int verbose = 0; + public int debug = 0; + public int info = 0; + public int warn = 0; + public int error = 0; + } + } + + public final Looper looper = new Looper(); + public static final class Looper { + + public static Looper myLooper() { + return null; + } + } + + public static class Handler { + + public Handler(Looper looper) { + + } + + public Message obtainMessage() { + return new Message(); + } + + public boolean sendMessage(Message message) { + return true; + } + + public void handleMessage(Message message) { + + } + } + + public static class Message { + + } + + public final SystemClock systemClock = new SystemClock(); + public static class SystemClock { + + public long uptimeMillis() { + return 0; + } + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java index 9020c24b..c6432d49 100644 --- a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java +++ b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java @@ -22,6 +22,7 @@ import java.lang.reflect.Method; /** Base class for generated subscriber meta info classes created by annotation processing. */ +@SuppressWarnings({ "rawtypes", "TryWithIdenticalCatches", "unchecked" }) public abstract class AbstractSubscriberInfo implements SubscriberInfo { private final Class subscriberClass; private final Class superSubscriberInfoClass; diff --git a/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java b/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java new file mode 100644 index 00000000..4d0e1cae --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java @@ -0,0 +1,15 @@ +package org.greenrobot.eventbus.util; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class ExceptionStackTraceUtils { + + public static String getStackTraceAsString(Throwable ex) { + + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + ex.printStackTrace(printWriter); + return stringWriter.toString(); + } +} From b8a44d8b59b31080971b9ca6a2fb33796bc742d6 Mon Sep 17 00:00:00 2001 From: Andrei Dobrescu Date: Mon, 10 May 2021 18:01:06 +0300 Subject: [PATCH 090/128] android sdk proxy implementation --- .../src/org/greenrobot/eventbus/EventBus.java | 8 ++ .../greenrobot/eventbus/EventBusBuilder.java | 7 +- .../src/org/greenrobot/eventbus/Logger.java | 6 +- .../eventbus/MainThreadSupport.java | 24 ----- .../src/org/greenrobot/eventbus/Poster.java | 2 +- .../android/AndroidDependenciesDetector.java | 46 +++++++++ .../eventbus/android/AndroidLogger.java | 14 +-- .../eventbus/android/AndroidSDK.java | 97 ------------------- .../eventbus/android/AndroidSDKProxy.java | 41 ++++++++ EventBusPerformance/build.gradle | 1 + EventBusTest/build.gradle | 1 + .../eventbus/AndroidSDKProxyTest.java | 16 +++ .../eventbus/AndroidSDKAvailabilityTest.java | 16 +++ .../eventbus/EventBusBuilderTest.java | 1 - eventbus-android/.gitignore | 1 + eventbus-android/build.gradle | 29 ++++++ eventbus-android/consumer-rules.pro | 0 eventbus-android/proguard-rules.pro | 21 ++++ eventbus-android/src/main/AndroidManifest.xml | 4 + .../greenrobot/eventbus/HandlerPoster.java | 19 ++-- .../eventbus/android/AndroidLogProxyImpl.java | 36 +++++++ .../eventbus/android/AndroidSDKProxyImpl.java | 8 ++ .../DefaultAndroidMainThreadSupport.java | 20 ++++ settings.gradle | 3 +- 24 files changed, 273 insertions(+), 148 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java create mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java create mode 100644 EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java create mode 100644 eventbus-android/.gitignore create mode 100644 eventbus-android/build.gradle create mode 100644 eventbus-android/consumer-rules.pro create mode 100644 eventbus-android/proguard-rules.pro create mode 100644 eventbus-android/src/main/AndroidManifest.xml rename {EventBus/src => eventbus-android/src/main/java}/org/greenrobot/eventbus/HandlerPoster.java (81%) create mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java create mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java create mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index aa6c5981..9bf7d0b3 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -15,6 +15,7 @@ */ package org.greenrobot.eventbus; +import org.greenrobot.eventbus.android.AndroidDependenciesDetector; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; @@ -139,6 +140,13 @@ public EventBus() { * ThreadMode} and priority. */ public void register(Object subscriber) { + + if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.isAndroidSDKProxyImplAvailable()) { + //should crash user's app if the user (developer) has not imported the android compatibility library + throw new RuntimeException("Looks like you are using the latest version of EventBus on Android " + + "without importing the EventBus for Android compatibility library. Please import it on app/build.gradle!"); + } + Class subscriberClass = subscriber.getClass(); List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index 57a9f40a..a42277d6 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -15,7 +15,7 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.android.AndroidSDK; +import org.greenrobot.eventbus.android.AndroidSDKProxy; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; import java.util.ArrayList; import java.util.List; @@ -162,9 +162,8 @@ Logger getLogger() { MainThreadSupport getMainThreadSupport() { if (mainThreadSupport != null) { return mainThreadSupport; - } else if (AndroidSDK.isAvailable()) { - return new MainThreadSupport.AndroidHandlerMainThreadSupport( - AndroidSDK.get().looper, AndroidSDK.get().systemClock); + } else if (AndroidSDKProxy.isAvailable()) { + return AndroidSDKProxy.get().defaultMainThreadSupport; } else { return null; } diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index cc7e5f43..24a6a1cd 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -16,7 +16,7 @@ package org.greenrobot.eventbus; import org.greenrobot.eventbus.android.AndroidLogger; -import org.greenrobot.eventbus.android.AndroidSDK; +import org.greenrobot.eventbus.android.AndroidSDKProxy; import java.util.logging.Level; public interface Logger { @@ -63,8 +63,8 @@ public void log(Level level, String msg, Throwable th) { class Default { public static Logger get() { - if (AndroidSDK.isAvailable()) { - return new AndroidLogger(AndroidSDK.get(), "EventBus"); + if (AndroidSDKProxy.isAvailable()) { + return new AndroidLogger(AndroidSDKProxy.get(), "EventBus"); } return new SystemOutLogger(); diff --git a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java index d45ace2f..22605811 100644 --- a/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java +++ b/EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java @@ -15,8 +15,6 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.android.AndroidSDK; - /** * Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used. */ @@ -25,26 +23,4 @@ public interface MainThreadSupport { boolean isMainThread(); Poster createPoster(EventBus eventBus); - - class AndroidHandlerMainThreadSupport implements MainThreadSupport { - - private final AndroidSDK.Looper looper; - private final AndroidSDK.SystemClock systemClock; - - public AndroidHandlerMainThreadSupport(AndroidSDK.Looper looper, AndroidSDK.SystemClock systemClock) { - this.looper = looper; - this.systemClock = systemClock; - } - - @Override - public boolean isMainThread() { - return looper == AndroidSDK.Looper.myLooper(); - } - - @Override - public Poster createPoster(EventBus eventBus) { - return new HandlerPoster(eventBus, looper, systemClock, 10); - } - } - } diff --git a/EventBus/src/org/greenrobot/eventbus/Poster.java b/EventBus/src/org/greenrobot/eventbus/Poster.java index a69a078d..67cfd67c 100644 --- a/EventBus/src/org/greenrobot/eventbus/Poster.java +++ b/EventBus/src/org/greenrobot/eventbus/Poster.java @@ -20,7 +20,7 @@ * * @author William Ferguson */ -interface Poster { +public interface Poster { /** * Enqueue an event to be posted for a particular subscription. diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java new file mode 100644 index 00000000..fe7f125c --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java @@ -0,0 +1,46 @@ +package org.greenrobot.eventbus.android; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +@SuppressWarnings("TryWithIdenticalCatches") +public class AndroidDependenciesDetector { + + public static boolean isAndroidSDKAvailable() { + + try { + Class looperClass = Class.forName("android.os.Looper"); + Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper"); + Object mainLooper = getMainLooper.invoke(null); + return mainLooper != null; + } + catch (ClassNotFoundException ignored) {} + catch (NoSuchMethodException ignored) {} + catch (IllegalAccessException ignored) {} + catch (InvocationTargetException ignored) {} + + return false; + } + + public static boolean isAndroidSDKProxyImplAvailable() { + + try { + Class.forName("org.greenrobot.eventbus.android.AndroidSDKProxyImpl"); + return true; + } + catch (ClassNotFoundException ex) { + return false; + } + } + + public static AndroidSDKProxy instantiateAndroidSDKProxy() { + + try { + Class impl = Class.forName("org.greenrobot.eventbus.android.AndroidSDKProxyImpl"); + return (AndroidSDKProxy) impl.getConstructor().newInstance(); + } + catch (Throwable ex) { + return null; + } + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java index f79a8893..15f5e29d 100644 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java @@ -21,10 +21,10 @@ public class AndroidLogger implements Logger { - private final AndroidSDK androidSDK; + private final AndroidSDKProxy androidSDK; private final String tag; - public AndroidLogger(AndroidSDK androidSDK, String tag) { + public AndroidLogger(AndroidSDKProxy androidSDK, String tag) { this.androidSDK = androidSDK; this.tag = tag; } @@ -46,16 +46,16 @@ private int mapLevel(Level level) { int value = level.intValue(); if (value < 800) { // below INFO if (value < 500) { // below FINE - return androidSDK.log.getLogLevels().verbose; + return androidSDK.log.getVerboseLevelId(); } else { - return androidSDK.log.getLogLevels().debug; + return androidSDK.log.getDebugLevelId(); } } else if (value < 900) { // below WARNING - return androidSDK.log.getLogLevels().info; + return androidSDK.log.getInfoLevelId(); } else if (value < 1000) { // below ERROR - return androidSDK.log.getLogLevels().warn; + return androidSDK.log.getWarnLevelId(); } else { - return androidSDK.log.getLogLevels().error; + return androidSDK.log.getErrorLevelId(); } } } diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java deleted file mode 100644 index 65e4a801..00000000 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDK.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.greenrobot.eventbus.android; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -@SuppressWarnings("TryWithIdenticalCatches") -public final class AndroidSDK -{ - - private static final AndroidSDK implementation; - - static { - boolean isAndroidSDKAvailable = false; - - try { - Class looperClass = Class.forName("android.os.Looper"); - Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper"); - Object mainLooper = getMainLooper.invoke(null); - isAndroidSDKAvailable = mainLooper != null; - } - catch (ClassNotFoundException ignored) {} - catch (NoSuchMethodException ignored) {} - catch (IllegalAccessException ignored) {} - catch (InvocationTargetException ignored) {} - - implementation = isAndroidSDKAvailable ? new AndroidSDK() : null; - } - - public static boolean isAvailable() { - return implementation != null; - } - - public static AndroidSDK get() { - return implementation; - } - - public final Log log = new Log(); - public static final class Log { - - //android.util.Log - //public static int println(int priority, java.lang.String tag, java.lang.String msg) { throw new RuntimeException("Stub!"); } - public void println(int priority, String tag, String msg) { - } - - public LogLevels getLogLevels() { - return new LogLevels(); - } - - public static final class LogLevels { - - public int verbose = 0; - public int debug = 0; - public int info = 0; - public int warn = 0; - public int error = 0; - } - } - - public final Looper looper = new Looper(); - public static final class Looper { - - public static Looper myLooper() { - return null; - } - } - - public static class Handler { - - public Handler(Looper looper) { - - } - - public Message obtainMessage() { - return new Message(); - } - - public boolean sendMessage(Message message) { - return true; - } - - public void handleMessage(Message message) { - - } - } - - public static class Message { - - } - - public final SystemClock systemClock = new SystemClock(); - public static class SystemClock { - - public long uptimeMillis() { - return 0; - } - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java new file mode 100644 index 00000000..ce56f99e --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java @@ -0,0 +1,41 @@ +package org.greenrobot.eventbus.android; + +import org.greenrobot.eventbus.MainThreadSupport; + +public abstract class AndroidSDKProxy { + + private static final AndroidSDKProxy implementation; + + static { + implementation = AndroidDependenciesDetector.isAndroidSDKAvailable() + ? AndroidDependenciesDetector.instantiateAndroidSDKProxy() + : null; + } + + public static boolean isAvailable() { + return implementation != null; + } + + public static AndroidSDKProxy get() { + return implementation; + } + + public final LogProxy log; + public final MainThreadSupport defaultMainThreadSupport; + + public AndroidSDKProxy(LogProxy log, MainThreadSupport defaultMainThreadSupport) { + this.log = log; + this.defaultMainThreadSupport = defaultMainThreadSupport; + } + + interface LogProxy { + + void println(int priority, String tag, String msg); + + int getVerboseLevelId(); + int getDebugLevelId(); + int getInfoLevelId(); + int getWarnLevelId(); + int getErrorLevelId(); + } +} diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 6acf599c..0a51db7a 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -13,6 +13,7 @@ apply plugin: 'com.android.application' dependencies { implementation project(':eventbus') + implementation project(':eventbus-android') annotationProcessor project(':eventbus-annotation-processor') implementation 'com.squareup:otto:1.3.8' } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 5a3b2a57..740389ad 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -13,6 +13,7 @@ apply plugin: 'com.android.application' dependencies { androidTestImplementation project(':eventbus') + androidTestImplementation project(':eventbus-android') androidTestImplementation project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') // Trying to repro bug: diff --git a/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java b/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java new file mode 100644 index 00000000..7383d00b --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java @@ -0,0 +1,16 @@ +package org.greenrobot.eventbus; + +import org.greenrobot.eventbus.android.AndroidSDKProxy; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class AndroidSDKProxyTest { + + @Test + public void shouldBeAvailable() { + assertTrue(AndroidSDKProxy.isAvailable()); + assertNotNull(AndroidSDKProxy.get()); + } +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java new file mode 100644 index 00000000..f35a7b05 --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java @@ -0,0 +1,16 @@ +package org.greenrobot.eventbus; + +import org.greenrobot.eventbus.android.AndroidSDKProxy; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +public class AndroidSDKAvailabilityTest { + + @Test + public void shouldNotBeAvailable() { + assertFalse(AndroidSDKProxy.isAvailable()); + assertNull(AndroidSDKProxy.get()); + } +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java index 05a60362..16f13255 100644 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java @@ -18,7 +18,6 @@ import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** diff --git a/eventbus-android/.gitignore b/eventbus-android/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/eventbus-android/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle new file mode 100644 index 00000000..e20de7a2 --- /dev/null +++ b/eventbus-android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.2.0' + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 30 + + defaultConfig { + minSdkVersion 7 + targetSdkVersion 30 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation project(":eventbus") +} diff --git a/eventbus-android/consumer-rules.pro b/eventbus-android/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/eventbus-android/proguard-rules.pro b/eventbus-android/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/eventbus-android/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/eventbus-android/src/main/AndroidManifest.xml b/eventbus-android/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e4f0b52b --- /dev/null +++ b/eventbus-android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java similarity index 81% rename from EventBus/src/org/greenrobot/eventbus/HandlerPoster.java rename to eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java index bd285432..71158e2d 100644 --- a/EventBus/src/org/greenrobot/eventbus/HandlerPoster.java +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java @@ -15,22 +15,21 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.android.AndroidSDK; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; -public class HandlerPoster extends AndroidSDK.Handler implements Poster { +public class HandlerPoster extends Handler implements Poster { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; - private final AndroidSDK.SystemClock systemClock; private final EventBus eventBus; private boolean handlerActive; - protected HandlerPoster(EventBus eventBus, AndroidSDK.Looper looper, - AndroidSDK.SystemClock systemClock, - int maxMillisInsideHandleMessage) { + public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { super(looper); this.eventBus = eventBus; - this.systemClock = systemClock; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); } @@ -49,10 +48,10 @@ public void enqueue(Subscription subscription, Object event) { } @Override - public void handleMessage(AndroidSDK.Message msg) { + public void handleMessage(Message msg) { boolean rescheduled = false; try { - long started = systemClock.uptimeMillis(); + long started = SystemClock.uptimeMillis(); while (true) { PendingPost pendingPost = queue.poll(); if (pendingPost == null) { @@ -66,7 +65,7 @@ public void handleMessage(AndroidSDK.Message msg) { } } eventBus.invokeSubscriber(pendingPost); - long timeInMethod = systemClock.uptimeMillis() - started; + long timeInMethod = SystemClock.uptimeMillis() - started; if (timeInMethod >= maxMillisInsideHandleMessage) { if (!sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java new file mode 100644 index 00000000..65dc06ec --- /dev/null +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java @@ -0,0 +1,36 @@ +package org.greenrobot.eventbus.android; + +import android.util.Log; + +public class AndroidLogProxyImpl implements AndroidSDKProxy.LogProxy { + + @Override + public void println(int priority, String tag, String msg) { + Log.println(priority, tag, msg); + } + + @Override + public int getVerboseLevelId() { + return Log.VERBOSE; + } + + @Override + public int getDebugLevelId() { + return Log.DEBUG; + } + + @Override + public int getInfoLevelId() { + return Log.INFO; + } + + @Override + public int getWarnLevelId() { + return Log.WARN; + } + + @Override + public int getErrorLevelId() { + return Log.ERROR; + } +} diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java new file mode 100644 index 00000000..40a80b25 --- /dev/null +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java @@ -0,0 +1,8 @@ +package org.greenrobot.eventbus.android; + +public class AndroidSDKProxyImpl extends AndroidSDKProxy { + + public AndroidSDKProxyImpl() { + super(new AndroidLogProxyImpl(), new DefaultAndroidMainThreadSupport()); + } +} diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java new file mode 100644 index 00000000..13339465 --- /dev/null +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java @@ -0,0 +1,20 @@ +package org.greenrobot.eventbus.android; + +import android.os.Looper; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.HandlerPoster; +import org.greenrobot.eventbus.MainThreadSupport; +import org.greenrobot.eventbus.Poster; + +public class DefaultAndroidMainThreadSupport implements MainThreadSupport { + + @Override + public boolean isMainThread() { + return true; + } + + @Override + public Poster createPoster(EventBus eventBus) { + return new HandlerPoster(eventBus, Looper.getMainLooper(), 10); + } +} diff --git a/settings.gradle b/settings.gradle index c25cd47e..44670236 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,7 @@ include ':EventBusTestJava' include ':EventBusTest' include ':EventBusTestSubscriberInJar' include ':EventBusPerformance' +include ':eventbus-android' project(":EventBus").name = "eventbus" -project(":EventBusAnnotationProcessor").name = "eventbus-annotation-processor" \ No newline at end of file +project(":EventBusAnnotationProcessor").name = "eventbus-annotation-processor" From 21c6b5602100ef03489502080b6f74edd61e1a53 Mon Sep 17 00:00:00 2001 From: Andrei Dobrescu Date: Mon, 10 May 2021 18:59:12 +0300 Subject: [PATCH 091/128] refactorings --- .../src/org/greenrobot/eventbus/EventBus.java | 2 +- .../greenrobot/eventbus/EventBusBuilder.java | 6 +-- .../src/org/greenrobot/eventbus/Logger.java | 7 ++-- .../eventbus/android/AndroidComponents.java | 31 ++++++++++++++ .../android/AndroidDependenciesDetector.java | 12 +++--- .../eventbus/android/AndroidSDKProxy.java | 41 ------------------- .../AndroidComponentsAvailabilityTest.java | 16 ++++++++ .../eventbus/AndroidSDKProxyTest.java | 16 -------- ...droidComponentsAvailabilityOnJavaTest.java | 17 ++++++++ .../eventbus/AndroidSDKAvailabilityTest.java | 16 -------- .../android/AndroidComponentsImpl.java | 8 ++++ .../eventbus/android/AndroidLogProxyImpl.java | 36 ---------------- .../eventbus/android/AndroidLogger.java | 19 ++++----- .../eventbus/android/AndroidSDKProxyImpl.java | 8 ---- 14 files changed, 95 insertions(+), 140 deletions(-) create mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java delete mode 100644 EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java create mode 100644 EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java delete mode 100644 EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java create mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java delete mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java create mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java delete mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java rename {EventBus/src => eventbus-android/src/main/java}/org/greenrobot/eventbus/android/AndroidLogger.java (71%) delete mode 100644 eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 9bf7d0b3..25f93823 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -141,7 +141,7 @@ public EventBus() { */ public void register(Object subscriber) { - if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.isAndroidSDKProxyImplAvailable()) { + if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) { //should crash user's app if the user (developer) has not imported the android compatibility library throw new RuntimeException("Looks like you are using the latest version of EventBus on Android " + "without importing the EventBus for Android compatibility library. Please import it on app/build.gradle!"); diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index a42277d6..ff4a5f80 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -15,7 +15,7 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.android.AndroidSDKProxy; +import org.greenrobot.eventbus.android.AndroidComponents; import org.greenrobot.eventbus.meta.SubscriberInfoIndex; import java.util.ArrayList; import java.util.List; @@ -162,8 +162,8 @@ Logger getLogger() { MainThreadSupport getMainThreadSupport() { if (mainThreadSupport != null) { return mainThreadSupport; - } else if (AndroidSDKProxy.isAvailable()) { - return AndroidSDKProxy.get().defaultMainThreadSupport; + } else if (AndroidComponents.areAvailable()) { + return AndroidComponents.get().defaultMainThreadSupport; } else { return null; } diff --git a/EventBus/src/org/greenrobot/eventbus/Logger.java b/EventBus/src/org/greenrobot/eventbus/Logger.java index 24a6a1cd..e9ec8e88 100644 --- a/EventBus/src/org/greenrobot/eventbus/Logger.java +++ b/EventBus/src/org/greenrobot/eventbus/Logger.java @@ -15,8 +15,7 @@ */ package org.greenrobot.eventbus; -import org.greenrobot.eventbus.android.AndroidLogger; -import org.greenrobot.eventbus.android.AndroidSDKProxy; +import org.greenrobot.eventbus.android.AndroidComponents; import java.util.logging.Level; public interface Logger { @@ -63,8 +62,8 @@ public void log(Level level, String msg, Throwable th) { class Default { public static Logger get() { - if (AndroidSDKProxy.isAvailable()) { - return new AndroidLogger(AndroidSDKProxy.get(), "EventBus"); + if (AndroidComponents.areAvailable()) { + return AndroidComponents.get().logger; } return new SystemOutLogger(); diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java new file mode 100644 index 00000000..7138b6d9 --- /dev/null +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java @@ -0,0 +1,31 @@ +package org.greenrobot.eventbus.android; + +import org.greenrobot.eventbus.Logger; +import org.greenrobot.eventbus.MainThreadSupport; + +public abstract class AndroidComponents { + + private static final AndroidComponents implementation; + + static { + implementation = AndroidDependenciesDetector.isAndroidSDKAvailable() + ? AndroidDependenciesDetector.instantiateAndroidComponents() + : null; + } + + public static boolean areAvailable() { + return implementation != null; + } + + public static AndroidComponents get() { + return implementation; + } + + public final Logger logger; + public final MainThreadSupport defaultMainThreadSupport; + + public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) { + this.logger = logger; + this.defaultMainThreadSupport = defaultMainThreadSupport; + } +} diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java index fe7f125c..1783f143 100644 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java +++ b/EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java @@ -22,10 +22,12 @@ public static boolean isAndroidSDKAvailable() { return false; } - public static boolean isAndroidSDKProxyImplAvailable() { + private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME = "org.greenrobot.eventbus.android.AndroidComponentsImpl"; + + public static boolean areAndroidComponentsAvailable() { try { - Class.forName("org.greenrobot.eventbus.android.AndroidSDKProxyImpl"); + Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME); return true; } catch (ClassNotFoundException ex) { @@ -33,11 +35,11 @@ public static boolean isAndroidSDKProxyImplAvailable() { } } - public static AndroidSDKProxy instantiateAndroidSDKProxy() { + public static AndroidComponents instantiateAndroidComponents() { try { - Class impl = Class.forName("org.greenrobot.eventbus.android.AndroidSDKProxyImpl"); - return (AndroidSDKProxy) impl.getConstructor().newInstance(); + Class impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME); + return (AndroidComponents) impl.getConstructor().newInstance(); } catch (Throwable ex) { return null; diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java b/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java deleted file mode 100644 index ce56f99e..00000000 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidSDKProxy.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.greenrobot.eventbus.android; - -import org.greenrobot.eventbus.MainThreadSupport; - -public abstract class AndroidSDKProxy { - - private static final AndroidSDKProxy implementation; - - static { - implementation = AndroidDependenciesDetector.isAndroidSDKAvailable() - ? AndroidDependenciesDetector.instantiateAndroidSDKProxy() - : null; - } - - public static boolean isAvailable() { - return implementation != null; - } - - public static AndroidSDKProxy get() { - return implementation; - } - - public final LogProxy log; - public final MainThreadSupport defaultMainThreadSupport; - - public AndroidSDKProxy(LogProxy log, MainThreadSupport defaultMainThreadSupport) { - this.log = log; - this.defaultMainThreadSupport = defaultMainThreadSupport; - } - - interface LogProxy { - - void println(int priority, String tag, String msg); - - int getVerboseLevelId(); - int getDebugLevelId(); - int getInfoLevelId(); - int getWarnLevelId(); - int getErrorLevelId(); - } -} diff --git a/EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java b/EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java new file mode 100644 index 00000000..15ae3d80 --- /dev/null +++ b/EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java @@ -0,0 +1,16 @@ +package org.greenrobot.eventbus; + +import org.greenrobot.eventbus.android.AndroidComponents; +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class AndroidComponentsAvailabilityTest { + + @Test + public void shouldBeAvailable() { + assertTrue(AndroidComponents.areAvailable()); + assertNotNull(AndroidComponents.get()); + } +} diff --git a/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java b/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java deleted file mode 100644 index 7383d00b..00000000 --- a/EventBusTest/src/org/greenrobot/eventbus/AndroidSDKProxyTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.greenrobot.eventbus; - -import org.greenrobot.eventbus.android.AndroidSDKProxy; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class AndroidSDKProxyTest { - - @Test - public void shouldBeAvailable() { - assertTrue(AndroidSDKProxy.isAvailable()); - assertNotNull(AndroidSDKProxy.get()); - } -} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java new file mode 100644 index 00000000..cc2e69ff --- /dev/null +++ b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java @@ -0,0 +1,17 @@ +package org.greenrobot.eventbus; + +import org.greenrobot.eventbus.android.AndroidComponents; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +public class AndroidComponentsAvailabilityOnJavaTest +{ + + @Test + public void shouldNotBeAvailable() { + assertFalse(AndroidComponents.areAvailable()); + assertNull(AndroidComponents.get()); + } +} diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java deleted file mode 100644 index f35a7b05..00000000 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidSDKAvailabilityTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.greenrobot.eventbus; - -import org.greenrobot.eventbus.android.AndroidSDKProxy; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; - -public class AndroidSDKAvailabilityTest { - - @Test - public void shouldNotBeAvailable() { - assertFalse(AndroidSDKProxy.isAvailable()); - assertNull(AndroidSDKProxy.get()); - } -} diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java new file mode 100644 index 00000000..afcb4af0 --- /dev/null +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java @@ -0,0 +1,8 @@ +package org.greenrobot.eventbus.android; + +public class AndroidComponentsImpl extends AndroidComponents { + + public AndroidComponentsImpl() { + super(new AndroidLogger("EventBus"), new DefaultAndroidMainThreadSupport()); + } +} diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java deleted file mode 100644 index 65dc06ec..00000000 --- a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogProxyImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.greenrobot.eventbus.android; - -import android.util.Log; - -public class AndroidLogProxyImpl implements AndroidSDKProxy.LogProxy { - - @Override - public void println(int priority, String tag, String msg) { - Log.println(priority, tag, msg); - } - - @Override - public int getVerboseLevelId() { - return Log.VERBOSE; - } - - @Override - public int getDebugLevelId() { - return Log.DEBUG; - } - - @Override - public int getInfoLevelId() { - return Log.INFO; - } - - @Override - public int getWarnLevelId() { - return Log.WARN; - } - - @Override - public int getErrorLevelId() { - return Log.ERROR; - } -} diff --git a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java similarity index 71% rename from EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java rename to eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java index 15f5e29d..45fd6e4e 100644 --- a/EventBus/src/org/greenrobot/eventbus/android/AndroidLogger.java +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java @@ -15,30 +15,29 @@ */ package org.greenrobot.eventbus.android; +import android.util.Log; import org.greenrobot.eventbus.Logger; import org.greenrobot.eventbus.util.ExceptionStackTraceUtils; import java.util.logging.Level; public class AndroidLogger implements Logger { - private final AndroidSDKProxy androidSDK; private final String tag; - public AndroidLogger(AndroidSDKProxy androidSDK, String tag) { - this.androidSDK = androidSDK; + public AndroidLogger(String tag) { this.tag = tag; } public void log(Level level, String msg) { if (level != Level.OFF) { - androidSDK.log.println(mapLevel(level), tag, msg); + Log.println(mapLevel(level), tag, msg); } } public void log(Level level, String msg, Throwable th) { if (level != Level.OFF) { // That's how Log does it internally - androidSDK.log.println(mapLevel(level), tag, msg + "\n" + ExceptionStackTraceUtils.getStackTraceAsString(th)); + Log.println(mapLevel(level), tag, msg + "\n" + ExceptionStackTraceUtils.getStackTraceAsString(th)); } } @@ -46,16 +45,16 @@ private int mapLevel(Level level) { int value = level.intValue(); if (value < 800) { // below INFO if (value < 500) { // below FINE - return androidSDK.log.getVerboseLevelId(); + return Log.VERBOSE; } else { - return androidSDK.log.getDebugLevelId(); + return Log.DEBUG; } } else if (value < 900) { // below WARNING - return androidSDK.log.getInfoLevelId(); + return Log.INFO; } else if (value < 1000) { // below ERROR - return androidSDK.log.getWarnLevelId(); + return Log.WARN; } else { - return androidSDK.log.getErrorLevelId(); + return Log.ERROR; } } } diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java deleted file mode 100644 index 40a80b25..00000000 --- a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidSDKProxyImpl.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.greenrobot.eventbus.android; - -public class AndroidSDKProxyImpl extends AndroidSDKProxy { - - public AndroidSDKProxyImpl() { - super(new AndroidLogProxyImpl(), new DefaultAndroidMainThreadSupport()); - } -} From 53f24c58a36bbe065b5bc26141c1e17016f45a16 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 21 Jun 2021 15:03:18 +0200 Subject: [PATCH 092/128] Update Gradle [6.7.1 -> 6.8.3] --- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 31 ++++++++++------------- gradlew.bat | 25 +++++------------- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 23334 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 WDWbsF$p{Gi@ZUasP|4|kdH)CXgbPdn delta 19998 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1f3fdbc5..8cf6eb5a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfd..4f906e0c 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -154,19 +156,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -175,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a14..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From a396776d0aa29a8ea7f5bc1c0edf5a1952171231 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 21 Jun 2021 15:06:20 +0200 Subject: [PATCH 093/128] Downgrade Android plugin to work with IntelliJ IDEA. --- EventBusPerformance/build.gradle | 3 ++- EventBusTest/build.gradle | 3 ++- eventbus-android/build.gradle | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 0a51db7a..7fc3eea4 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -5,7 +5,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1 + classpath 'com.android.tools.build:gradle:4.1.3' } } diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 740389ad..8fc33ece 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -5,7 +5,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1 + classpath 'com.android.tools.build:gradle:4.1.3' } } diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index e20de7a2..328896af 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -5,7 +5,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1 + classpath 'com.android.tools.build:gradle:4.1.3' } } From 1d5e79aa5d7bc1efdf61e85cb14ad6e58bda0ab7 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 21 Jun 2021 15:10:01 +0200 Subject: [PATCH 094/128] CI: use GitHub Actions. --- .github/workflows/gradle.yml | 42 ++++++++++++++++++++++++++++++++++++ .travis.yml | 35 ------------------------------ 2 files changed, 42 insertions(+), 35 deletions(-) create mode 100644 .github/workflows/gradle.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 00000000..1ac038ec --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,42 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + pull_request: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Gradle Info + run: ./gradlew -version + - name: Build with Gradle + run: ./gradlew build + - name: Cleanup Gradle Cache + # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. + # Restoring these files from a GitHub Actions cache might cause problems for future builds. + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b22ae054..00000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -sudo: false -language: android -jdk: - - oraclejdk8 - -# http://docs.travis-ci.com/user/languages/android/ -android: - components: - - build-tools-28.0.3 - - android-26 - licenses: - - 'android-sdk-license-.+' - -before_script: - - chmod +x gradlew -# - echo no | android create avd --force -n test -t android-10 --abi armeabi -# - emulator -avd test -no-skin -no-audio -no-window & -# - android-wait-for-emulator -# - adb shell input keyevent 82 & - -# Currently connectedCheck fails, so don't run unit test on Emulator for now. Issue: -# com.android.builder.testing.ConnectedDevice > hasTests[test(AVD) - 2.3.3] FAILED -# No tests found. - -script: - - TERM=dumb ./gradlew check - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - - $HOME/.android/build-cache From b74299b71799cc40bc1c32e51bb4fc46cc295804 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 21 Jun 2021 15:31:04 +0200 Subject: [PATCH 095/128] Embed ProGuard rules for Android. --- eventbus-android/build.gradle | 2 ++ eventbus-android/consumer-rules.pro | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index 328896af..f2818f0e 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -18,6 +18,8 @@ android { defaultConfig { minSdkVersion 7 targetSdkVersion 30 + + consumerProguardFiles "consumer-rules.pro" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 diff --git a/eventbus-android/consumer-rules.pro b/eventbus-android/consumer-rules.pro index e69de29b..06d028c3 100644 --- a/eventbus-android/consumer-rules.pro +++ b/eventbus-android/consumer-rules.pro @@ -0,0 +1,10 @@ +-keepattributes *Annotation* +-keepclassmembers class * { + @org.greenrobot.eventbus.Subscribe ; +} +-keep enum org.greenrobot.eventbus.ThreadMode { *; } + +# And if you use AsyncExecutor: +-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { + (java.lang.Throwable); +} From 3f4ee0cc6ddc5f6ba99ecea7da0dd431103b5341 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 21 Jun 2021 15:37:24 +0200 Subject: [PATCH 096/128] Use common compile SDK for eventbus-android. --- build.gradle | 2 +- eventbus-android/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b29b352e..30e30418 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - _compileSdkVersion = 26 // When updating, don't forget to adjust .travis.yml. + _compileSdkVersion = 30 // Android 11 (R) } } diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index f2818f0e..cdb59fb9 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -13,11 +13,11 @@ buildscript { apply plugin: 'com.android.library' android { - compileSdkVersion 30 + compileSdkVersion _compileSdkVersion defaultConfig { minSdkVersion 7 - targetSdkVersion 30 + targetSdkVersion 30 // Android 11 (R) consumerProguardFiles "consumer-rules.pro" } From 51a5c05bed252145e7ebe29e8ed7f8d6b8a1b329 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 14:17:00 +0200 Subject: [PATCH 097/128] Switch to maven-publish plugin. --- EventBus/build.gradle | 37 +++++------ EventBusAnnotationProcessor/build.gradle | 37 +++++------ build.gradle | 24 +++++++ eventbus-android/build.gradle | 28 ++++++++ gradle/publish.gradle | 83 ++++++------------------ 5 files changed, 106 insertions(+), 103 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index 47456d58..ea96d39c 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'java' -archivesBaseName = 'eventbus' group = 'org.greenrobot' version = '3.2.0' java.sourceCompatibility = JavaVersion.VERSION_1_8 @@ -15,8 +14,6 @@ sourceSets { } } -apply from: rootProject.file("gradle/publish.gradle") - javadoc { failOnError = false title = "EventBus ${version} API" @@ -24,30 +21,30 @@ javadoc { } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier.set("javadoc") from 'build/docs/javadoc' } task sourcesJar(type: Jar) { + archiveClassifier.set("sources") from sourceSets.main.allSource - classifier = 'sources' -} - -artifacts { - archives jar - archives javadocJar - archives sourcesJar } -uploadArchives { - repositories { - mavenDeployer { - // Common setup is defined in publish.gradle. - - pom.project { - name 'EventBus' - description 'EventBus is a publish/subscribe event bus optimized for Android.' - } +apply from: rootProject.file("gradle/publish.gradle") +// Set project-specific properties +afterEvaluate { + publishing.publications { + mavenJava(MavenPublication) { + artifactId = "eventbus-java" + + from components.java + artifact javadocJar + artifact sourcesJar + pom { + name = "EventBus" + description = "EventBus is a publish/subscribe event bus optimized for Android." + packaging = "jar" + } } } } diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 4ccdbb94..d5eb89e6 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'java' -archivesBaseName = 'eventbus-annotation-processor' group = 'org.greenrobot' version = '3.2.0' @@ -28,38 +27,36 @@ sourceSets { } } -apply from: rootProject.file("gradle/publish.gradle") - javadoc { title = "EventBus Annotation Processor ${version} API" options.bottom = 'Available under the Apache License, Version 2.0 - Copyright © 2015-2020 greenrobot.org. All Rights Reserved.' } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier.set("javadoc") from 'build/docs/javadoc' } task sourcesJar(type: Jar) { + archiveClassifier.set("sources") from sourceSets.main.allSource - classifier = 'sources' -} - -artifacts { - archives jar - archives javadocJar - archives sourcesJar } -uploadArchives { - repositories { - mavenDeployer { - // Common setup is defined in publish.gradle. - - pom.project { - name 'EventBus Annotation Processor' - description 'Precompiler for EventBus Annotations.' +apply from: rootProject.file("gradle/publish.gradle") +// Set project-specific properties +afterEvaluate { + publishing.publications { + mavenJava(MavenPublication) { + artifactId = "eventbus-annotation-processor" + + from components.java + artifact javadocJar + artifact sourcesJar + pom { + name = "EventBus Annotation Processor" + description = "Precompiler for EventBus Annotations." + packaging = "jar" } } } -} \ No newline at end of file +} diff --git a/build.gradle b/build.gradle index 30e30418..d575a7a5 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,13 @@ buildscript { ext { _compileSdkVersion = 30 // Android 11 (R) } + repositories { + mavenCentral() + maven { url "https://plugins.gradle.org/m2/" } + } + dependencies { + classpath "io.github.gradle-nexus:publish-plugin:1.1.0" + } } allprojects { @@ -22,3 +29,20 @@ if (JavaVersion.current().isJava8Compatible()) { wrapper { distributionType = Wrapper.DistributionType.ALL } + +// Plugin to publish to Central https://github.com/gradle-nexus/publish-plugin/ +// This plugin ensures a separate, named staging repo is created for each build when publishing. +apply plugin: "io.github.gradle-nexus.publish-plugin" +nexusPublishing { + repositories { + sonatype { + if (project.hasProperty("sonatypeUsername") && project.hasProperty("sonatypePassword")) { + println('nexusPublishing credentials supplied.') + username = sonatypeUsername + password = sonatypePassword + } else { + println('nexusPublishing credentials NOT supplied.') + } + } + } +} diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index cdb59fb9..601e0c9a 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -12,6 +12,9 @@ buildscript { apply plugin: 'com.android.library' +group = 'org.greenrobot' +version = '3.2.0' + android { compileSdkVersion _compileSdkVersion @@ -30,3 +33,28 @@ android { dependencies { implementation project(":eventbus") } + +task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + archiveClassifier.set("sources") +} + +apply from: rootProject.file("gradle/publish.gradle") +// Set project-specific properties +// https://developer.android.com/studio/build/maven-publish-plugin +afterEvaluate { + publishing.publications { + mavenJava(MavenPublication) { + artifactId = "eventbus" + + from components.release + artifact sourcesJar + + pom { + name = "EventBus" + description = "EventBus is a publish/subscribe event bus optimized for Android." + packaging = "aar" + } + } + } +} diff --git a/gradle/publish.gradle b/gradle/publish.gradle index a887ff3a..5420dd44 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -1,18 +1,8 @@ // Configures common publishing settings. -apply plugin: "maven" +apply plugin: "maven-publish" apply plugin: "signing" -configurations { - deployerJars -} - -dependencies { - // Using an older version to remain compatible with Wagon API used by Gradle/Maven. - deployerJars 'org.apache.maven.wagon:wagon-webdav-jackrabbit:3.2.0' - deployerJars 'org.apache.maven.wagon:wagon-ftp:3.3.2' -} - signing { if (project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && project.hasProperty('signing.secretKeyRingFile')) { @@ -22,71 +12,38 @@ signing { } } -// Use afterEvaluate or dependencies might be lost in the generated POM. -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - def preferredRepo = project.findProperty('preferredRepo') - println "preferredRepo=$preferredRepo" - - if (preferredRepo == 'local') { - repository url: repositories.mavenLocal().url - } else if (preferredRepo != null - && project.hasProperty('preferredUsername') - && project.hasProperty('preferredPassword')) { - configuration = configurations.deployerJars - repository(url: repositoryUrl) { - authentication(userName: preferredUsername, password: preferredPassword) - } - } else if (project.hasProperty('sonatypeUsername') - && project.hasProperty('sonatypePassword')) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - def isSnapshot = version.endsWith('-SNAPSHOT') - def sonatypeRepositoryUrl = isSnapshot - ? "https://oss.sonatype.org/content/repositories/snapshots/" - : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - repository(url: sonatypeRepositoryUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - } else { - println "Deployment settings missing/incomplete for ${project.name}." - } - - // Common properties, projects still need to set name and description. - pom.project { - packaging 'jar' - url 'https://greenrobot.org/eventbus/' +// https://developer.android.com/studio/build/maven-publish-plugin +// Because the Android components are created only during the afterEvaluate phase, you must +// configure your publications using the afterEvaluate() lifecycle method. +afterEvaluate { + publishing { + publications { + // Note: Sonatype repo created by publish-plugin, see root build.gradle. + mavenJava(MavenPublication) { + pom { + url = "https://greenrobot.org/eventbus/" scm { - url 'https://github.com/greenrobot/EventBus' - connection 'scm:git@github.com:greenrobot/EventBus.git' - developerConnection 'scm:git@github.com:greenrobot/EventBus.git' - } - - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } + connection = "scm:git@github.com:greenrobot/EventBus.git" + developerConnection = "scm:git@github.com:greenrobot/EventBus.git" + url = "https://github.com/greenrobot/EventBus" } developers { developer { - id 'greenrobot' - name 'greenrobot' + id = "greenrobot" + name = "greenrobot" } } issueManagement { - system 'GitHub Issues' - url 'https://github.com/greenrobot/EventBus/issues' + system = "https://github.com/greenrobot/EventBus/issues" + url = "https://github.com/greenrobot/EventBus/issues" } organization { - name 'greenrobot' - url 'https://greenrobot.org' + name = "greenrobot" + url = "https://greenrobot.org" } } } From 831071ea8ba06a7b956a1930db718b936149b945 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 14:18:39 +0200 Subject: [PATCH 098/128] Start development of next version. --- EventBus/build.gradle | 2 +- EventBusAnnotationProcessor/build.gradle | 2 +- eventbus-android/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index ea96d39c..c3b3092d 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group = 'org.greenrobot' -version = '3.2.0' +version = '3.3.0-SNAPSHOT' java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index d5eb89e6..52585d50 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group = 'org.greenrobot' -version = '3.2.0' +version = '3.3.0-SNAPSHOT' java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index 601e0c9a..a08b02cc 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -13,7 +13,7 @@ buildscript { apply plugin: 'com.android.library' group = 'org.greenrobot' -version = '3.2.0' +version = '3.3.0-SNAPSHOT' android { compileSdkVersion _compileSdkVersion From a110323585e69993db306f8e1bbbadc02d09e9df Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 14:34:16 +0200 Subject: [PATCH 099/128] Make eventbus-java an exposed dependency of eventbus. --- eventbus-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index a08b02cc..21ff4c34 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -31,7 +31,7 @@ android { } dependencies { - implementation project(":eventbus") + api project(":eventbus") } task sourcesJar(type: Jar) { From bc0b3f3fdb4943f07ac6ea54fd5a50d7cba4727f Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 14:38:29 +0200 Subject: [PATCH 100/128] Rename EventBus project so it is added as dependency in POM. --- EventBusAnnotationProcessor/build.gradle | 2 +- EventBusPerformance/build.gradle | 2 +- EventBusTest/build.gradle | 2 +- EventBusTestJava/build.gradle | 2 +- EventBusTestSubscriberInJar/build.gradle | 2 +- eventbus-android/build.gradle | 2 +- settings.gradle | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 52585d50..8b4b5eea 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -7,7 +7,7 @@ java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 dependencies { - implementation project(':eventbus') + implementation project(':eventbus-java') implementation 'de.greenrobot:java-common:2.3.1' // Generates the required META-INF descriptor to make the processor incremental. diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 7fc3eea4..a9bc6e29 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -13,7 +13,7 @@ buildscript { apply plugin: 'com.android.application' dependencies { - implementation project(':eventbus') + implementation project(':eventbus-java') implementation project(':eventbus-android') annotationProcessor project(':eventbus-annotation-processor') implementation 'com.squareup:otto:1.3.8' diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index 8fc33ece..e2d1ee27 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -13,7 +13,7 @@ buildscript { apply plugin: 'com.android.application' dependencies { - androidTestImplementation project(':eventbus') + androidTestImplementation project(':eventbus-java') androidTestImplementation project(':eventbus-android') androidTestImplementation project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index ea5c4dd5..ef0a331f 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -15,7 +15,7 @@ sourceSets { dependencies { compile fileTree(dir: 'libs', include: '*.jar') - compile(project(':eventbus')) { + compile(project(':eventbus-java')) { exclude group: "com.google.android" // Does not seem to work... } annotationProcessor project(':eventbus-annotation-processor') diff --git a/EventBusTestSubscriberInJar/build.gradle b/EventBusTestSubscriberInJar/build.gradle index b091c149..93960dc9 100644 --- a/EventBusTestSubscriberInJar/build.gradle +++ b/EventBusTestSubscriberInJar/build.gradle @@ -10,7 +10,7 @@ configurations { } dependencies { - compile project(':eventbus') + compile project(':eventbus-java') provided project(':eventbus-annotation-processor') } diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index 21ff4c34..61b28c1d 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -31,7 +31,7 @@ android { } dependencies { - api project(":eventbus") + api project(":eventbus-java") } task sourcesJar(type: Jar) { diff --git a/settings.gradle b/settings.gradle index 44670236..9e53b0e9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,5 +6,5 @@ include ':EventBusTestSubscriberInJar' include ':EventBusPerformance' include ':eventbus-android' -project(":EventBus").name = "eventbus" +project(":EventBus").name = "eventbus-java" project(":EventBusAnnotationProcessor").name = "eventbus-annotation-processor" From 740a862356c8a370943d7f565a2049644b67abd7 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 14:52:59 +0200 Subject: [PATCH 101/128] Update Android references and messages. --- EventBus/build.gradle | 2 +- EventBus/src/org/greenrobot/eventbus/EventBus.java | 7 +++---- EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index c3b3092d..b591586f 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -42,7 +42,7 @@ afterEvaluate { artifact sourcesJar pom { name = "EventBus" - description = "EventBus is a publish/subscribe event bus optimized for Android." + description = "EventBus is a publish/subscribe event bus." packaging = "jar" } } diff --git a/EventBus/src/org/greenrobot/eventbus/EventBus.java b/EventBus/src/org/greenrobot/eventbus/EventBus.java index 25f93823..147bb5ff 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBus.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBus.java @@ -140,11 +140,10 @@ public EventBus() { * ThreadMode} and priority. */ public void register(Object subscriber) { - if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) { - //should crash user's app if the user (developer) has not imported the android compatibility library - throw new RuntimeException("Looks like you are using the latest version of EventBus on Android " + - "without importing the EventBus for Android compatibility library. Please import it on app/build.gradle!"); + // Crash if the user (developer) has not imported the Android compatibility library. + throw new RuntimeException("It looks like you are using EventBus on Android, " + + "make sure to add the \"eventbus\" Android library to your dependencies."); } Class subscriberClass = subscriber.getClass(); diff --git a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java index ff4a5f80..6df346d6 100644 --- a/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java +++ b/EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java @@ -143,8 +143,7 @@ public EventBusBuilder addIndex(SubscriberInfoIndex index) { /** * Set a specific log handler for all EventBus logging. *

- * By default all logging is via {@link android.util.Log} but if you want to use EventBus - * outside the Android environment then you will need to provide another log target. + * By default, all logging is via {@code android.util.Log} on Android or System.out on JVM. */ public EventBusBuilder logger(Logger logger) { this.logger = logger; From df94b23dca5683cf881fc8078c4ee1c038f1f663 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 15:35:19 +0200 Subject: [PATCH 102/128] Update Java test projects. --- EventBusTestJava/build.gradle | 14 ++++++-------- EventBusTestSubscriberInJar/build.gradle | 14 +++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/EventBusTestJava/build.gradle b/EventBusTestJava/build.gradle index ef0a331f..9e2bdad1 100644 --- a/EventBusTestJava/build.gradle +++ b/EventBusTestJava/build.gradle @@ -1,4 +1,4 @@ -apply plugin: 'java' +apply plugin: "java-library" java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 @@ -8,18 +8,16 @@ java.targetCompatibility = JavaVersion.VERSION_1_8 sourceSets { test { java { - srcDirs += ['src/main/java'] + srcDirs += ["src/main/java"] } } } dependencies { - compile fileTree(dir: 'libs', include: '*.jar') - compile(project(':eventbus-java')) { - exclude group: "com.google.android" // Does not seem to work... - } - annotationProcessor project(':eventbus-annotation-processor') - compile 'junit:junit:4.12' + implementation fileTree(dir: "libs", include: "*.jar") + implementation(project(":eventbus-java")) + annotationProcessor project(":eventbus-annotation-processor") + implementation "junit:junit:4.13.2" } tasks.withType(JavaCompile) { diff --git a/EventBusTestSubscriberInJar/build.gradle b/EventBusTestSubscriberInJar/build.gradle index 93960dc9..21096be3 100644 --- a/EventBusTestSubscriberInJar/build.gradle +++ b/EventBusTestSubscriberInJar/build.gradle @@ -1,7 +1,7 @@ -apply plugin: 'java' +apply plugin: "java-library" -group = 'de.greenrobot' -version = '3.0.0' +group = "de.greenrobot" +version = "3.0.0" java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 @@ -10,20 +10,20 @@ configurations { } dependencies { - compile project(':eventbus-java') - provided project(':eventbus-annotation-processor') + implementation project(":eventbus-java") + annotationProcessor project(":eventbus-annotation-processor") } sourceSets { main { compileClasspath += configurations.provided java { - srcDir 'src' + srcDir "src" } } } compileJava { - options.compilerArgs << '-AeventBusIndex=org.greenrobot.eventbus.InJarIndex' + options.compilerArgs << "-AeventBusIndex=org.greenrobot.eventbus.InJarIndex" options.fork = true } From adc7b9f70e327915d048086c87ba80a827c5e8d6 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 15:35:50 +0200 Subject: [PATCH 103/128] Drop explicit eventbus-java dependency from Android test projects. --- EventBusPerformance/build.gradle | 1 - EventBusTest/build.gradle | 1 - 2 files changed, 2 deletions(-) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index a9bc6e29..247d085e 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -13,7 +13,6 @@ buildscript { apply plugin: 'com.android.application' dependencies { - implementation project(':eventbus-java') implementation project(':eventbus-android') annotationProcessor project(':eventbus-annotation-processor') implementation 'com.squareup:otto:1.3.8' diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index e2d1ee27..f449b739 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -13,7 +13,6 @@ buildscript { apply plugin: 'com.android.application' dependencies { - androidTestImplementation project(':eventbus-java') androidTestImplementation project(':eventbus-android') androidTestImplementation project(':EventBusTestJava') androidTestAnnotationProcessor project(':eventbus-annotation-processor') From 45352be3f13374f545679f1f3d793e0e0a3e16f4 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 22 Jun 2021 15:45:24 +0200 Subject: [PATCH 104/128] Re-add deprecated test classes for Android. --- EventBusTest/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/EventBusTest/build.gradle b/EventBusTest/build.gradle index f449b739..2ca34312 100644 --- a/EventBusTest/build.gradle +++ b/EventBusTest/build.gradle @@ -57,6 +57,8 @@ android { } } + useLibrary 'android.test.base' + lintOptions { // To see problems right away, also nice for Travis CI textOutput 'stdout' From e573ffa2b1877398ca95a32f53a1c45363852bc7 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 29 Jun 2021 14:03:55 +0200 Subject: [PATCH 105/128] Regression: correctly check for Android main thread. --- .../eventbus/android/DefaultAndroidMainThreadSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java index 13339465..02b3f3af 100644 --- a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java @@ -10,7 +10,7 @@ public class DefaultAndroidMainThreadSupport implements MainThreadSupport { @Override public boolean isMainThread() { - return true; + return Looper.getMainLooper() == Looper.myLooper(); } @Override From 5efb61f919512df21f5b8e3c1605f70f5281062e Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 29 Jun 2021 14:10:12 +0200 Subject: [PATCH 106/128] Regression: restore AndroidLogger log output. Drop added ExceptionStackTraceUtils class. --- .../eventbus/util/ExceptionStackTraceUtils.java | 15 --------------- .../eventbus/android/AndroidLogger.java | 4 ++-- 2 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java diff --git a/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java b/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java deleted file mode 100644 index 4d0e1cae..00000000 --- a/EventBus/src/org/greenrobot/eventbus/util/ExceptionStackTraceUtils.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.greenrobot.eventbus.util; - -import java.io.PrintWriter; -import java.io.StringWriter; - -public class ExceptionStackTraceUtils { - - public static String getStackTraceAsString(Throwable ex) { - - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(stringWriter); - ex.printStackTrace(printWriter); - return stringWriter.toString(); - } -} diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java index 45fd6e4e..04cc1cf3 100644 --- a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java @@ -17,7 +17,7 @@ import android.util.Log; import org.greenrobot.eventbus.Logger; -import org.greenrobot.eventbus.util.ExceptionStackTraceUtils; + import java.util.logging.Level; public class AndroidLogger implements Logger { @@ -37,7 +37,7 @@ public void log(Level level, String msg) { public void log(Level level, String msg, Throwable th) { if (level != Level.OFF) { // That's how Log does it internally - Log.println(mapLevel(level), tag, msg + "\n" + ExceptionStackTraceUtils.getStackTraceAsString(th)); + Log.println(mapLevel(level), tag, msg + "\n" + Log.getStackTraceString(th)); } } From 8980e2d12e7ba6ac68e80ad17800a2b1e87d308e Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 29 Jun 2021 14:13:58 +0200 Subject: [PATCH 107/128] Regression: Remove added suppression. --- .../src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java | 1 - 1 file changed, 1 deletion(-) diff --git a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java index c6432d49..9020c24b 100644 --- a/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java +++ b/EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java @@ -22,7 +22,6 @@ import java.lang.reflect.Method; /** Base class for generated subscriber meta info classes created by annotation processing. */ -@SuppressWarnings({ "rawtypes", "TryWithIdenticalCatches", "unchecked" }) public abstract class AbstractSubscriberInfo implements SubscriberInfo { private final Class subscriberClass; private final Class superSubscriberInfoClass; From ece8c276957a99accb2d4000dc8b24e9b392c1e8 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 13 Jul 2021 14:30:43 +0200 Subject: [PATCH 108/128] Publishing: add license back to POM. --- gradle/publish.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 5420dd44..4d0e092d 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -29,6 +29,14 @@ afterEvaluate { url = "https://github.com/greenrobot/EventBus" } + licenses { + license { + name = "The Apache Software License, Version 2.0" + url = "https://www.apache.org/licenses/LICENSE-2.0.txt" + distribution = "repo" + } + } + developers { developer { id = "greenrobot" From 2d6910e13eb5f0dda3818611098b7bfd0f1b1c61 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 13 Jul 2021 14:33:10 +0200 Subject: [PATCH 109/128] Update README --- README.md | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2a776233..f5bd9878 100644 --- a/README.md +++ b/README.md @@ -68,16 +68,19 @@ Add EventBus to your project Available on Maven Central. -Via Gradle: -```gradle -implementation 'org.greenrobot:eventbus:3.2.0' +Android projects: +```groovy +implementation("org.greenrobot:eventbus:3.2.0") ``` -Via Maven: +Java projects: +```groovy +implementation("org.greenrobot:eventbus-java:3.2.0") +``` ```xml org.greenrobot - eventbus + eventbus-java 3.2.0 ``` @@ -85,20 +88,7 @@ Via Maven: R8, ProGuard ------------ -If your project uses R8 or ProGuard add the following rules: - -```bash --keepattributes *Annotation* --keepclassmembers class * { - @org.greenrobot.eventbus.Subscribe ; -} --keep enum org.greenrobot.eventbus.ThreadMode { *; } - -# And if you use AsyncExecutor: --keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { - (java.lang.Throwable); -} -``` +If your project uses R8 or ProGuard this library ships [with embedded rules](/eventbus-android/consumer-rules.pro). Homepage, Documentation, Links ------------------------------ @@ -112,8 +102,6 @@ For more details please check the [EventBus website](https://greenrobot.org/even [FAQ](https://greenrobot.org/eventbus/documentation/faq/) -How does EventBus compare to other solutions, like Otto from Square? Check this [comparison](COMPARISON.md). - License ------- Copyright (C) 2012-2020 Markus Junginger, greenrobot (https://greenrobot.org) @@ -125,5 +113,3 @@ Other projects by greenrobot [__ObjectBox__](https://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database. [__Essentials__](https://github.com/greenrobot/essentials) is a set of utility classes and hash functions for Android & Java projects. - -[__greenDAO__](https://github.com/greenrobot/greenDAO) is an ORM optimized for Android: it maps database tables to Java objects and uses code generation for optimal speed. From d74c3bac7ca58a85a9a7cd46cd74bed8a76792fc Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 13 Jul 2021 14:44:39 +0200 Subject: [PATCH 110/128] Prevent removal or renaming of AndroidComponentsImpl. --- eventbus-android/consumer-rules.pro | 3 +++ .../org/greenrobot/eventbus/android/AndroidComponentsImpl.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/eventbus-android/consumer-rules.pro b/eventbus-android/consumer-rules.pro index 06d028c3..d5248bac 100644 --- a/eventbus-android/consumer-rules.pro +++ b/eventbus-android/consumer-rules.pro @@ -8,3 +8,6 @@ -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { (java.lang.Throwable); } + +# Accessed via reflection, avoid renaming or removal +-keep class org.greenrobot.eventbus.android.AndroidComponentsImpl diff --git a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java index afcb4af0..20f35b18 100644 --- a/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java +++ b/eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java @@ -1,5 +1,8 @@ package org.greenrobot.eventbus.android; +/** + * Used via reflection in the Java library by {@link AndroidDependenciesDetector}. + */ public class AndroidComponentsImpl extends AndroidComponents { public AndroidComponentsImpl() { From ee34ff6b3b590a848223bfd9e9e075fd1bfd49b1 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 13 Jul 2021 14:44:51 +0200 Subject: [PATCH 111/128] Add README for Android library. --- eventbus-android/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 eventbus-android/README.md diff --git a/eventbus-android/README.md b/eventbus-android/README.md new file mode 100644 index 00000000..126c7ba9 --- /dev/null +++ b/eventbus-android/README.md @@ -0,0 +1,7 @@ +# EventBus for Android + +Despite its name this module is actually published as `org.greenrobot:eventbus` as an Android library (AAR). + +It has a dependency on the Java-only artifact `org.greenrobot:eventbus-java` (JAR) previously available under the `eventbus` name. + +Provides an `AndroidComponents` implementation to the Java library if it detects `AndroidComponentsImpl` on the classpath via reflection. From 846e6656b828fde0c697c5c4df0b05ed1a4ef516 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 13 Jul 2021 14:47:24 +0200 Subject: [PATCH 112/128] Drop AndroidComponentsAvailabilityOnJavaTest, ensured implicitly by other tests. If other tests would use any Android API on JVM, they would crash. --- ...AndroidComponentsAvailabilityOnJavaTest.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java diff --git a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java b/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java deleted file mode 100644 index cc2e69ff..00000000 --- a/EventBusTestJava/src/main/java/org/greenrobot/eventbus/AndroidComponentsAvailabilityOnJavaTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.greenrobot.eventbus; - -import org.greenrobot.eventbus.android.AndroidComponents; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; - -public class AndroidComponentsAvailabilityOnJavaTest -{ - - @Test - public void shouldNotBeAvailable() { - assertFalse(AndroidComponents.areAvailable()); - assertNull(AndroidComponents.get()); - } -} From a49951eae51cfc8024a2c51f4a9fddc945021c66 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 30 Nov 2021 13:36:19 +0100 Subject: [PATCH 113/128] Actually sign new artifacts from mavenJava publication. Add support for file-based signing key (for CI). --- eventbus-android/build.gradle | 2 + gradle/publish.gradle | 107 ++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index 61b28c1d..6edd255e 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -42,6 +42,8 @@ task sourcesJar(type: Jar) { apply from: rootProject.file("gradle/publish.gradle") // Set project-specific properties // https://developer.android.com/studio/build/maven-publish-plugin +// Because the Android components are created only during the afterEvaluate phase, you must +// configure your publications using the afterEvaluate() lifecycle method. afterEvaluate { publishing.publications { mavenJava(MavenPublication) { diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 4d0e092d..1206dd62 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -3,58 +3,79 @@ apply plugin: "maven-publish" apply plugin: "signing" -signing { - if (project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && - project.hasProperty('signing.secretKeyRingFile')) { - sign configurations.archives - } else { - println "Signing information missing/incomplete for ${project.name}." - } -} +publishing { + publications { + // Note: Sonatype repo created by publish-plugin, see root build.gradle. + mavenJava(MavenPublication) { + pom { + url = "https://greenrobot.org/eventbus/" -// https://developer.android.com/studio/build/maven-publish-plugin -// Because the Android components are created only during the afterEvaluate phase, you must -// configure your publications using the afterEvaluate() lifecycle method. -afterEvaluate { - publishing { - publications { - // Note: Sonatype repo created by publish-plugin, see root build.gradle. - mavenJava(MavenPublication) { - pom { - url = "https://greenrobot.org/eventbus/" - - scm { - connection = "scm:git@github.com:greenrobot/EventBus.git" - developerConnection = "scm:git@github.com:greenrobot/EventBus.git" - url = "https://github.com/greenrobot/EventBus" - } + scm { + connection = "scm:git@github.com:greenrobot/EventBus.git" + developerConnection = "scm:git@github.com:greenrobot/EventBus.git" + url = "https://github.com/greenrobot/EventBus" + } - licenses { - license { - name = "The Apache Software License, Version 2.0" - url = "https://www.apache.org/licenses/LICENSE-2.0.txt" - distribution = "repo" - } + licenses { + license { + name = "The Apache Software License, Version 2.0" + url = "https://www.apache.org/licenses/LICENSE-2.0.txt" + distribution = "repo" } + } - developers { - developer { - id = "greenrobot" - name = "greenrobot" - } + developers { + developer { + id = "greenrobot" + name = "greenrobot" } + } - issueManagement { - system = "https://github.com/greenrobot/EventBus/issues" - url = "https://github.com/greenrobot/EventBus/issues" - } + issueManagement { + system = "https://github.com/greenrobot/EventBus/issues" + url = "https://github.com/greenrobot/EventBus/issues" + } - organization { - name = "greenrobot" - url = "https://greenrobot.org" - } + organization { + name = "greenrobot" + url = "https://greenrobot.org" } } } } } + +// Note: ext to export to scripts applying this script. +ext { + // Signing: in-memory ascii-armored key (CI) or keyring file (dev machine), see https://docs.gradle.org/current/userguide/signing_plugin.html + hasSigningPropertiesKeyFile = { + return (project.hasProperty('signingKeyId') + && project.hasProperty('signingKeyFile') + && project.hasProperty('signingPassword')) + } + // Typically via ~/.gradle/gradle.properties; default properties for signing plugin. + hasSigningPropertiesKeyRing = { + return (project.hasProperty('signing.keyId') + && project.hasProperty('signing.secretKeyRingFile') + && project.hasProperty('signing.password')) + } + hasSigningProperties = { + return hasSigningPropertiesKeyFile() || hasSigningPropertiesKeyRing() + } +} + +signing { + if (hasSigningProperties()) { + if (hasSigningPropertiesKeyFile()) { + println "Configured signing to use key file." + String signingKey = new File(signingKeyFile).text + useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) + } else if (hasSigningPropertiesKeyRing()) { + println "Configured signing to use key ring." + // Note: using expected property names (see above), no need to configure anything. + } + sign publishing.publications.mavenJava + } else { + println "WARNING: signing properties NOT set, will not sign artifacts." + } +} From b95c914c870dcef4df04780ba24464ceedd4f579 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 30 Nov 2021 13:39:09 +0100 Subject: [PATCH 114/128] GitHub Actions: use built-in cache support from setup-java task. --- .github/workflows/gradle.yml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 1ac038ec..758ea017 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,24 +19,10 @@ jobs: with: java-version: '11' distribution: 'adopt' - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- + cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Gradle Info run: ./gradlew -version - name: Build with Gradle run: ./gradlew build - - name: Cleanup Gradle Cache - # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. - # Restoring these files from a GitHub Actions cache might cause problems for future builds. - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties From 650fc80c395760f352b62fc450e511ae771d6720 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 30 Nov 2021 14:22:44 +0100 Subject: [PATCH 115/128] Make group and version detectable by publish plugin. --- EventBus/build.gradle | 5 +++-- EventBusAnnotationProcessor/build.gradle | 4 ++-- build.gradle | 4 ++++ eventbus-android/build.gradle | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/EventBus/build.gradle b/EventBus/build.gradle index b591586f..ffea11b6 100644 --- a/EventBus/build.gradle +++ b/EventBus/build.gradle @@ -1,7 +1,8 @@ apply plugin: 'java' -group = 'org.greenrobot' -version = '3.3.0-SNAPSHOT' +group = rootProject.group +version = rootProject.version + java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/EventBusAnnotationProcessor/build.gradle b/EventBusAnnotationProcessor/build.gradle index 8b4b5eea..0ec77d93 100644 --- a/EventBusAnnotationProcessor/build.gradle +++ b/EventBusAnnotationProcessor/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' -group = 'org.greenrobot' -version = '3.3.0-SNAPSHOT' +group = rootProject.group +version = rootProject.version java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/build.gradle b/build.gradle index d575a7a5..57827719 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,10 @@ buildscript { } } +// Set group and version in root build.gradle so publish-plugin can detect them. +group = "org.greenrobot" +version = "3.3.0-SNAPSHOT" + allprojects { repositories { mavenCentral() diff --git a/eventbus-android/build.gradle b/eventbus-android/build.gradle index 6edd255e..c1992ce4 100644 --- a/eventbus-android/build.gradle +++ b/eventbus-android/build.gradle @@ -12,8 +12,8 @@ buildscript { apply plugin: 'com.android.library' -group = 'org.greenrobot' -version = '3.3.0-SNAPSHOT' +group = rootProject.group +version = rootProject.version android { compileSdkVersion _compileSdkVersion From d4bfdd52a7c8a9ae9ab7f53a04e8471ca3c8c363 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 30 Nov 2021 14:41:19 +0100 Subject: [PATCH 116/128] README: use snapshot version to indicate instructions require next version. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f5bd9878..4e8c8c32 100644 --- a/README.md +++ b/README.md @@ -70,18 +70,18 @@ Available on org.greenrobot eventbus-java - 3.2.0 + 3.3.0-SNAPSHOT ``` From 5fa535537bb121180456b618f91a5de515f775a4 Mon Sep 17 00:00:00 2001 From: Uwe - ObjectBox <13865709+greenrobot-team@users.noreply.github.com> Date: Mon, 6 Dec 2021 08:31:28 +0100 Subject: [PATCH 117/128] Link instructions for stable version. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4e8c8c32..31fb1521 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ Add EventBus to your project Available on Maven Central. +**Note: to use the latest stable version [see the previous README](https://github.com/greenrobot/EventBus/tree/V3.2.0#add-eventbus-to-your-project). The following only applies to the 3.3.0 preview release available on the [Maven Central Snapshots](https://oss.sonatype.org/content/repositories/snapshots/) repository.** + Android projects: ```groovy implementation("org.greenrobot:eventbus:3.3.0-SNAPSHOT") From 37c9296f90abdf4feea3454eda8dfa7ab076a797 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 6 Dec 2021 14:50:38 +0100 Subject: [PATCH 118/128] Prepare release 3.3.0 --- README.md | 8 +++----- build.gradle | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 31fb1521..2a1aac69 100644 --- a/README.md +++ b/README.md @@ -68,22 +68,20 @@ Add EventBus to your project Available on Maven Central. -**Note: to use the latest stable version [see the previous README](https://github.com/greenrobot/EventBus/tree/V3.2.0#add-eventbus-to-your-project). The following only applies to the 3.3.0 preview release available on the [Maven Central Snapshots](https://oss.sonatype.org/content/repositories/snapshots/) repository.** - Android projects: ```groovy -implementation("org.greenrobot:eventbus:3.3.0-SNAPSHOT") +implementation("org.greenrobot:eventbus:3.3.0") ``` Java projects: ```groovy -implementation("org.greenrobot:eventbus-java:3.3.0-SNAPSHOT") +implementation("org.greenrobot:eventbus-java:3.3.0") ``` ```xml org.greenrobot eventbus-java - 3.3.0-SNAPSHOT + 3.3.0 ``` diff --git a/build.gradle b/build.gradle index 57827719..0c29d3b2 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { // Set group and version in root build.gradle so publish-plugin can detect them. group = "org.greenrobot" -version = "3.3.0-SNAPSHOT" +version = "3.3.0" allprojects { repositories { From f588193f2d4410c90e148fa7fe8f2767c0993023 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Mon, 6 Dec 2021 15:13:58 +0100 Subject: [PATCH 119/128] README: update build badge, license year. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2a1aac69..a8241b11 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ EventBus [EventBus](https://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.
-[![Build Status](https://travis-ci.org/greenrobot/EventBus.svg?branch=master)](https://travis-ci.org/greenrobot/EventBus) +[![Build Status](https://github.com/greenrobot/EventBus/actions/workflows/gradle.yml/badge.svg)](https://github.com/greenrobot/EventBus/actions) [![Follow greenrobot on Twitter](https://img.shields.io/twitter/follow/greenrobot_de.svg?style=flat-square&logo=twitter)](https://twitter.com/greenrobot_de) EventBus... @@ -98,13 +98,13 @@ For more details please check the [EventBus website](https://greenrobot.org/even [Documentation](https://greenrobot.org/eventbus/documentation/) -[Changelog](https://greenrobot.org/eventbus/changelog/) +[Changelog](https://github.com/greenrobot/EventBus/releases) [FAQ](https://greenrobot.org/eventbus/documentation/faq/) License ------- -Copyright (C) 2012-2020 Markus Junginger, greenrobot (https://greenrobot.org) +Copyright (C) 2012-2021 Markus Junginger, greenrobot (https://greenrobot.org) EventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE). From 9f4d2ec6fa878afd94cc5c1751a439facff0c58a Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Wed, 8 Dec 2021 09:36:41 +0100 Subject: [PATCH 120/128] Fix ProGuard rules to keep default failure event class constructor. --- eventbus-android/consumer-rules.pro | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eventbus-android/consumer-rules.pro b/eventbus-android/consumer-rules.pro index d5248bac..4646fb1e 100644 --- a/eventbus-android/consumer-rules.pro +++ b/eventbus-android/consumer-rules.pro @@ -4,8 +4,9 @@ } -keep enum org.greenrobot.eventbus.ThreadMode { *; } -# And if you use AsyncExecutor: --keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { +# If using AsyncExecutord, keep required constructor of default event used. +# Adjust the class name if a custom failure event type is used. +-keepclassmembers class org.greenrobot.eventbus.util.ThrowableFailureEvent { (java.lang.Throwable); } From 757bc9a18ff7c63dc54ef30d208e3931e230292d Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Wed, 8 Dec 2021 09:37:19 +0100 Subject: [PATCH 121/128] AsyncExecutor: update docs with event class requirements, ProGuard rule tip. --- .../greenrobot/eventbus/util/AsyncExecutor.java | 16 ++++++++++++---- .../eventbus/util/ThrowableFailureEvent.java | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java index 9c0433e8..c11e5c6c 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java +++ b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java @@ -23,10 +23,18 @@ import java.util.logging.Level; /** - * Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events of any - * given type (default is {@link ThrowableFailureEvent}). - * - * @author Markus + * Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events. + * By default, uses {@link ThrowableFailureEvent}. + *

+ * Set a custom event type using {@link Builder#failureEventType(Class)}. + * The failure event class must have a constructor with one parameter of type {@link Throwable}. + * If using ProGuard or R8 make sure the constructor of the failure event class is kept, it is accessed via reflection. + * E.g. add a rule like + *

+ * -keepclassmembers class com.example.CustomThrowableFailureEvent {
+ *     <init>(java.lang.Throwable);
+ * }
+ * 
*/ public class AsyncExecutor { diff --git a/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java b/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java index 1b339fba..7707e289 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java +++ b/EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java @@ -17,6 +17,7 @@ /** * A generic failure event, which can be used by apps to propagate thrown exceptions. + * Used as default failure event by {@link AsyncExecutor}. */ public class ThrowableFailureEvent implements HasExecutionScope { protected final Throwable throwable; From 60c4b78837b933435f3d22e92690a8812b505ef5 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Wed, 8 Dec 2021 09:37:29 +0100 Subject: [PATCH 122/128] AsyncExecutor: use lambda. --- .../eventbus/util/AsyncExecutor.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java index c11e5c6c..bd9cb365 100644 --- a/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java +++ b/EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java @@ -111,24 +111,21 @@ private AsyncExecutor(Executor threadPool, EventBus eventBus, Class failureEv /** Posts an failure event if the given {@link RunnableEx} throws an Exception. */ public void execute(final RunnableEx runnable) { - threadPool.execute(new Runnable() { - @Override - public void run() { + threadPool.execute(() -> { + try { + runnable.run(); + } catch (Exception e) { + Object event; try { - runnable.run(); - } catch (Exception e) { - Object event; - try { - event = failureEventConstructor.newInstance(e); - } catch (Exception e1) { - eventBus.getLogger().log(Level.SEVERE, "Original exception:", e); - throw new RuntimeException("Could not create failure event", e1); - } - if (event instanceof HasExecutionScope) { - ((HasExecutionScope) event).setExecutionScope(scope); - } - eventBus.post(event); + event = failureEventConstructor.newInstance(e); + } catch (Exception e1) { + eventBus.getLogger().log(Level.SEVERE, "Original exception:", e); + throw new RuntimeException("Could not create failure event", e1); } + if (event instanceof HasExecutionScope) { + ((HasExecutionScope) event).setExecutionScope(scope); + } + eventBus.post(event); } }); } From eba6809508855cf061437ecae168688eb7259982 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Wed, 8 Dec 2021 10:12:43 +0100 Subject: [PATCH 123/128] Make EventBusPerformance build again (project outdated though) Use Java 8 features. --- EventBusPerformance/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EventBusPerformance/build.gradle b/EventBusPerformance/build.gradle index 247d085e..37a32249 100644 --- a/EventBusPerformance/build.gradle +++ b/EventBusPerformance/build.gradle @@ -40,4 +40,9 @@ android { } } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } From c7993322e531653789777360cc4821dd2183c4d7 Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Wed, 8 Dec 2021 11:51:14 +0100 Subject: [PATCH 124/128] Prepare release 3.3.1 --- README.md | 6 +++--- build.gradle | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a8241b11..878807a8 100644 --- a/README.md +++ b/README.md @@ -70,18 +70,18 @@ Available on org.greenrobot eventbus-java - 3.3.0 + 3.3.1 ``` diff --git a/build.gradle b/build.gradle index 0c29d3b2..aaeccfeb 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { // Set group and version in root build.gradle so publish-plugin can detect them. group = "org.greenrobot" -version = "3.3.0" +version = "3.3.1" allprojects { repositories { From 6f939ca40a9691f0e12e3facff4bb4f0377aeae1 Mon Sep 17 00:00:00 2001 From: Uwe - ObjectBox <13865709+greenrobot-team@users.noreply.github.com> Date: Mon, 13 Dec 2021 12:53:39 +0100 Subject: [PATCH 125/128] README: fix subscriber method snippet. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 878807a8..75ecf629 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ EventBus in 3 steps ```java @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(MessageEvent event) {/* Do something */}; + public void onMessageEvent(MessageEvent event) { + // Do something + } ``` Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle: From a74cdf0a5c96359b8d10e129740e33d90504f43a Mon Sep 17 00:00:00 2001 From: greenrobot Team Date: Tue, 25 Jan 2022 08:44:41 +0100 Subject: [PATCH 126/128] Document MAIN_ORDERED behavior if not Android. --- .../org/greenrobot/eventbus/ThreadMode.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java index b8ee7d53..b1ff2427 100644 --- a/EventBus/src/org/greenrobot/eventbus/ThreadMode.java +++ b/EventBus/src/org/greenrobot/eventbus/ThreadMode.java @@ -17,15 +17,14 @@ /** * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus. - * EventBus takes care of threading independently from the posting thread. - * + * EventBus takes care of threading independently of the posting thread. + * * @see EventBus#register(Object) - * @author Markus */ public enum ThreadMode { /** - * Subscriber will be called directly in the same thread, which is posting the event. This is the default. Event delivery - * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for + * This is the default. Subscriber will be called directly in the same thread, which is posting the event. Event delivery + * implies the least overhead because it avoids thread switching completely. Thus, this is the recommended mode for * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread. */ @@ -35,6 +34,7 @@ public enum ThreadMode { * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread. + *

* If not on Android, behaves the same as {@link #POSTING}. */ MAIN, @@ -42,6 +42,8 @@ public enum ThreadMode { /** * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN}, * the event will always be queued for delivery. This ensures that the post call is non-blocking. + *

+ * If not on Android, behaves the same as {@link #POSTING}. */ MAIN_ORDERED, @@ -49,15 +51,17 @@ public enum ThreadMode { * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to - * return quickly to avoid blocking the background thread. If not on Android, always uses a background thread. + * return quickly to avoid blocking the background thread. + *

+ * If not on Android, always uses a background thread. */ BACKGROUND, /** - * Subscriber will be called in a separate thread. This is always independent from the posting thread and the + * Subscriber will be called in a separate thread. This is always independent of the posting thread and the * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number - * of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus + * of long-running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications. */ ASYNC From 842a4a312c4ea1592bd7067a00495eebe129c078 Mon Sep 17 00:00:00 2001 From: guoci Date: Wed, 22 Dec 2021 14:13:33 -0500 Subject: [PATCH 127/128] fix typo --- EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java index 624ddf6d..94db640e 100644 --- a/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java +++ b/EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java @@ -64,7 +64,7 @@ public void run() { eventBus.invokeSubscriber(pendingPost); } } catch (InterruptedException e) { - eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e); + eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interrupted", e); } } finally { executorRunning = false; From 0194926b3bcf70cc0d7bfd3c5da16708dd5ab876 Mon Sep 17 00:00:00 2001 From: Uwe <13865709+greenrobot-team@users.noreply.github.com> Date: Mon, 11 Jul 2022 09:59:54 +0200 Subject: [PATCH 128/128] CI: use temurin for JDK, update checkout and setup-java to v3. --- .github/workflows/gradle.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 758ea017..365ea1a6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '11' - distribution: 'adopt' + distribution: 'temurin' cache: gradle - name: Grant execute permission for gradlew run: chmod +x gradlew