I have an android project with following structure:
-- Calendar
------app (app module)
----------build.gradle (module level)
------build.gradle (project level)
------Commons(A common project which i reuse across various projects)
----------common (common module in Commons project)
-------------build.gradle (for only common module level)
----------build.gradle(for Commons Project)
Now the problem is that if I compile Commons, deploy it to bintray and then use it as implementation 'com.amitkma.Commons:common:1.0.0'
in app module, all the dependencies (which are implemented in common build.gradle) is available to use in app module also. But if I use it like following
implementation project(:Commons:common)
, only dependencies provided using api
is available to use.
I want to know what is the difference between api
and implementation
with respect to module is compiled or used directly like above?
There are two things at play here:
api
andimplementation
when declaring dependencies. In short dependencies in theimplementation
scope are only visible at runtime because they are an implementation detail. Such libraries will use theruntime
scope in their published Maven metadata. More information in the documentationcompile
andruntime
were mixed by Gradle and thus allruntime
dependencies did appear on the compile classpath. Gradle 5 changes thisSo when you publish your component, the limitation of Gradle 4.x means that your
common
dependencies are available toapp
. Note that moving to Gradle 5 will cause a breakage there, as documented. And when you use the project directly, the separation is properly enforced.The fix is to simply promote dependencies that are part of the common api to the
api
configuration incommon
and for the runtime ones, declare them inapp
as after all they are directly required by it.