android: add grpc-android into main build (#6793)

Add grpc-android into main build. grpc-android will be built if Gradle option skipAndroid is false. This change also migrates deprecated Robolectric methods to androidx.test methods.
This commit is contained in:
Chengyuan Zhang 2020-03-04 15:40:39 -08:00 committed by GitHub
parent a57f1a9636
commit 5ba663bcf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 135 deletions

View File

@ -1,27 +1,11 @@
apply plugin: 'com.android.library' plugins {
id "maven-publish"
group = "io.grpc" id "com.android.library"
version = "1.29.0-SNAPSHOT" // CURRENT_GRPC_VERSION id "digital.wup.android-maven-publish"
description = 'gRPC: Android'
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.0'
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.8.1"
classpath "digital.wup:android-maven-publish:3.6.2"
}
} }
apply plugin: "maven-publish" description = 'gRPC: Android'
apply plugin: "net.ltgt.errorprone"
apply plugin: "digital.wup.android-maven-publish"
apply plugin: "signing"
android { android {
compileSdkVersion 28 compileSdkVersion 28
@ -39,20 +23,16 @@ android {
repositories { repositories {
google() google()
jcenter() jcenter()
mavenCentral()
mavenLocal()
} }
dependencies { dependencies {
errorprone 'com.google.errorprone:error_prone_core:2.3.4' implementation project(':grpc-core')
errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
implementation 'io.grpc:grpc-core:1.29.0-SNAPSHOT' // CURRENT_GRPC_VERSION testImplementation project('::grpc-okhttp')
testImplementation libraries.androidx_test
testImplementation 'io.grpc:grpc-okhttp:1.29.0-SNAPSHOT' // CURRENT_GRPC_VERSION testImplementation libraries.junit
testImplementation 'junit:junit:4.12' testImplementation libraries.robolectric
testImplementation 'org.robolectric:robolectric:4.3.1' testImplementation libraries.truth
testImplementation 'com.google.truth:truth:1.0.1'
} }
task javadocs(type: Javadoc) { task javadocs(type: Javadoc) {
@ -83,81 +63,11 @@ task sourcesJar(type: Jar) {
publishing { publishing {
publications { publications {
maven(MavenPublication) { maven {
from components.android from components.android
artifact javadocJar artifact javadocJar
artifact sourcesJar artifact sourcesJar
pom {
name = project.group + ":" + project.name
url = 'https://github.com/grpc/grpc-java'
afterEvaluate {
// description is not available until evaluated.
description = project.description
}
scm {
connection = 'scm:git:https://github.com/grpc/grpc-java.git'
developerConnection = 'scm:git:git@github.com:grpc/grpc-java.git'
url = 'https://github.com/grpc/grpc-java'
}
licenses {
license {
name = 'Apache 2.0'
url = 'https://opensource.org/licenses/Apache-2.0'
}
}
developers {
developer {
id = "grpc.io"
name = "gRPC Contributors"
email = "grpc-io@googlegroups.com"
url = "https://grpc.io/"
organization = "gRPC Authors"
organizationUrl = "https://www.google.com"
}
}
withXml {
asNode().dependencies.'*'.findAll() { dep ->
dep.artifactId.text() in ['grpc-api', 'grpc-core']
}.each() { core ->
core.version*.value = "[" + core.version.text() + "]"
}
}
}
}
}
repositories {
maven {
if (rootProject.hasProperty('repositoryDir')) {
url = new File(rootProject.repositoryDir).toURI()
} else {
String stagingUrl
if (rootProject.hasProperty('repositoryId')) {
stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' +
rootProject.repositoryId
} else {
stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
}
credentials {
if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) {
username = rootProject.ossrhUsername
password = rootProject.ossrhPassword
}
}
def releaseUrl = stagingUrl
def snapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
url = version.endsWith('SNAPSHOT') ? snapshotUrl : releaseUrl
}
} }
} }
} }
signing {
required false
sign publishing.publications.maven
}

View File

@ -1 +0,0 @@
rootProject.name = 'grpc-android'

View File

@ -28,6 +28,7 @@ import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import androidx.test.core.app.ApplicationProvider;
import io.grpc.CallOptions; import io.grpc.CallOptions;
import io.grpc.ClientCall; import io.grpc.ClientCall;
import io.grpc.ManagedChannel; import io.grpc.ManagedChannel;
@ -39,7 +40,6 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements; import org.robolectric.annotation.Implements;
@ -54,24 +54,32 @@ import org.robolectric.shadows.ShadowNetworkInfo;
public final class AndroidChannelBuilderTest { public final class AndroidChannelBuilderTest {
private final NetworkInfo WIFI_CONNECTED = private final NetworkInfo WIFI_CONNECTED =
ShadowNetworkInfo.newInstance( ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.CONNECTED, ConnectivityManager.TYPE_WIFI, 0, true, true); NetworkInfo.DetailedState.CONNECTED,
ConnectivityManager.TYPE_WIFI,
0,
true,
NetworkInfo.State.CONNECTED);
private final NetworkInfo WIFI_DISCONNECTED = private final NetworkInfo WIFI_DISCONNECTED =
ShadowNetworkInfo.newInstance( ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.DISCONNECTED, ConnectivityManager.TYPE_WIFI, 0, true, false); NetworkInfo.DetailedState.DISCONNECTED,
ConnectivityManager.TYPE_WIFI,
0,
true,
NetworkInfo.State.DISCONNECTED);
private final NetworkInfo MOBILE_CONNECTED = private final NetworkInfo MOBILE_CONNECTED =
ShadowNetworkInfo.newInstance( ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.CONNECTED, NetworkInfo.DetailedState.CONNECTED,
ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_MOBILE,
ConnectivityManager.TYPE_MOBILE_MMS, ConnectivityManager.TYPE_MOBILE_MMS,
true, true,
true); NetworkInfo.State.CONNECTED);
private final NetworkInfo MOBILE_DISCONNECTED = private final NetworkInfo MOBILE_DISCONNECTED =
ShadowNetworkInfo.newInstance( ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.DISCONNECTED, NetworkInfo.DetailedState.DISCONNECTED,
ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_MOBILE,
ConnectivityManager.TYPE_MOBILE_MMS, ConnectivityManager.TYPE_MOBILE_MMS,
true, true,
false); NetworkInfo.State.DISCONNECTED);
private ConnectivityManager connectivityManager; private ConnectivityManager connectivityManager;
@ -79,7 +87,9 @@ public final class AndroidChannelBuilderTest {
public void setUp() { public void setUp() {
connectivityManager = connectivityManager =
(ConnectivityManager) (ConnectivityManager)
RuntimeEnvironment.application.getSystemService(Context.CONNECTIVITY_SERVICE); ApplicationProvider
.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
} }
@Test @Test
@ -103,8 +113,9 @@ public final class AndroidChannelBuilderTest {
// Network change and shutdown should be no-op for the channel without an Android Context // Network change and shutdown should be no-op for the channel without an Android Context
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdown(); androidChannel.shutdown();
assertThat(delegateChannel.resetCount).isEqualTo(0); assertThat(delegateChannel.resetCount).isEqualTo(0);
@ -131,48 +142,55 @@ public final class AndroidChannelBuilderTest {
TestChannel delegateChannel = new TestChannel(); TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel = ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel( new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext()); delegateChannel, ApplicationProvider.getApplicationContext());
assertThat(delegateChannel.resetCount).isEqualTo(0); assertThat(delegateChannel.resetCount).isEqualTo(0);
// On API levels < 24, the broadcast receiver will invoke resetConnectBackoff() on the first // On API levels < 24, the broadcast receiver will invoke resetConnectBackoff() on the first
// connectivity action broadcast regardless of previous connection status // connectivity action broadcast regardless of previous connection status
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1); assertThat(delegateChannel.resetCount).isEqualTo(1);
// The broadcast receiver may fire when the active network status has not actually changed // The broadcast receiver may fire when the active network status has not actually changed
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1); assertThat(delegateChannel.resetCount).isEqualTo(1);
// Drop the connection // Drop the connection
shadowOf(connectivityManager).setActiveNetworkInfo(null); shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1); assertThat(delegateChannel.resetCount).isEqualTo(1);
// Notify that a new but not connected network is available // Notify that a new but not connected network is available
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_DISCONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_DISCONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1); assertThat(delegateChannel.resetCount).isEqualTo(1);
// Establish a connection // Establish a connection
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(2); assertThat(delegateChannel.resetCount).isEqualTo(2);
// Disconnect, then shutdown the channel and verify that the broadcast receiver has been // Disconnect, then shutdown the channel and verify that the broadcast receiver has been
// unregistered // unregistered
shadowOf(connectivityManager).setActiveNetworkInfo(null); shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdown(); androidChannel.shutdown();
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(2); assertThat(delegateChannel.resetCount).isEqualTo(2);
// enterIdle is not called on API levels < 24 // enterIdle is not called on API levels < 24
@ -186,7 +204,7 @@ public final class AndroidChannelBuilderTest {
TestChannel delegateChannel = new TestChannel(); TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel = ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel( new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext()); delegateChannel, ApplicationProvider.getApplicationContext());
assertThat(delegateChannel.resetCount).isEqualTo(0); assertThat(delegateChannel.resetCount).isEqualTo(0);
assertThat(delegateChannel.enterIdleCount).isEqualTo(0); assertThat(delegateChannel.enterIdleCount).isEqualTo(0);
@ -227,7 +245,7 @@ public final class AndroidChannelBuilderTest {
TestChannel delegateChannel = new TestChannel(); TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel = ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel( new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext()); delegateChannel, ApplicationProvider.getApplicationContext());
// The first onAvailable() may just signal that the device was connected when the callback is // The first onAvailable() may just signal that the device was connected when the callback is
// registered, rather than indicating a changed network, so we do not enter idle. // registered, rather than indicating a changed network, so we do not enter idle.
@ -248,15 +266,17 @@ public final class AndroidChannelBuilderTest {
TestChannel delegateChannel = new TestChannel(); TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel = ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel( new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext()); delegateChannel, ApplicationProvider.getApplicationContext());
shadowOf(connectivityManager).setActiveNetworkInfo(null); shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdownNow(); androidChannel.shutdownNow();
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast( ApplicationProvider
new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); .getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(0); assertThat(delegateChannel.resetCount).isEqualTo(0);
} }
@ -268,7 +288,7 @@ public final class AndroidChannelBuilderTest {
TestChannel delegateChannel = new TestChannel(); TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel = ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel( new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext()); delegateChannel, ApplicationProvider.getApplicationContext());
androidChannel.shutdownNow(); androidChannel.shutdownNow();
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED); shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
@ -318,6 +338,7 @@ public final class AndroidChannelBuilderTest {
} }
@Implementation(minSdk = N) @Implementation(minSdk = N)
@Override
protected void registerDefaultNetworkCallback( protected void registerDefaultNetworkCallback(
ConnectivityManager.NetworkCallback networkCallback) { ConnectivityManager.NetworkCallback networkCallback) {
defaultNetworkCallbacks.add(networkCallback); defaultNetworkCallbacks.add(networkCallback);

View File

@ -157,6 +157,7 @@ subprojects {
mockito: 'org.mockito:mockito-core:2.28.2', mockito: 'org.mockito:mockito-core:2.28.2',
truth: 'com.google.truth:truth:1.0.1', truth: 'com.google.truth:truth:1.0.1',
guava_testlib: "com.google.guava:guava-testlib:${guavaVersion}", guava_testlib: "com.google.guava:guava-testlib:${guavaVersion}",
androidx_test: "androidx.test:core:1.2.0",
robolectric: "org.robolectric:robolectric:4.3.1", robolectric: "org.robolectric:robolectric:4.3.1",
// Benchmark dependencies // Benchmark dependencies

View File

@ -16,7 +16,6 @@ echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3"
LOCAL_MVN_TEMP=$(mktemp -d) LOCAL_MVN_TEMP=$(mktemp -d)
pushd "$GRPC_JAVA_DIR/android" pushd "$GRPC_JAVA_DIR/android"
../gradlew publish \ ../gradlew publish \
--include-build "$GRPC_JAVA_DIR" \
-Dorg.gradle.parallel=false \ -Dorg.gradle.parallel=false \
-PskipCodegen=true \ -PskipCodegen=true \
-PrepositoryDir="$LOCAL_MVN_TEMP" -PrepositoryDir="$LOCAL_MVN_TEMP"

View File

@ -86,4 +86,6 @@ if (settings.hasProperty('skipAndroid') && skipAndroid.toBoolean()) {
println '*** Android SDK is required. To avoid building Android projects, set -PskipAndroid=true' println '*** Android SDK is required. To avoid building Android projects, set -PskipAndroid=true'
include ":grpc-cronet" include ":grpc-cronet"
project(':grpc-cronet').projectDir = "$rootDir/cronet" as File project(':grpc-cronet').projectDir = "$rootDir/cronet" as File
include ":grpc-android"
project(':grpc-android').projectDir = "$rootDir/android" as File
} }