Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android: add grpc-android into main build #6793

Merged
merged 3 commits into from Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
}