From bf8e86164001f514ce74514de5d0034f3473ee0f Mon Sep 17 00:00:00 2001 From: Andrei Dobrescu Date: Mon, 10 May 2021 16:04:25 +0300 Subject: [PATCH 01/25] 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 02/25] 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 03/25] 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 04/25] 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 05/25] 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 06/25] 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 07/25] 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 08/25] 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 09/25] 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 10/25] 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 11/25] 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 12/25] 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 13/25] 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 14/25] 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 15/25] 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 16/25] 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 17/25] 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 18/25] 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 19/25] 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 20/25] 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 21/25] 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 22/25] 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 23/25] 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 24/25] 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 25/25] 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()); - } -}