Skip to content

Commit

Permalink
android: add grpc-android into main build (#6793)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
voidzcy committed Mar 4, 2020
1 parent a57f1a9 commit 5ba663b
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 135 deletions.
114 changes: 12 additions & 102 deletions android/build.gradle
@@ -1,27 +1,11 @@
apply plugin: 'com.android.library'
plugins {
id "maven-publish"

group = "io.grpc"
version = "1.29.0-SNAPSHOT" // CURRENT_GRPC_VERSION
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"
}
id "com.android.library"
id "digital.wup.android-maven-publish"
}

apply plugin: "maven-publish"
apply plugin: "net.ltgt.errorprone"
apply plugin: "digital.wup.android-maven-publish"
apply plugin: "signing"
description = 'gRPC: Android'

android {
compileSdkVersion 28
Expand All @@ -39,20 +23,16 @@ android {
repositories {
google()
jcenter()
mavenCentral()
mavenLocal()
}

dependencies {
errorprone 'com.google.errorprone:error_prone_core:2.3.4'
errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
implementation project(':grpc-core')

implementation 'io.grpc:grpc-core:1.29.0-SNAPSHOT' // CURRENT_GRPC_VERSION

testImplementation 'io.grpc:grpc-okhttp:1.29.0-SNAPSHOT' // CURRENT_GRPC_VERSION
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'com.google.truth:truth:1.0.1'
testImplementation project('::grpc-okhttp')
testImplementation libraries.androidx_test
testImplementation libraries.junit
testImplementation libraries.robolectric
testImplementation libraries.truth
}

task javadocs(type: Javadoc) {
Expand Down Expand Up @@ -83,81 +63,11 @@ task sourcesJar(type: Jar) {

publishing {
publications {
maven(MavenPublication) {
maven {
from components.android

artifact javadocJar
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
}
1 change: 0 additions & 1 deletion android/settings.gradle

This file was deleted.

Expand Up @@ -28,6 +28,7 @@
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import androidx.test.core.app.ApplicationProvider;
import io.grpc.CallOptions;
import io.grpc.ClientCall;
import io.grpc.ManagedChannel;
Expand All @@ -39,7 +40,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
Expand All @@ -54,32 +54,42 @@
public final class AndroidChannelBuilderTest {
private final NetworkInfo WIFI_CONNECTED =
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 =
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 =
ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.CONNECTED,
ConnectivityManager.TYPE_MOBILE,
ConnectivityManager.TYPE_MOBILE_MMS,
true,
true);
NetworkInfo.State.CONNECTED);
private final NetworkInfo MOBILE_DISCONNECTED =
ShadowNetworkInfo.newInstance(
NetworkInfo.DetailedState.DISCONNECTED,
ConnectivityManager.TYPE_MOBILE,
ConnectivityManager.TYPE_MOBILE_MMS,
true,
false);
NetworkInfo.State.DISCONNECTED);

private ConnectivityManager connectivityManager;

@Before
public void setUp() {
connectivityManager =
(ConnectivityManager)
RuntimeEnvironment.application.getSystemService(Context.CONNECTIVITY_SERVICE);
ApplicationProvider
.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
}

@Test
Expand All @@ -103,8 +113,9 @@ public void nullContextDoesNotThrow_api23() {

// Network change and shutdown should be no-op for the channel without an Android Context
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdown();

assertThat(delegateChannel.resetCount).isEqualTo(0);
Expand All @@ -131,48 +142,55 @@ public void resetConnectBackoff_api23() {
TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext());
delegateChannel, ApplicationProvider.getApplicationContext());
assertThat(delegateChannel.resetCount).isEqualTo(0);

// On API levels < 24, the broadcast receiver will invoke resetConnectBackoff() on the first
// connectivity action broadcast regardless of previous connection status
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1);

// The broadcast receiver may fire when the active network status has not actually changed
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1);

// Drop the connection
shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1);

// Notify that a new but not connected network is available
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_DISCONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(1);

// Establish a connection
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
assertThat(delegateChannel.resetCount).isEqualTo(2);

// Disconnect, then shutdown the channel and verify that the broadcast receiver has been
// unregistered
shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdown();
shadowOf(connectivityManager).setActiveNetworkInfo(MOBILE_CONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));

assertThat(delegateChannel.resetCount).isEqualTo(2);
// enterIdle is not called on API levels < 24
Expand All @@ -186,7 +204,7 @@ public void resetConnectBackoffAndEnterIdle_api24() {
TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext());
delegateChannel, ApplicationProvider.getApplicationContext());
assertThat(delegateChannel.resetCount).isEqualTo(0);
assertThat(delegateChannel.enterIdleCount).isEqualTo(0);

Expand Down Expand Up @@ -227,7 +245,7 @@ public void newChannelWithConnection_entersIdleOnSecondConnectionChange_api24()
TestChannel delegateChannel = new TestChannel();
ManagedChannel 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
// registered, rather than indicating a changed network, so we do not enter idle.
Expand All @@ -248,15 +266,17 @@ public void shutdownNowUnregistersBroadcastReceiver_api23() {
TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext());
delegateChannel, ApplicationProvider.getApplicationContext());

shadowOf(connectivityManager).setActiveNetworkInfo(null);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
androidChannel.shutdownNow();
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
RuntimeEnvironment.application.sendBroadcast(
new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
ApplicationProvider
.getApplicationContext()
.sendBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));

assertThat(delegateChannel.resetCount).isEqualTo(0);
}
Expand All @@ -268,7 +288,7 @@ public void shutdownNowUnregistersNetworkCallback_api24() {
TestChannel delegateChannel = new TestChannel();
ManagedChannel androidChannel =
new AndroidChannelBuilder.AndroidChannel(
delegateChannel, RuntimeEnvironment.application.getApplicationContext());
delegateChannel, ApplicationProvider.getApplicationContext());

androidChannel.shutdownNow();
shadowOf(connectivityManager).setActiveNetworkInfo(WIFI_CONNECTED);
Expand Down Expand Up @@ -318,6 +338,7 @@ private void notifyDefaultNetworkCallbacksOnLost(Network network) {
}

@Implementation(minSdk = N)
@Override
protected void registerDefaultNetworkCallback(
ConnectivityManager.NetworkCallback networkCallback) {
defaultNetworkCallbacks.add(networkCallback);
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Expand Up @@ -157,6 +157,7 @@ subprojects {
mockito: 'org.mockito:mockito-core:2.28.2',
truth: 'com.google.truth:truth:1.0.1',
guava_testlib: "com.google.guava:guava-testlib:${guavaVersion}",
androidx_test: "androidx.test:core:1.2.0",
robolectric: "org.robolectric:robolectric:4.3.1",

// Benchmark dependencies
Expand Down
1 change: 0 additions & 1 deletion buildscripts/kokoro/linux_artifacts.sh
Expand Up @@ -16,7 +16,6 @@ echo y | ${ANDROID_HOME}/tools/bin/sdkmanager "build-tools;28.0.3"
LOCAL_MVN_TEMP=$(mktemp -d)
pushd "$GRPC_JAVA_DIR/android"
../gradlew publish \
--include-build "$GRPC_JAVA_DIR" \
-Dorg.gradle.parallel=false \
-PskipCodegen=true \
-PrepositoryDir="$LOCAL_MVN_TEMP"
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Expand Up @@ -86,4 +86,6 @@ if (settings.hasProperty('skipAndroid') && skipAndroid.toBoolean()) {
println '*** Android SDK is required. To avoid building Android projects, set -PskipAndroid=true'
include ":grpc-cronet"
project(':grpc-cronet').projectDir = "$rootDir/cronet" as File
include ":grpc-android"
project(':grpc-android').projectDir = "$rootDir/android" as File
}

0 comments on commit 5ba663b

Please sign in to comment.