LoginSignup
1
2

More than 5 years have passed since last update.

Android Studio 3にしたらJavaアプリケーションの依存関係が解決できなくなったのでその対処方法

Last updated at Posted at 2017-12-09

症状

Android Studio 3.xに対応するため、com.android.tools.build:gradle:3.0.1に変更したところ、RunConfigurationのApplicationから実行できていたpure Javaなアプリケーションの依存が解決できなくなった。
つまりNoClassDefFoundErrorが出る。

要はあるModuleにこんなJava Application存在していた。
スクリーンショット 2017-12-09 20.44.08.png

対処 (ベストプラクティスはこちら)

注意: これだとブレークポイントで止まれない。止まることができる方法は後述

このように、gradle runで実行できるように設定する。
画像ではlibというモジュール名になってる。
:yourModuleName:run

スクリーンショット 2017-12-09 20.44.23.png

そして、対象のmoduleのbuild.gradleに以下を追記。

build.gradle
apply plugin: 'application'

mainClassName = "your.main.class.myClass"

要はresourceが取得できなかった問題に似ている?
Android StudioでJava Libraryなモジュールからリソースを含んだ実行可能なJarを生成するまで

ブレークポイントでも止まる実行方法

注意: ブレークしてしばらくしたらgradleのtaskが死んでしまうのでダメか...

libというJavaなモジュールがあって、myClass.javaがあって、Gsonを参照しているとする。

myClass.java
package com.example.lib;

import com.google.gson.GsonBuilder;

public class myClass {
    public myClass() {
        System.out.println(GsonBuilder.class);
        System.out.println("hoge");
    }
    public static void main(String[] args) throws Exception {
        new myClass();
    }
}

build.gradleにJavaExecなtaskを適当な名前で追加する。
ここでexecuteHoteとかexecutePiyoとか名前を変えて、それぞれのmainを設定しておけば、mainを複数作りたいmoduleでも対応できると思う。

build.gradle
apply plugin: 'application'

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.google.code.gson:gson:2.8.2'
}

mainClassName = "" //意味ないように見えるが、これがないとプロジェクト全体のbuildが通らない

task executeMyClass(type: JavaExec) {
    main = "com.example.lib.myClass"
    classpath = sourceSets.main.runtimeClasspath
}

Add New ConfigurationからRemoteを追加。Nameは適当に。
Search sources using module's classpath:<whole project>でのままでもいいかもしれない

Before launchのところからRun Gradle taskを追加する。
Grade projectは実行したいprojectであり、今回はlib。
Talksには:lib:executeMyClass --debug-jvmとする。(--debug-jvmによってデバッガのアタッチを待ってくれる。)
スクリーンショット 2017-12-10 22.16.50.png
まとめるとこんな感じになる。
スクリーンショット 2017-12-10 22.12.58.png

実行

Run debugをするとBefore launchに従ってexecuteMyClassが実行される。
が、これはデバッガからのアタッチを待ってるので終わらない。

なのでStopする。要は画像の一番右のやつをクリック。
スクリーンショット 2017-12-10 22.25.20.png
そしたら、ブレークポイントで止まる。

JavaExec
Gradle to execute Java class (without modifying build.gradle)

Stopしたのになんで実行されてんだ感がすごいし、Android Studio 2.xの時より面倒になったけど、とりあえず動くので良しとする。動かん。

そしてベストプラクティス

前章にあるように、build.gradletask executeMyClassを同じように作る。
Add New ConfigurationからRemoteを追加するが、Nameは適当にして、他は全てデフォルトでそのままOKする。

おもむろにshを実行する。

executeMyClass.sh
./gradlew :lib:executeMyClass --debug-jvm

すると、EXECUTINGで止まったままになる。

Android Studioでさっき追加したRemoteをdebugで実行すると...なんとアタッチできる。めでたし。
エラーはターミナルに表示されるので、落ちたクラスにクリックでジャンプはできない。

Android Studio 2.x時代と同じように実行できる方法を発見したので真のベストプラクティスはこちら

余談

Android Studio 2.xの時と比べるとすごい手間であるが、時代に取り残されないようにするためにはこうするしかないのか...?
そもそもAndroid StudioでJavaアプリケーションを動かすのが間違ってるのかもしれない。(と思ったけど、Androidなモジュールがないプロジェクトであれば、ApplicationのConfigurationから実行は可能なのが余計に謎)
Gradle plugin 3.xでimplementationとかapiとか増えたせいの仕様変更が原因な気がするけど実際問題よく分からん...

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2