google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.36k stars 2k forks source link

Fragment injection broken when the fragment is used in an AndroidAuto CarActivity #2150

Open Aweck-Xevo opened 3 years ago

Aweck-Xevo commented 3 years ago

CarActivity is a context, but it is not an Activity. So when a fragment is attached inside of a CarActivity, the getActivity() call returns null. This breaks the following code in AndroidInjection.java and AndroidSupportInjection.java:

private static HasAndroidInjector findHasAndroidInjectorForFragment(Fragment fragment) {
    [...]
    Activity activity = fragment.getActivity();
    if (activity instanceof HasAndroidInjector) {
      return (HasAndroidInjector) activity;
    }
    if (activity.getApplication() instanceof HasAndroidInjector) {
      return (HasAndroidInjector) activity.getApplication();
    }
    throw new IllegalArgumentException(
        String.format("No injector was found for %s", fragment.getClass().getCanonicalName()));
}

Since we are just casting and using instanceof anyway, I propose we use getContext() instead of getActivity() here. Then it will be non-null for carActivity and will get the HasAndroidInjector from the application context instead.

bcorso commented 3 years ago

@Aweck-Xevo sorry I'm not familiar with CarActivity. Can you verify that fragment.getContext() return an instance of your CarActivity?

Also, if you have a link to any documentation about it that would help. I did a quick search and found this source. Not sure if it's the same CarActivity you're referring to, but that one does not extend Context.

Aweck-Xevo commented 3 years ago

@bcorso It does return an instance of my CarActivity subclass. When I trace CarActivity, it does end up inheriting from context. This activity is used for creating OEM Android Auto apps. Google is somewhat hush-hush about it for some reason and the documentation isn't public. But or the sake of improving Dagger, I think it's probably okay to post the inheritance pathway:

java.lang.Object ↳ | android.content.Context   | ↳ | android.content.ContextWrapper   |   | ↳ | com.google.android.gms.car.CarActivity   |   |   | ↳ | com.google.android.gms.car.CarComponentActivity   |   |   |   | ↳ | com.google.android.gms.car.CarFragmentActivity   |   |   |   |   | ↳ | com.google.android.apps.auto.sdk.CarActivity