[JAVA] Do you really understand? How to check the library and license used by the app

TL;DR

Introduction

If you want to distribute your app on Google Play, you must properly comply with the license terms of the external library you used. Therefore, app developers need to know what external libraries their apps are using.

On Android, it's standard practice to use Gradle to deploy external libraries. Gradle will download to your local environment, including the libraries that the external library you want to use references (depends on). While Gradle hides the tedious work, you may actually be using an unexpected library.

build.gradle



//...

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

//...

ʻAppcompat-v7 is an almost indispensable library for making modern Android apps, and I think many people are using it. Did you know that apps that import ʻappcompat-v7 also import the libraries listed below?

There are a total of 30 libraries including ʻappcompat-v7. Keep in mind, these libraries are libraries where the user did not write ʻimplementation, but just one line of statement that **'appcompat-v7 ʻimplementation **.

In this article, I will explain how to find out the external libraries used in Android application production. It also explains how to check the Apache License 2.0 attribution notice, which is often applied to Android libraries.

Know the library you are using

This time, I will explain using the following dependencies as an example. Apache Commons Codec is added to the dependencies created as a result of proceeding with the Android Studio project creation wizard with the default settings. ..

build.gradle



//...

dependencies {
    //Android Studio added by default
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    //add to
    implementation 'commons-codec:commons-codec:1.11'
}

//...

Now, I will explain how to know the library you are using.

In fact, this can be understood by executing only one Gralde task. Let's run the ʻandroid Dependencies` task from the Gradle window.

pic1.jpg

Then, I think that the result came out in the Run window. Let's take a look at the blocks that start with releaseRuntimeClassPath.

androidDependencies execution result.



...

releaseRuntimeClasspath - Dependencies for runtime/packaging
+--- com.android.support:appcompat-v7:28.0.0@aar
+--- com.android.support.constraint:constraint-layout:1.1.3@aar
+--- commons-codec:commons-codec:1.11@jar
+--- com.android.support:support-fragment:28.0.0@aar
+--- com.android.support:animated-vector-drawable:28.0.0@aar
+--- com.android.support:support-core-ui:28.0.0@aar
+--- com.android.support:support-core-utils:28.0.0@aar
+--- com.android.support:support-vector-drawable:28.0.0@aar
+--- com.android.support:loader:28.0.0@aar
+--- com.android.support:viewpager:28.0.0@aar
+--- com.android.support:coordinatorlayout:28.0.0@aar
+--- com.android.support:drawerlayout:28.0.0@aar
+--- com.android.support:slidingpanelayout:28.0.0@aar
+--- com.android.support:customview:28.0.0@aar
+--- com.android.support:swiperefreshlayout:28.0.0@aar
+--- com.android.support:asynclayoutinflater:28.0.0@aar
+--- com.android.support:support-compat:28.0.0@aar
+--- com.android.support:versionedparcelable:28.0.0@aar
+--- com.android.support:collections:28.0.0@jar
+--- com.android.support:cursoradapter:28.0.0@aar
+--- android.arch.lifecycle:runtime:1.1.1@aar
+--- com.android.support:documentfile:28.0.0@aar
+--- com.android.support:localbroadcastmanager:28.0.0@aar
+--- com.android.support:print:28.0.0@aar
+--- android.arch.lifecycle:viewmodel:1.1.1@aar
+--- android.arch.lifecycle:livedata:1.1.1@aar
+--- android.arch.lifecycle:livedata-core:1.1.1@aar
+--- android.arch.lifecycle:common:1.1.1@jar
+--- android.arch.core:runtime:1.1.1@aar
+--- android.arch.core:common:1.1.1@jar
+--- com.android.support:interpolator:28.0.0@aar
+--- com.android.support:support-annotations:28.0.0@jar
\--- com.android.support.constraint:constraint-layout-solver:1.1.3@jar

...

The ʻandroidDependenciestask is a task that presents your app's dependencies. Normally, the run-time classpath of the release task matches the library you are actually including. Therefore, you can look at thereleaseRuntimeClasspath` to get a list of the libraries your app is using.

If you want to know more detailed dependencies, run the dependencies task.

pic2.jpg

Dependency execution result.



...

releaseCompileClasspath - Resolved configuration for compilation for variant: release
+--- com.android.support:appcompat-v7:28.0.0
|    +--- com.android.support:support-annotations:28.0.0
|    +--- com.android.support:support-compat:28.0.0
|    |    +--- com.android.support:support-annotations:28.0.0
|    |    +--- com.android.support:collections:28.0.0
|    |    |    \--- com.android.support:support-annotations:28.0.0
|    |    +--- android.arch.lifecycle:runtime:1.1.1
|    |    |    +--- android.arch.lifecycle:common:1.1.1
|    |    |    |    \--- com.android.support:support-annotations:26.1.0 -> 28.0.0
|    |    |    +--- android.arch.core:common:1.1.1
|    |    |    |    \--- com.android.support:support-annotations:26.1.0 -> 28.0.0
|    |    |    \--- com.android.support:support-annotations:26.1.0 -> 28.0.0
|    |    \--- com.android.support:versionedparcelable:28.0.0
|    |         +--- com.android.support:support-annotations:28.0.0
|    |         \--- com.android.support:collections:28.0.0 (*)
|    +--- com.android.support:collections:28.0.0 (*)
|    +--- com.android.support:cursoradapter:28.0.0
|    |    \--- com.android.support:support-annotations:28.0.0
|    +--- com.android.support:support-core-utils:28.0.0
|    |    +--- com.android.support:support-annotations:28.0.0
|    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    +--- com.android.support:documentfile:28.0.0
|    |    |    \--- com.android.support:support-annotations:28.0.0
|    |    +--- com.android.support:loader:28.0.0
|    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    +--- android.arch.lifecycle:livedata:1.1.1
|    |    |    |    +--- android.arch.core:runtime:1.1.1
|    |    |    |    |    +--- com.android.support:support-annotations:26.1.0 -> 28.0.0
|    |    |    |    |    \--- android.arch.core:common:1.1.1 (*)
|    |    |    |    +--- android.arch.lifecycle:livedata-core:1.1.1
|    |    |    |    |    +--- android.arch.lifecycle:common:1.1.1 (*)
|    |    |    |    |    +--- android.arch.core:common:1.1.1 (*)
|    |    |    |    |    \--- android.arch.core:runtime:1.1.1 (*)
|    |    |    |    \--- android.arch.core:common:1.1.1 (*)
|    |    |    \--- android.arch.lifecycle:viewmodel:1.1.1
|    |    |         \--- com.android.support:support-annotations:26.1.0 -> 28.0.0
|    |    +--- com.android.support:localbroadcastmanager:28.0.0
|    |    |    \--- com.android.support:support-annotations:28.0.0
|    |    \--- com.android.support:print:28.0.0
|    |         \--- com.android.support:support-annotations:28.0.0
|    +--- com.android.support:support-fragment:28.0.0
|    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    +--- com.android.support:support-core-ui:28.0.0
|    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    +--- com.android.support:support-core-utils:28.0.0 (*)
|    |    |    +--- com.android.support:customview:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    \--- com.android.support:support-compat:28.0.0 (*)
|    |    |    +--- com.android.support:viewpager:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    |    \--- com.android.support:customview:28.0.0 (*)
|    |    |    +--- com.android.support:coordinatorlayout:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    |    \--- com.android.support:customview:28.0.0 (*)
|    |    |    +--- com.android.support:drawerlayout:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    |    \--- com.android.support:customview:28.0.0 (*)
|    |    |    +--- com.android.support:slidingpanelayout:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    |    \--- com.android.support:customview:28.0.0 (*)
|    |    |    +--- com.android.support:interpolator:28.0.0
|    |    |    |    \--- com.android.support:support-annotations:28.0.0
|    |    |    +--- com.android.support:swiperefreshlayout:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    +--- com.android.support:support-compat:28.0.0 (*)
|    |    |    |    \--- com.android.support:interpolator:28.0.0 (*)
|    |    |    +--- com.android.support:asynclayoutinflater:28.0.0
|    |    |    |    +--- com.android.support:support-annotations:28.0.0
|    |    |    |    \--- com.android.support:support-compat:28.0.0 (*)
|    |    |    \--- com.android.support:cursoradapter:28.0.0 (*)
|    |    +--- com.android.support:support-core-utils:28.0.0 (*)
|    |    +--- com.android.support:support-annotations:28.0.0
|    |    +--- com.android.support:loader:28.0.0 (*)
|    |    \--- android.arch.lifecycle:viewmodel:1.1.1 (*)
|    +--- com.android.support:support-vector-drawable:28.0.0
|    |    +--- com.android.support:support-annotations:28.0.0
|    |    \--- com.android.support:support-compat:28.0.0 (*)
|    \--- com.android.support:animated-vector-drawable:28.0.0
|         +--- com.android.support:support-vector-drawable:28.0.0 (*)
|         \--- com.android.support:support-core-ui:28.0.0 (*)
+--- com.android.support.constraint:constraint-layout:1.1.3
|    \--- com.android.support.constraint:constraint-layout-solver:1.1.3
\--- commons-codec:commons-codec:1.11

...

ʻAndroidDependencies will tell you the library that will eventually be used in a bulleted format, while dependencies` will tell you the dependencies in a tree format. Use this to find out if you really need a library.

Find out what library

When I try to output the list with ʻandroid Dependencies, I get a lot of unknown libraries. Check out the Maven Repository (https://mvnrepository.com/) for such libraries. For example, if you look at ʻandroid.arch.lifecycle: viewmodel, the following page will appear.

pic3.jpg

From this page, you can see that ʻandroid.arch.lifecycle: viewmodel is apparently part of an Android package named Android Lifecycle ViewModel and is distributed under the Apache License 2.0. Therefore, you can see that ʻandroid.arch.lifecycle: viewmodel should follow the distribution conditions of Apache License 2.0.

In fact, it will do it automatically

I've explained it for a long time, but in fact, there are many Android Studio plugins that automatically output the above steps (and even create license display activities depending on the item **). Please refer to @ tyoro's article.

Some libraries that embed license displays in Android apps

Bonus: [Apache License 2.0] Know the NOTICE file

You might be wondering, "If you do it automatically, you won't do it anymore?" However, there are some tasks that cannot be automated when displaying the license to use the library licensed under Apache License 2.0. It is a notice of belonging.

Apache License 2.0 stipulates that if the library you use has attribution, you must show its contents visibly in the documentation. Files containing the contents of this attribution are called NOTICE files, etc.

The trouble is that in the Android (Java) world, NOTICE files are generally distributed by embedding them in a jar or aar. Also, NOTICE files have no fixed file name or format. In other words, ** you need to look around each jar or aar to see if it contains a file equivalent to the NOTICE file **.

Below are the steps to check efficiently (?) Using Android Studio.

  1. Click the combo box labeled ʻAndroid` in the Project window image.png
  2. Select Project from the combo box list to switch the display.
  3. Select the library you want to see from ʻExternal Libraries` image.png

You can see all the dependent libraries in Android Studio, right?

Now, let's check if there is a NOTICE file in the Android Lifecycle ViewModel. If you dig into Gradle: android.arch.lifecycle: viewmodel-1.1.1 ...

image.png

There was an unfamiliar file called ʻandroid.arch.lifecycle_viewmodel.version in META-INF`, but when I looked inside, only the version information was really described as the file name. Apparently there is no NOTICE file in the Android Lifecycle ViewModel as there are no other files.

Next, let's check if there is a NOTICE file in Commons-Codec of Apache. If you dig into Gradle: commons-codec: commons-codec: 1.11 @ jar ...

image.png

I found NOTICE.txt in META-INF of commons-codec-1.11.jar. When you open NOTICE.txt, you can see that the content of attribution (credit information) is written. It seems that this description should be quoted in the license display.

This time, the NOTICE file existed with the path META-INF / NOTICE.txt, but it is not uncommon for some libraries to exist with completely different file names and file paths. Let's search patiently.

in conclusion

Distributing software that does not comply with the license terms may, in the worst case, be sued by the author and lead to trial. Handle the licensed software properly.

Recommended Posts

Do you really understand? How to check the library and license used by the app
How to replace characters that you do not understand [Principle]
How to check the extension and size of uploaded files
How to install the language used in Ubuntu and how to build the environment
What to do if you don't like the code generated by swagger-codegen-cli
[Rails] How to apply the CSS used in the main app with Administrate
How do you write the ternary operator (? :)
How to find the tens and ones
How to embed and display youtube videos in Rails (You can also get the URL you entered by editing)
How to connect to lcalhost from your smartphone and use the app under development
What to do if you can't activate the select box created by bootstrap-select
How to display the amount of disk used by Docker container for each container
[swift5] How to transition from the app to an external site by specifying the URL
[Rails] How to decide the destination by "rails routes"
How to check the logs in the Docker container
How to add sound in the app (swift)
[Swift] How to link the app with Firebase
How to find the total score and average score
How to check Rails commands in the terminal
[Java] How to get the key and value stored in Map by iterative processing
[ruby] How to assign a value to a hash by referring to the value and key of another hash
How to return to the previous screen by Swipe operation
How to move to the details screen by clicking the image
Until you publish the app on the App Store by yourself
How to check only one RadioButton check by default (Note)
How to think when you suddenly understand about generics
Java classes and instances to understand in the figure
How to check CircleCI code and automatically deploy to Heroku
[Ruby] How to get the tens place and the ones place
[Linux] Easy commentary! How to check and change permissions
[Android] How to check if the Google Play developer service is installed when the app is launched
Check how to set the timeout when connecting with Spring + HikariCP + MySQL and executing SQL
I tried to make an app that allows you to post and chat by genre ~ App overview ~
[Ruby] How to get the value by specifying the key. Differences between hashes, symbols and fetch
What you need to do to open a file from the menu in the document-Based App macOS app