2

Not a duplicate

I've read a lot of different SO posts with "similar" problems, but so far nothing has resolved my issue:

It seems like this one particular step (mergeDebugResources) can fail spectacularly in hundreds of different ways and never gives a helpful error message. At best it tells you nothing and at worst it gives you misleading information that sends you in the wrong direction trying to debug your problems.

What I'm doing

I'm writing a small wrapper around ExoPlayer. My wrapper exposes a custom View with properties that are passed directly to ExoPlayer's PlayerView. The attrs.xml file for my custom view looks like this:

<resources>
    <declare-styleable name="BFPlayer">
        <!-- PlayerView attributes -->
        <!-- I wish these were camelCase and not snake_case, but c'est la vie -->
        <attr name="use_artwork" format="boolean" />
        <attr name="default_artwork" format="reference" />
        <attr name="use_controller" format="boolean" />
        <attr name="hide_on_touch" format="boolean" />
        <attr name="auto_show" format="boolean" />
        <attr name="hide_during_ads" format="boolean" />
        <attr name="show_buffering" format="enum">
            <enum name="never" value="0" />
            <enum name="when_playing" value="1" />
            <enum name="always" value="2" />
        </attr>
        <attr name="resize_mode" format="enum">
            <enum name="fit" value="0" />
            <enum name="fixed_width" value="1" />
            <enum name="fixed_height" value="2" />
            <enum name="fill" value="3" />
            <enum name="zoom" value="4" />
        </attr>
        <attr name="surface_type" format="enum">
            <enum name="none" value="0" />
            <enum name="surface_view" value="1" />
            <enum name="texture_view" value="2" />
            <enum name="spherical_view" value="3" />
        </attr>
        <attr name="shutter_background_color" format="color" />
        <attr name="keep_content_on_player_reset" format="boolean" />
        <attr name="player_layout_id" format="reference" />
        <attr name="controller_layout_id" format="reference" />
        <!-- BFPlayer attributes -->
        <!-- snake_case to match ExoPlayer attributes -->
        <attr name="video_src" format="string" />
    </declare-styleable>
</resources>

What's happening

I'm getting the following error when trying to build my project:

* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> 1 exception was raised by workers:
  com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource compilation failed
  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/906c495794baffdd076b02fc420f6298/res/values/values.xml:726:5-730:25: AAPT: error: duplicate value for resource 'attr/resize_mode' with config ''.

  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/906c495794baffdd076b02fc420f6298/res/values/values.xml:726:5-730:25: AAPT: error: resource previously defined here.

  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/906c495794baffdd076b02fc420f6298/res/values/values.xml:726:5-730:25: AAPT: error: duplicate value for resource 'attr/surface_type' with config ''.

  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/906c495794baffdd076b02fc420f6298/res/values/values.xml:726:5-730:25: AAPT: error: resource previously defined here.

  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/1694e02eca6cc0cfe670672c5973bd19/res/values/values.xml:32:5-36:373: AAPT: error: duplicate value for resource 'attr/show_buffering' with config ''.

  /Users/stevenbarnett/.gradle/caches/transforms-2/files-2.1/1694e02eca6cc0cfe670672c5973bd19/res/values/values.xml:32:5-36:373: AAPT: error: resource previously defined here.

  /Users/stevenbarnett/Source/BluePlayer/AndroidSDK/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml: error: file failed to compile.

Notice that it's claiming the value defined in values.xml from line 726 column 5 through line 730 column 25 "was previously defined" in values.xml from line 726 column 5 through line 730 column 25. It's literally seeing the same declaration!

I've tried:

  • Cleaning my project
  • Invalidating caches and restarting
  • Deleting my ~/.gradle directory
  • Reinstalling Android Studio
  • Downgrading Gradle Android Plugin (from 3.4.0 to 3.0.0)
  • Upgrading Gradle Android Plugin (from 3.4.0 to 3.5.0-beta1)

I'm on Mac OS X (so any Windows-related issues are irrelevant)

I'm on a 64-bit machine, using 64-bit build tools

I have successfully built this project and many others before. The issue didn't arise until I tried to create this attrs.xml file. It's only the enum attributes that are throwing the error. Removing or renaming these attributes allows the project to build, however these are the names expected by ExoPlayer's PlayerView and so I cannot change them

stevendesu
  • 15,753
  • 22
  • 105
  • 182

1 Answers1

0

I don't have an answer I'm happy with, but I do have an answer kind of for now.

For the enum values (and only the enum values) PlayerView's attributes were colliding with my own -- for some reason. Perhaps a quirk of how Android parses the attributes.xml file? I solved this by changing the names and then using methods on the PlayerView to set these values at instantiation:

attrs.xml

<resources>
    <declare-styleable name="BFPlayer">
        <!-- PlayerView attributes -->
        <attr name="useArtwork" format="boolean" />
        <attr name="defaultArtwork" format="reference" />
        <attr name="useController" format="boolean" />
        <attr name="hideOnTouch" format="boolean" />
        <attr name="autoShow" format="boolean" />
        <attr name="hideDuringAds" format="boolean" />
        <attr name="showBuffering" format="enum">
            <enum name="never" value="0" />
            <enum name="when_playing" value="1" />
            <enum name="always" value="2" />
        </attr>
        <attr name="resizeMode" format="enum">
            <enum name="fit" value="0" />
            <enum name="fixed_width" value="1" />
            <enum name="fixed_height" value="2" />
            <enum name="fill" value="3" />
            <enum name="zoom" value="4" />
        </attr>
        <attr name="surfaceType" format="enum">
            <enum name="none" value="0" />
            <enum name="surface_view" value="1" />
            <enum name="texture_view" value="2" />
            <enum name="spherical_view" value="3" />
        </attr>
        <attr name="shutterBackgroundColor" format="color" />
        <attr name="keepContentOnPlayerReset" format="boolean" />
        <attr name="playerLayoutId" format="reference" />
        <attr name="controllerLayoutId" format="reference" />
        <!-- BFPlayer attributes -->
        <attr name="videoSrc" format="string" />
    </declare-styleable>
</resources>

BFPlayer.java

        this.setUseArtwork(attributes.getBoolean(R.styleable.BFPlayer_useArtwork, true));
        this.setDefaultArtwork(attributes.getDrawable(R.styleable.BFPlayer_defaultArtwork));
        this.setUseController(attributes.getBoolean(R.styleable.BFPlayer_useController, true));
        this.setControllerHideOnTouch(attributes.getBoolean(R.styleable.BFPlayer_hideOnTouch, true));
        this.setControllerAutoShow(attributes.getBoolean(R.styleable.BFPlayer_autoShow, true));
        this.setControllerHideDuringAds(attributes.getBoolean(R.styleable.BFPlayer_hideDuringAds, true));
        this.setShowBuffering(attributes.getBoolean(R.styleable.BFPlayer_showBuffering, true));
        this.setResizeMode(attributes.getInt(R.styleable.BFPlayer_resizeMode, AspectRatioFrameLayout.RESIZE_MODE_FIT));
        this.setShutterBackgroundColor(attributes.getColor(R.styleable.BFPlayer_shutterBackgroundColor, Color.BLACK));
        this.setKeepContentOnPlayerReset(attributes.getBoolean(R.styleable.BFPlayer_keepContentOnPlayerReset, false));
        this.setKeepScreenOn(attributes.getBoolean(R.styleable.BFPlayer_keepScreenOn, true));

My problem with this solution is two-fold:

  1. This duplicates the list of attributes between attrs.xml and BFPlayer.java, so if ExoPlayer adds a new attribute in a future release I'll have to remember to update two files instead of one
  2. A few attributes lack corresponding methods. There is no setSurfaceType method, for instance. This means that I physically cannot change this value from the default. The default creates a video renderer even when dealing with audio-only content, which means I'll be wasting CPU cycles and battery life for no reason when playing audio-only content

Still, this is the best I could come up with.

stevendesu
  • 15,753
  • 22
  • 105
  • 182