アスペクトを使用し、Maven経由で利用できるライブラリがあります。現在、そのライブラリをAndroidアプリケーションで使用しようとしています。
このプラグイン をアプリのgradleファイルに含めると、すべて正常に機能しますが、私の目標は、classpath 'com.uphyca.gradle:gradle-Android-aspectj-plugin:0.9.+'
とapply plugin: 'Android-aspectj'
(プラグインに必要)をに抽出することです。アプリで宣言する代わりに、my.libgradleファイル。
それは可能ですか?
アプリgradleファイル:
classpath 'com.uphyca.gradle:gradle-Android-aspectj-plugin:0.9.+'
apply plugin: 'Android-aspectj'
dependencies {
compile 'my.lib:example:1.0.0'
}
目標:
アプリgradleファイル:
dependencies {
compile 'my.lib:example:1.0.0'
}
my.lib gradleファイル:
classpath 'com.uphyca.gradle:gradle-Android-aspectj-plugin:0.9.+'
apply plugin: 'Android-aspectj'
dependencies {
compile 'org.aspectj:aspectjrt:1.7.3'
}
私も同じ問題を抱えていました。これは私がそれを解決するためにしたすべてです。
ルート/メインプロジェクト
ルートプロジェクトに、クラスのウィービングに必要なajcコンパイラを含むAspectJツールを追加します。 (これをライブラリのbuild.gradleファイルに追加することもできますが、ライブラリに対応するために作成するgradleプラグインはajcを使用するため、ここに追加することをお勧めします。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.Android.tools.build:gradle:1.2.3'
classpath 'org.aspectj:aspectjtools:1.8.5'
}
図書館プロジェクト
ライブラリのbuild.gradleファイルで、次のようになっていることを確認します。主な追加は、上部のimportステートメントと、Androidビルドプロパティの下のコードです。
import com.Android.build.gradle.LibraryPlugin
import org.aspectj.bridge.iMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
apply plugin: 'com.Android.library'
dependencies {
compile 'org.aspectj:aspectjrt:1.8.5'
}
Android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
}
}
}
Android.libraryVariants.all { variant ->
LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin)
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", Android.bootClasspath.join(File.pathSeparator)
]
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (iMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case iMessage.ABORT:
case iMessage.ERROR:
case iMessage.FAIL:
log.error message.message, message.thrown
break;
case iMessage.WARNING:
case iMessage.INFO:
log.info message.message, message.thrown
break;
case iMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
つまり、プロジェクトがコンパイルされているときに、ajc(AspectJのweaver)コマンドがAspectJとJavaソースファイルと.classファイルをコンパイルしてウィービングし、任意のJava VM。
これを実行するには、タスクにライブラリに関する引数が必要です。これが、args変数を作成する理由です。
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", Android.bootClasspath.join(File.pathSeparator)
]
次に、作成されたメッセージハンドラーは、ajcに渡されて、ajcがクラスをコンパイル/ウィービングしている間に発生しているイベントのメッセージを蓄積します。次に、プロジェクトロガーに渡され、プロジェクトロガーは、ajcが生成した重要なエラーや警告を出力します。たとえば、アドバイスでポイントカットを参照できない場合は、ポイントカットが検出され、gradleコンソールに表示されます。
したがって、上記で説明したことはすべて、基本的にここで行われています。 argsとメッセージハンドラーがajc(AspectJコンパイラー)のMain関数に渡される場所。
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (iMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case iMessage.ABORT:
case iMessage.ERROR:
case iMessage.FAIL:
log.error message.message, message.thrown
Gradleプラグイン
アスペクトがcom.uphyca.gradle:gradle-Android-aspectj-plugin
AspectJプラグインを使用してライブラリのモジュールに組み込まれている間、アプリモジュールをターゲットにしていたため、ライブラリのポイントカット/アドバイスはトリガーされませんでした。したがって、ライブラリのアスペクトをアプリのモジュールに組み込むには、プロジェクトのgradleプラグインを作成する必要があります。したがって、あなたがあなたの目標として定義したことはあなたの質問は不可能であるということです、これはそれができる唯一の方法です。
これがプラグインの外観です。 (プラグインはgroovyで実行されます)。
プラグインのbuild.gradle
apply plugin: 'groovy'
targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_7
dependencies {
compile gradleApi()
compile localGroovy()
compile 'com.Android.tools.build:gradle:1.1.0-rc3'
compile 'org.aspectj:aspectjtools:1.8.5'
compile 'org.aspectj:aspectjrt:1.8.5'
}
次に、実際のクラス。
import com.Android.build.gradle.AppPlugin
import com.Android.build.gradle.LibraryPlugin
import org.aspectj.bridge.iMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
public class YourPlugin implements Plugin<Project> {
@Override void apply(Project project) {
def hasApp = project.plugins.withType(AppPlugin)
def hasLib = project.plugins.withType(LibraryPlugin)
if (!hasApp && !hasLib) {
throw new IllegalStateException("'Android' or 'Android-library' plugin required.")
}
final def log = project.logger
final def variants
if (hasApp) {
variants = project.Android.applicationVariants
} else {
variants = project.Android.libraryVariants
}
project.dependencies {
compile 'com.name:example:1.0'
// TODO this should come transitively
compile 'org.aspectj:aspectjrt:1.8.5'
}
variants.all { variant ->
variant.dex.doFirst {
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.Android.bootClasspath.join(File.pathSeparator)
]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
for (iMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case iMessage.ABORT:
case iMessage.ERROR:
case iMessage.FAIL:
log.error message.message, message.thrown
break;
case iMessage.WARNING:
log.warn message.message, message.thrown
break;
case iMessage.INFO:
log.info message.message, message.thrown
break;
case iMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
}
}
私はこれがたくさんのように見えるかもしれないことを知っていますが、解決策は同じままなので、コピーと貼り付けがたくさんあります。クラスをよく見ると、ライブラリモジュールで行われているのと同じことがアプリのモジュールに適用されています。これに対して行う主な変更は、ここで行われるプラグインを介して、ライブラリモジュールをプロジェクトの依存関係に追加することです。
project.dependencies {
compile 'com.letz:example-library:1.0'
// TODO this should come transitively
compile 'org.aspectj:aspectjrt:1.8.5'
}
開発中にライブラリをプラグインで使用できるようにするには、ライブラリがローカルのMavenリポジトリにデプロイされていることを確認する必要があります。これは、このプラグイン( https://github.com/dcendents/Android-maven-gradle-plugin )をライブラリモジュールに適用し、gradle install
タスクを実行することで実行できます。
最終ステップ
それがすべて完了したら、これをbuild.gradleファイルに追加して、テスト用のサンプルアプリに適用できます。
buildscript {
repositories {
mavenCentral()
//Only necessary when developing locally.
mavenLocal()
}
dependencies {
classpath 'com.letz:example-plugin:1.0'
}
}
apply plugin: 'example-plugin'
これが完了すると、プラグインが適用されるとライブラリがプロジェクトに追加されるため、ライブラリをアプリで使用できるようになります。
それでも混乱する場合は、このソリューションを実装したプロジェクトがGithubにあるため、幸運を祈っています。フォークして、プラグインのプロジェクトをコピーし、必要な変更を加えてください。
このプロジェクトはFlenderと呼ばれ、接続チェックが必要なメソッドに注釈を付けるために使用されます。ここにリンクがあります https://github.com/jd-alexander/flender
この回答がお役に立てば幸いです。