Nobody reads the licence when adding a dependency. The package solves the problem, the install command works, and the question of what obligations came with it is deferred until a customer's procurement team asks for a software bill of materials, or an acquirer's lawyers do. By then the dependency is load-bearing.
Short answer
Open source licences impose obligations, and the obligations vary enormously between them. Permissive licences generally require attribution and preservation of the notice. Copyleft licences add requirements about distributing source and about what happens to code linked with them, which interacts badly with the way mobile apps are distributed. The SPDX licence list is the standard reference identifying each licence unambiguously, and identifying what you have is the first step because most teams cannot answer that question.
What obligations actually attach
Attribution is the near-universal one. Most licences require the copyright notice and licence text to be included with the distributed software, which for a mobile app means a licences screen inside the app or an accessible equivalent. Shipping without it is a licence violation for a large share of the dependencies in a typical project.
Source availability applies to strong copyleft licences. If a licence requires that recipients receive the corresponding source of the work, and your app links that code, the obligation follows the distribution. This is the requirement that makes certain licences a poor fit for a closed-source commercial app.
Notice of modification is required by several licences when you change the code, which happens more than teams remember: a patched dependency vendored into the repository to fix a bug is a modification.
Patent grants and their termination clauses appear in several modern licences, and they can affect what happens if you assert a patent against a contributor.
Restrictions on use appear in licences that are not open source at all despite being distributed like they are, including source-available licences with field-of-use limits. These sit in dependency trees more often than people expect.
Why mobile distribution complicates it
The store model changes the analysis in ways that are not obvious.
Distribution happens through a third party under its own terms, and both Apple's App Review Guidelines and Google Play's policies impose their own conditions on what you distribute. Where a licence's terms conflict with the store's, the conflict has to be resolved rather than ignored, and historically some strong copyleft licences have been treated as incompatible with certain store terms.
Static linking is the norm. Mobile apps ship as a single artifact with dependencies compiled in, which removes the dynamic-linking distinction that some licence analyses rely on.
The binary is delivered to users, which means you are distributing, not merely operating a service. Teams used to server-side software sometimes carry over the assumption that internal use does not trigger distribution obligations, and shipping an app is distribution.
Transitive dependencies are numerous and invisible. A single package can pull in dozens, each with its own licence, and the licence you accepted is the union of all of them rather than the one at the top.
Building the inventory
You cannot comply with obligations you cannot enumerate, and the inventory is the part most teams skip.
Generate it from the build rather than from the manifest. What matters is what shipped, not what was declared, and build tooling on both platforms can produce a dependency list including transitive packages.
Record the SPDX identifier for each. Licence names in package metadata are inconsistent and sometimes wrong, and the SPDX identifier is the unambiguous form that makes automated checking possible.
Flag the ones without a clear licence. A dependency with no licence file is not permissively licensed by default; it is unlicensed, which means you have no rights to it beyond what copyright gives you, which is very little.
Note which dependencies you have modified, since that changes the obligations for several licences.
Keep it current. An inventory generated once is a snapshot, and the value comes from regenerating it per release so that a new transitive dependency with an unexpected licence is visible when it arrives rather than a year later.
Meeting the attribution requirement
This is the obligation almost everyone has and many apps fail, and it is the cheapest to fix.
Ship a licences screen. Both platforms have conventions for this, usually under settings or about, and there are established tools that generate the content from the dependency inventory automatically.
Include the full licence text, not a list of names. Most licences require the text itself to accompany the distribution, and a list saying which libraries were used does not satisfy that.
Keep it generated rather than hand-maintained. A hand-written attribution screen is out of date after the next dependency change, and a generated one is correct by construction.
Make it reachable without an account. Attribution that sits behind a login is not accessible to everyone who received the software.
What to do about a problematic licence
Occasionally the inventory surfaces something incompatible with how you distribute, and the options are finite.
Replace the dependency. Usually the cleanest answer, and easier the earlier you find it, which is the practical argument for generating the inventory before a dependency becomes structural.
Isolate it. Some obligations attach differently depending on how code is combined, and there may be an architecture where the dependency runs as a separate component. This is a genuine legal question rather than an engineering preference, and it is where you want advice rather than a forum answer.
Comply with the obligation. If the requirement is to make corresponding source available and you can do that, it may simply be acceptable, and a number of commercial apps do exactly this.
Obtain a different licence. Many projects offer commercial licensing alongside an open one, and for a dependency you genuinely need this is often the fastest resolution.
What is not a strategy is hoping. Licence obligations do not expire because nobody noticed, and the moment they surface is usually a due-diligence process where the cost of the problem is highest.
Where this connects to security
The same inventory answers a different question, which is why the effort is worth more than compliance alone.
Knowing every dependency in a shipped build is the prerequisite for knowing whether any of them has a known vulnerability, and it is the same list. Teams that build a licence inventory get a vulnerability inventory almost free.
It also surfaces dependencies nobody remembers adding, which is a recurring finding on mobile projects and a reasonable prompt to remove code that is no longer used.
An automated pass over the built artifact such as PTKD.com is a practical way to see what actually shipped, including SDKs and libraries present in the binary that a package manifest may not reflect. Android's security best practices and the OWASP MASVS both assume you can enumerate your dependencies, and that assumption is the one most often unmet.
A note on scope: everything here is engineering practice for making obligations visible and manageable. Whether a specific licence combination is acceptable for your product is a legal question, and the point of the inventory is to let a lawyer answer it in an hour rather than a month.
The questions you will eventually be asked
Compliance work feels abstract until someone external asks, and knowing the questions in advance makes the preparation concrete.
Can you provide a software bill of materials? This arrives from enterprise customers and increasingly from public sector buyers. A generated inventory answers it in minutes; without one it becomes a week of archaeology.
Which of your dependencies are copyleft, and how are they combined? This is a due-diligence question and it is asked because the answer occasionally changes a valuation. Having it documented, with the reasoning reviewed once by someone qualified, is a much better position than assembling it under deadline.
Do you have the right to distribute all of the code in your product? A dependency with no licence file makes this answer no, strictly speaking, and finding one during diligence is worse than finding it now.
How do you satisfy attribution requirements? Pointing at an in-app licences screen ends the conversation. Explaining that you intend to build one does not.
What is your process when a dependency is added? The answer they want is that licence identification happens at the point of addition, automatically, rather than as a periodic clean-up.
Making it a process rather than a project
The reason licence work is painful is that it gets done as a one-off audit and then decays immediately.
Put the inventory generation into the build, so it produces an artifact for every release and drift is visible.
Add an allowed-licence list and fail the build on anything outside it. This sounds heavy-handed and it is the single most effective control, because it moves the decision to the moment the dependency is added, when replacing it is cheap.
Keep a short exceptions file with a reason and an owner for each. Exceptions are legitimate; undocumented exceptions are how a policy stops meaning anything.
Regenerate the attribution screen as part of the same step, so it cannot fall out of date without the build noticing.
That is perhaps a day of setup, and it converts a recurring audit into something that happens automatically and produces evidence.
Licences that are not what they look like
Two categories cause disproportionate trouble because they resemble ordinary open source and are not.
Source-available licences permit reading and modifying the code while restricting use, often forbidding competing commercial offerings or requiring a licence above a revenue threshold. Several widely used packages have moved to these terms in recent years, usually at a major version, which means an ordinary dependency upgrade can change your obligations without any signal in the changelog you read.
Dual-licensed projects offer a copyleft licence and a commercial one. Using the copyleft version is fine if you can meet its terms and is frequently not what a closed-source product wants, and the commercial option exists precisely for that case.
The practical defence for both is that licence identification runs on every dependency change, including upgrades, rather than only on new additions. A version bump that changes a licence is invisible to a process that only checks packages the first time it sees them.
A table of what each obligation usually requires
| Obligation | Typically triggered by | What shipping it means |
|---|---|---|
| Attribution | Almost every licence | Licences screen with full text |
| Notice of modification | Several permissive and copyleft licences | Record what you changed |
| Corresponding source | Strong copyleft | Provide source to recipients |
| Patent terms | Several modern licences | Understand termination clauses |
| Use restrictions | Source-available licences | Check field-of-use limits |
The table is deliberately general, because the exact trigger depends on the specific licence text and on how the code is combined. Its purpose is to show that the obligations are few in number and different in kind, which makes the inventory the useful artifact rather than a licence-by-licence reading exercise.
What to take away
Most dependencies carry obligations, and attribution is the near-universal one that most apps do not meet.
Generate the dependency inventory from the build rather than the manifest, record SPDX identifiers, and regenerate per release.
Mobile distribution is distribution, static linking is the norm, and store terms add their own conditions, so server-side licence intuitions do not transfer.
Ship a generated licences screen containing full licence text, reachable without an account, and regenerate it in the same build step that produces the inventory so it cannot silently fall out of date.
And treat the inventory as dual purpose, because the list that answers the licence question is the same list that answers the vulnerability question.
Run licence identification on upgrades as well as additions, since a package can change its terms at a major version without any signal in the changelog you actually read.



