mirror of https://github.com/grpc/grpc.git
parent
5a03bdb622
commit
f9fb3ebf1f
25 changed files with 5429 additions and 1 deletions
@ -0,0 +1,9 @@ |
||||
*.iml |
||||
.gradle |
||||
/local.properties |
||||
/.idea/workspace.xml |
||||
/.idea/libraries |
||||
.DS_Store |
||||
/build |
||||
/captures |
||||
.externalNativeBuild |
@ -0,0 +1,37 @@ |
||||
gRPC on Android |
||||
============== |
||||
|
||||
Note: Building the protobuf dependency for Android requires |
||||
https://github.com/google/protobuf/pull/3878. This fix will be in the next |
||||
protobuf release, but until then must be manually patched in to |
||||
`third_party/protobuf` to build gRPC for Android. |
||||
|
||||
PREREQUISITES |
||||
------------- |
||||
|
||||
- Android SDK |
||||
- Android NDK |
||||
- `protoc` and `grpc_cpp_plugin` binaries on the host system |
||||
|
||||
INSTALL |
||||
------- |
||||
|
||||
The example application can be built via Android Studio or on the command line |
||||
using `gradle`: |
||||
|
||||
```sh |
||||
$ ./gradlew installDebug |
||||
``` |
||||
|
||||
INSTRUMENTATION TESTS |
||||
--------------------- |
||||
|
||||
The instrumentation tests can be run via the following `gradle` command. This |
||||
requires an emulator already running on your computer. |
||||
|
||||
``` |
||||
$ ./gradlew connectedAndroidTest \ |
||||
-Pandroid.testInstrumentationRunnerArguments.server_host=grpc-test.sandbox.googleapis.com \ |
||||
-Pandroid.testInstrumentationRunnerArguments.server_port=443 \ |
||||
-Pandroid.testInstrumentationRunnerArguments.use_tls=true |
||||
``` |
@ -0,0 +1 @@ |
||||
/build |
@ -0,0 +1,119 @@ |
||||
cmake_minimum_required(VERSION 3.4.1) |
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") |
||||
|
||||
set(PROTOBUF_PROTOC_EXECUTABLE "/usr/local/bin/protoc" CACHE STRING "Protoc binary on host") |
||||
set(gRPC_CPP_PLUGIN_EXECUTABLE "/usr/local/bin/grpc_cpp_plugin" CACHE STRING "gRPC CPP plugin binary on host") |
||||
|
||||
set(GRPC_SRC_DIR ../../../../../) |
||||
|
||||
set(GRPC_BUILD_DIR ../grpc/outputs/${ANDROID_ABI}) |
||||
file(MAKE_DIRECTORY ${GRPC_BUILD_DIR}) |
||||
|
||||
add_subdirectory(${GRPC_SRC_DIR} ${GRPC_BUILD_DIR}) |
||||
|
||||
#include_directories(${GRPC_SRC_DIR}/include) |
||||
include_directories(${GRPC_SRC_DIR}) |
||||
|
||||
set(GRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens) |
||||
file(MAKE_DIRECTORY ${GRPC_PROTO_GENS_DIR}) |
||||
include_directories(${GRPC_PROTO_GENS_DIR}) |
||||
|
||||
function(android_protobuf_grpc_generate_cpp SRC_FILES HDR_FILES INCLUDE_ROOT) |
||||
if(NOT ARGN) |
||||
message(SEND_ERROR "Error: android_protobuf_grpc_generate_cpp() called without any proto files") |
||||
return() |
||||
endif() |
||||
|
||||
set(${SRC_FILES}) |
||||
set(${HDR_FILES}) |
||||
set(PROTOBUF_INCLUDE_PATH -I ${INCLUDE_ROOT}) |
||||
foreach(FIL ${ARGN}) |
||||
get_filename_component(ABS_FIL ${FIL} ABSOLUTE) |
||||
get_filename_component(FIL_WE ${FIL} NAME_WE) |
||||
file(RELATIVE_PATH REL_FIL ${CMAKE_CURRENT_SOURCE_DIR}/${INCLUDE_ROOT} ${ABS_FIL}) |
||||
get_filename_component(REL_DIR ${REL_FIL} DIRECTORY) |
||||
set(RELFIL_WE "${REL_DIR}/${FIL_WE}") |
||||
|
||||
list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc") |
||||
list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h") |
||||
list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc") |
||||
list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h") |
||||
|
||||
add_custom_command( |
||||
OUTPUT "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" |
||||
"${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" |
||||
"${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" |
||||
"${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" |
||||
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} |
||||
ARGS --grpc_out=${GRPC_PROTO_GENS_DIR} |
||||
--cpp_out=${GRPC_PROTO_GENS_DIR} |
||||
--plugin=protoc-gen-grpc=${gRPC_CPP_PLUGIN_EXECUTABLE} |
||||
${PROTOBUF_INCLUDE_PATH} |
||||
${REL_FIL} |
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
||||
DEPENDS ${PROTOBUF_PROTOC_EXECUTABLE} ${gRPC_CPP_PLUGIN_EXECUTABLE} ${ABS_FIL} ) |
||||
endforeach() |
||||
|
||||
set_source_files_properties(${${SRC_FILES}} ${${HDR_FILES}} PROPERTIES GENERATED TRUE) |
||||
set(${SRC_FILES} ${${SRC_FILES}} PARENT_SCOPE) |
||||
set(${HDR_FILES} ${${HDR_FILES}} PARENT_SCOPE) |
||||
endfunction() |
||||
|
||||
set(PROTO_BASE_DIR ${GRPC_SRC_DIR}/examples/protos) |
||||
|
||||
android_protobuf_grpc_generate_cpp( |
||||
MESSAGES_PROTO_SRCS MESSAGES_PROTO_HDRS |
||||
${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/messages.proto) |
||||
|
||||
add_library(messages_proto_lib |
||||
SHARED ${MESSAGES_PROTO_SRCS} ${MESSAGES_PROTO_HDRS}) |
||||
|
||||
target_link_libraries(messages_proto_lib |
||||
libprotobuf |
||||
grpc++ |
||||
android |
||||
log) |
||||
|
||||
android_protobuf_grpc_generate_cpp( |
||||
EMPTY_PROTO_SRCS EMPTY_PROTO_HDRS |
||||
${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/empty.proto) |
||||
|
||||
add_library(empty_proto_lib |
||||
SHARED ${EMPTY_PROTO_SRCS} ${EMPTY_PROTO_HDRS}) |
||||
|
||||
target_link_libraries(empty_proto_lib |
||||
libprotobuf |
||||
grpc++ |
||||
android |
||||
log) |
||||
|
||||
android_protobuf_grpc_generate_cpp( |
||||
TEST_PROTO_SRCS TEST_PROTO_HDRS ${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/test.proto) |
||||
|
||||
add_library(test_proto_lib |
||||
SHARED ${TEST_PROTO_SRCS} ${TEST_PROTO_HDRS}) |
||||
|
||||
target_link_libraries(test_proto_lib |
||||
libprotobuf |
||||
grpc++ |
||||
empty_proto_lib |
||||
messages_proto_lib |
||||
android |
||||
log) |
||||
|
||||
find_library(log-lib |
||||
log) |
||||
|
||||
add_library(grpc-interop |
||||
SHARED |
||||
src/main/cpp/grpc-interop.cc |
||||
${GRPC_SRC_DIR}/test/cpp/interop/interop_client.h |
||||
${GRPC_SRC_DIR}/test/cpp/interop/interop_client.cc) |
||||
|
||||
target_link_libraries(grpc-interop |
||||
messages_proto_lib |
||||
empty_proto_lib |
||||
test_proto_lib |
||||
android |
||||
${log-lib}) |
@ -0,0 +1,56 @@ |
||||
apply plugin: 'com.android.application' |
||||
|
||||
android { |
||||
compileSdkVersion 26 |
||||
defaultConfig { |
||||
applicationId "io.grpc.android.interop.cpp" |
||||
minSdkVersion 14 |
||||
targetSdkVersion 26 |
||||
versionCode 1 |
||||
versionName "1.0" |
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" |
||||
externalNativeBuild { |
||||
cmake { |
||||
// The paths to the protoc and grpc_cpp_plugin binaries on the host system (codegen |
||||
// is not cross-compiled to Android) |
||||
def protoc = project.hasProperty('protoc') ? |
||||
project.property('protoc') : '/usr/local/bin/protoc' |
||||
def grpc_cpp_plugin = project.hasProperty('grpc_cpp_plugin') ? |
||||
project.property('grpc_cpp_plugin') : '/usr/local/bin/grpc_cpp_plugin' |
||||
|
||||
cppFlags "-std=c++14 -frtti -fexceptions" |
||||
arguments '-DANDROID_STL=c++_shared' |
||||
arguments '-DRUN_HAVE_POSIX_REGEX=0' |
||||
arguments '-DRUN_HAVE_STD_REGEX=0' |
||||
arguments '-DRUN_HAVE_STEADY_CLOCK=0' |
||||
arguments '-Dprotobuf_BUILD_PROTOC_BINARIES=off' |
||||
arguments '-DgRPC_BUILD_CODEGEN=off' |
||||
arguments '-DPROTOBUF_PROTOC_EXECUTABLE=' + protoc |
||||
arguments '-DgRPC_CPP_PLUGIN_EXECUTABLE=' + grpc_cpp_plugin |
||||
} |
||||
} |
||||
ndk.abiFilters 'x86' |
||||
} |
||||
buildTypes { |
||||
debug { |
||||
minifyEnabled false |
||||
} |
||||
release { |
||||
minifyEnabled true |
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
||||
} |
||||
} |
||||
externalNativeBuild { |
||||
cmake { |
||||
path "CMakeLists.txt" |
||||
} |
||||
} |
||||
} |
||||
|
||||
dependencies { |
||||
implementation fileTree(dir: 'libs', include: ['*.jar']) |
||||
implementation 'com.android.support:appcompat-v7:26.1.0' |
||||
testImplementation 'junit:junit:4.12' |
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1' |
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' |
||||
} |
@ -0,0 +1,21 @@ |
||||
# Add project specific ProGuard rules here. |
||||
# You can control the set of applied configuration files using the |
||||
# proguardFiles setting in build.gradle. |
||||
# |
||||
# For more details, see |
||||
# http://developer.android.com/guide/developing/tools/proguard.html |
||||
|
||||
# If your project uses WebView with JS, uncomment the following |
||||
# and specify the fully qualified class name to the JavaScript interface |
||||
# class: |
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
||||
# public *; |
||||
#} |
||||
|
||||
# Uncomment this to preserve the line number information for |
||||
# debugging stack traces. |
||||
#-keepattributes SourceFile,LineNumberTable |
||||
|
||||
# If you keep the line number information, uncomment this to |
||||
# hide the original source file name. |
||||
#-renamesourcefileattribute SourceFile |
@ -0,0 +1,92 @@ |
||||
/* |
||||
* Copyright 2018, gRPC Authors All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.grpc.interop.cpp; |
||||
|
||||
import static junit.framework.Assert.assertTrue; |
||||
|
||||
import android.content.Context; |
||||
import android.support.test.InstrumentationRegistry; |
||||
import android.support.test.runner.AndroidJUnit4; |
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
|
||||
@RunWith(AndroidJUnit4.class) |
||||
public class InteropTest { |
||||
private String host; |
||||
private int port; |
||||
private boolean useTls; |
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
host = InstrumentationRegistry.getArguments().getString("server_host", "10.0.2.2"); |
||||
port = |
||||
Integer.parseInt(InstrumentationRegistry.getArguments().getString("server_port", "8080")); |
||||
useTls = |
||||
Boolean.parseBoolean(InstrumentationRegistry.getArguments().getString("use_tls", "false")); |
||||
|
||||
if (useTls) { |
||||
Context ctx = InstrumentationRegistry.getTargetContext(); |
||||
String sslRootsFile = "roots.pem"; |
||||
InputStream in = ctx.getAssets().open(sslRootsFile); |
||||
File outFile = new File(ctx.getExternalFilesDir(null), sslRootsFile); |
||||
OutputStream out = new FileOutputStream(outFile); |
||||
byte[] buffer = new byte[1024]; |
||||
int bytesRead; |
||||
while ((bytesRead = in.read(buffer)) != -1) { |
||||
out.write(buffer, 0, bytesRead); |
||||
} |
||||
in.close(); |
||||
out.close(); |
||||
InteropActivity.configureSslRoots(outFile.getCanonicalPath()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void emptyUnary() { |
||||
assertTrue(InteropActivity.doEmpty(host, port, useTls)); |
||||
} |
||||
|
||||
@Test |
||||
public void largeUnary() { |
||||
assertTrue(InteropActivity.doLargeUnary(host, port, useTls)); |
||||
} |
||||
|
||||
@Test |
||||
public void emptyStream() { |
||||
assertTrue(InteropActivity.doEmptyStream(host, port, useTls)); |
||||
} |
||||
|
||||
@Test |
||||
public void requestStreaming() { |
||||
assertTrue(InteropActivity.doRequestStreaming(host, port, useTls)); |
||||
} |
||||
|
||||
@Test |
||||
public void responseStreaming() { |
||||
assertTrue(InteropActivity.doResponseStreaming(host, port, useTls)); |
||||
} |
||||
|
||||
@Test |
||||
public void pingPong() { |
||||
assertTrue(InteropActivity.doPingPong(host, port, useTls)); |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="io.grpc.interop.cpp" > |
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" /> |
||||
|
||||
<application |
||||
android:allowBackup="false" |
||||
android:icon="@mipmap/ic_launcher" |
||||
android:label="@string/app_name" |
||||
android:theme="@style/Base.V7.Theme.AppCompat.Light" > |
||||
<activity |
||||
android:name=".InteropActivity" |
||||
android:label="@string/app_name" > |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
</activity> |
||||
</application> |
||||
|
||||
</manifest> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,124 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc++/grpc++.h> |
||||
#include <jni.h> |
||||
#include <src/core/lib/gpr/env.h> |
||||
|
||||
#include "test/cpp/interop/interop_client.h" |
||||
|
||||
extern "C" JNIEXPORT void JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_configureSslRoots(JNIEnv* env, |
||||
jobject obj_this, |
||||
jstring path_raw) { |
||||
const char* path = env->GetStringUTFChars(path_raw, (jboolean*)0); |
||||
|
||||
gpr_setenv("GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", path); |
||||
} |
||||
|
||||
std::shared_ptr<grpc::testing::InteropClient> GetClient(const char* host, |
||||
int port, |
||||
bool use_tls) { |
||||
const int host_port_buf_size = 1024; |
||||
char host_port[host_port_buf_size]; |
||||
snprintf(host_port, host_port_buf_size, "%s:%d", host, port); |
||||
|
||||
std::shared_ptr<grpc::ChannelCredentials> credentials; |
||||
if (use_tls) { |
||||
credentials = grpc::SslCredentials(grpc::SslCredentialsOptions()); |
||||
} else { |
||||
credentials = grpc::InsecureChannelCredentials(); |
||||
} |
||||
|
||||
return std::shared_ptr<grpc::testing::InteropClient>( |
||||
new grpc::testing::InteropClient( |
||||
grpc::CreateChannel(host_port, credentials), true, false)); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doEmpty(JNIEnv* env, jobject obj_this, |
||||
jstring host_raw, |
||||
jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoEmpty(); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doLargeUnary(JNIEnv* env, |
||||
jobject obj_this, |
||||
jstring host_raw, |
||||
jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoLargeUnary(); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doEmptyStream(JNIEnv* env, |
||||
jobject obj_this, |
||||
jstring host_raw, |
||||
jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoEmptyStream(); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doRequestStreaming( |
||||
JNIEnv* env, jobject obj_this, jstring host_raw, jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoRequestStreaming(); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doResponseStreaming( |
||||
JNIEnv* env, jobject obj_this, jstring host_raw, jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoResponseStreaming(); |
||||
} |
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL |
||||
Java_io_grpc_interop_cpp_InteropActivity_doPingPong(JNIEnv* env, |
||||
jobject obj_this, |
||||
jstring host_raw, |
||||
jint port_raw, |
||||
jboolean use_tls_raw) { |
||||
const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0); |
||||
int port = static_cast<int>(port_raw); |
||||
bool use_tls = static_cast<bool>(use_tls_raw); |
||||
|
||||
return GetClient(host, port, use_tls)->DoPingPong(); |
||||
} |
@ -0,0 +1,122 @@ |
||||
/* |
||||
* Copyright 2018, gRPC Authors All rights reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.grpc.interop.cpp; |
||||
|
||||
import android.content.Context; |
||||
import android.os.AsyncTask; |
||||
import android.os.Bundle; |
||||
import android.support.v7.app.AppCompatActivity; |
||||
import android.text.TextUtils; |
||||
import android.text.method.ScrollingMovementMethod; |
||||
import android.view.View; |
||||
import android.view.inputmethod.InputMethodManager; |
||||
import android.widget.Button; |
||||
import android.widget.EditText; |
||||
import android.widget.TextView; |
||||
import java.lang.ref.WeakReference; |
||||
|
||||
public class InteropActivity extends AppCompatActivity { |
||||
|
||||
static { |
||||
System.loadLibrary("grpc-interop"); |
||||
} |
||||
|
||||
private Button sendButton; |
||||
private EditText hostEdit; |
||||
private EditText portEdit; |
||||
private TextView resultText; |
||||
private GrpcTask grpcTask; |
||||
|
||||
@Override |
||||
protected void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
setContentView(R.layout.activity_interop); |
||||
sendButton = (Button) findViewById(R.id.ping_pong_button); |
||||
hostEdit = (EditText) findViewById(R.id.host_edit_text); |
||||
portEdit = (EditText) findViewById(R.id.port_edit_text); |
||||
resultText = (TextView) findViewById(R.id.grpc_result_text); |
||||
resultText.setMovementMethod(new ScrollingMovementMethod()); |
||||
} |
||||
|
||||
@Override |
||||
protected void onPause() { |
||||
super.onPause(); |
||||
if (grpcTask != null) { |
||||
grpcTask.cancel(true); |
||||
grpcTask = null; |
||||
} |
||||
} |
||||
|
||||
public void doPingPong(View view) { |
||||
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)) |
||||
.hideSoftInputFromWindow(hostEdit.getWindowToken(), 0); |
||||
sendButton.setEnabled(false); |
||||
resultText.setText(""); |
||||
grpcTask = new GrpcTask(this); |
||||
grpcTask.executeOnExecutor( |
||||
AsyncTask.THREAD_POOL_EXECUTOR, |
||||
hostEdit.getText().toString(), |
||||
portEdit.getText().toString()); |
||||
} |
||||
|
||||
private static class GrpcTask extends AsyncTask<String, Void, String> { |
||||
private final WeakReference<InteropActivity> activityReference; |
||||
|
||||
private GrpcTask(InteropActivity activity) { |
||||
this.activityReference = new WeakReference<InteropActivity>(activity); |
||||
} |
||||
|
||||
@Override |
||||
protected String doInBackground(String... params) { |
||||
String host = params[0]; |
||||
String portStr = params[1]; |
||||
int port = TextUtils.isEmpty(portStr) ? 50051 : Integer.valueOf(portStr); |
||||
// TODO(ericgribkoff) Support other test cases in the app UI
|
||||
if (doPingPong(host, port, false)) { |
||||
return "Success"; |
||||
} else { |
||||
return "Failure"; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void onPostExecute(String result) { |
||||
InteropActivity activity = activityReference.get(); |
||||
if (activity == null || isCancelled()) { |
||||
return; |
||||
} |
||||
TextView resultText = (TextView) activity.findViewById(R.id.grpc_result_text); |
||||
Button sendButton = (Button) activity.findViewById(R.id.ping_pong_button); |
||||
resultText.setText(result); |
||||
sendButton.setEnabled(true); |
||||
} |
||||
} |
||||
|
||||
public static native void configureSslRoots(String path); |
||||
|
||||
public static native boolean doEmpty(String host, int port, boolean useTls); |
||||
|
||||
public static native boolean doLargeUnary(String host, int port, boolean useTls); |
||||
|
||||
public static native boolean doEmptyStream(String host, int port, boolean useTls); |
||||
|
||||
public static native boolean doRequestStreaming(String host, int port, boolean useTls); |
||||
|
||||
public static native boolean doResponseStreaming(String host, int port, boolean useTls); |
||||
|
||||
public static native boolean doPingPong(String host, int port, boolean useTls); |
||||
} |
@ -0,0 +1,48 @@ |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
tools:context=".InteropActivity" |
||||
android:orientation="vertical" > |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="horizontal"> |
||||
<EditText |
||||
android:id="@+id/host_edit_text" |
||||
android:layout_weight="2" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:hint="Enter Host" /> |
||||
<EditText |
||||
android:id="@+id/port_edit_text" |
||||
android:layout_weight="1" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:inputType="numberDecimal" |
||||
android:hint="Enter Port" /> |
||||
</LinearLayout> |
||||
|
||||
<Button |
||||
android:id="@+id/ping_pong_button" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:onClick="doPingPong" |
||||
android:text="Ping Pong" /> |
||||
|
||||
<TextView |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:paddingTop="12dp" |
||||
android:paddingBottom="12dp" |
||||
android:textSize="16sp" |
||||
android:text="Result:" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/grpc_result_text" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:scrollbars = "vertical" |
||||
android:textSize="16sp" /> |
||||
|
||||
</LinearLayout> |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 7.5 KiB |
@ -0,0 +1,3 @@ |
||||
<resources> |
||||
<string name="app_name">gRPC C++ Interop App</string> |
||||
</resources> |
@ -0,0 +1,24 @@ |
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
||||
|
||||
buildscript { |
||||
repositories { |
||||
google() |
||||
jcenter() |
||||
} |
||||
dependencies { |
||||
classpath 'com.android.tools.build:gradle:3.0.1' |
||||
// NOTE: Do not place your application dependencies here; they belong |
||||
// in the individual module build.gradle files |
||||
} |
||||
} |
||||
|
||||
allprojects { |
||||
repositories { |
||||
google() |
||||
jcenter() |
||||
} |
||||
} |
||||
|
||||
task clean(type: Delete) { |
||||
delete rootProject.buildDir |
||||
} |
@ -0,0 +1,17 @@ |
||||
# Project-wide Gradle settings. |
||||
|
||||
# IDE (e.g. Android Studio) users: |
||||
# Gradle settings configured through the IDE *will override* |
||||
# any settings specified in this file. |
||||
|
||||
# For more details on how to configure your build environment visit |
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html |
||||
|
||||
# Specifies the JVM arguments used for the daemon process. |
||||
# The setting is particularly useful for tweaking memory settings. |
||||
org.gradle.jvmargs=-Xmx1536m |
||||
|
||||
# When configured, Gradle will run in incubating parallel mode. |
||||
# This option should only be used with decoupled projects. More details, visit |
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
||||
# org.gradle.parallel=true |
Binary file not shown.
@ -0,0 +1,6 @@ |
||||
#Thu Jan 25 11:45:30 PST 2018 |
||||
distributionBase=GRADLE_USER_HOME |
||||
distributionPath=wrapper/dists |
||||
zipStoreBase=GRADLE_USER_HOME |
||||
zipStorePath=wrapper/dists |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip |
@ -0,0 +1,160 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
############################################################################## |
||||
## |
||||
## Gradle start up script for UN*X |
||||
## |
||||
############################################################################## |
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
DEFAULT_JVM_OPTS="" |
||||
|
||||
APP_NAME="Gradle" |
||||
APP_BASE_NAME=`basename "$0"` |
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value. |
||||
MAX_FD="maximum" |
||||
|
||||
warn ( ) { |
||||
echo "$*" |
||||
} |
||||
|
||||
die ( ) { |
||||
echo |
||||
echo "$*" |
||||
echo |
||||
exit 1 |
||||
} |
||||
|
||||
# OS specific support (must be 'true' or 'false'). |
||||
cygwin=false |
||||
msys=false |
||||
darwin=false |
||||
case "`uname`" in |
||||
CYGWIN* ) |
||||
cygwin=true |
||||
;; |
||||
Darwin* ) |
||||
darwin=true |
||||
;; |
||||
MINGW* ) |
||||
msys=true |
||||
;; |
||||
esac |
||||
|
||||
# Attempt to set APP_HOME |
||||
# Resolve links: $0 may be a link |
||||
PRG="$0" |
||||
# Need this for relative symlinks. |
||||
while [ -h "$PRG" ] ; do |
||||
ls=`ls -ld "$PRG"` |
||||
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
if expr "$link" : '/.*' > /dev/null; then |
||||
PRG="$link" |
||||
else |
||||
PRG=`dirname "$PRG"`"/$link" |
||||
fi |
||||
done |
||||
SAVED="`pwd`" |
||||
cd "`dirname \"$PRG\"`/" >/dev/null |
||||
APP_HOME="`pwd -P`" |
||||
cd "$SAVED" >/dev/null |
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
||||
|
||||
# Determine the Java command to use to start the JVM. |
||||
if [ -n "$JAVA_HOME" ] ; then |
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
# IBM's JDK on AIX uses strange locations for the executables |
||||
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
else |
||||
JAVACMD="$JAVA_HOME/bin/java" |
||||
fi |
||||
if [ ! -x "$JAVACMD" ] ; then |
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the |
||||
location of your Java installation." |
||||
fi |
||||
else |
||||
JAVACMD="java" |
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the |
||||
location of your Java installation." |
||||
fi |
||||
|
||||
# Increase the maximum file descriptors if we can. |
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then |
||||
MAX_FD_LIMIT=`ulimit -H -n` |
||||
if [ $? -eq 0 ] ; then |
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
||||
MAX_FD="$MAX_FD_LIMIT" |
||||
fi |
||||
ulimit -n $MAX_FD |
||||
if [ $? -ne 0 ] ; then |
||||
warn "Could not set maximum file descriptor limit: $MAX_FD" |
||||
fi |
||||
else |
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
||||
fi |
||||
fi |
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock |
||||
if $darwin; then |
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
||||
fi |
||||
|
||||
# For Cygwin, switch paths to Windows format before running java |
||||
if $cygwin ; then |
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
||||
JAVACMD=`cygpath --unix "$JAVACMD"` |
||||
|
||||
# We build the pattern for arguments to be converted via cygpath |
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
||||
SEP="" |
||||
for dir in $ROOTDIRSRAW ; do |
||||
ROOTDIRS="$ROOTDIRS$SEP$dir" |
||||
SEP="|" |
||||
done |
||||
OURCYGPATTERN="(^($ROOTDIRS))" |
||||
# Add a user-defined pattern to the cygpath arguments |
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
||||
fi |
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
||||
i=0 |
||||
for arg in "$@" ; do |
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
||||
else |
||||
eval `echo args$i`="\"$arg\"" |
||||
fi |
||||
i=$((i+1)) |
||||
done |
||||
case $i in |
||||
(0) set -- ;; |
||||
(1) set -- "$args0" ;; |
||||
(2) set -- "$args0" "$args1" ;; |
||||
(3) set -- "$args0" "$args1" "$args2" ;; |
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
||||
esac |
||||
fi |
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules |
||||
function splitJvmOpts() { |
||||
JVM_OPTS=("$@") |
||||
} |
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS |
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" |
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
@ -0,0 +1,90 @@ |
||||
@if "%DEBUG%" == "" @echo off |
||||
@rem ########################################################################## |
||||
@rem |
||||
@rem Gradle startup script for Windows |
||||
@rem |
||||
@rem ########################################################################## |
||||
|
||||
@rem Set local scope for the variables with windows NT shell |
||||
if "%OS%"=="Windows_NT" setlocal |
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
set DEFAULT_JVM_OPTS= |
||||
|
||||
set DIRNAME=%~dp0 |
||||
if "%DIRNAME%" == "" set DIRNAME=. |
||||
set APP_BASE_NAME=%~n0 |
||||
set APP_HOME=%DIRNAME% |
||||
|
||||
@rem Find java.exe |
||||
if defined JAVA_HOME goto findJavaFromJavaHome |
||||
|
||||
set JAVA_EXE=java.exe |
||||
%JAVA_EXE% -version >NUL 2>&1 |
||||
if "%ERRORLEVEL%" == "0" goto init |
||||
|
||||
echo. |
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
echo. |
||||
echo Please set the JAVA_HOME variable in your environment to match the |
||||
echo location of your Java installation. |
||||
|
||||
goto fail |
||||
|
||||
:findJavaFromJavaHome |
||||
set JAVA_HOME=%JAVA_HOME:"=% |
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
||||
|
||||
if exist "%JAVA_EXE%" goto init |
||||
|
||||
echo. |
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
||||
echo. |
||||
echo Please set the JAVA_HOME variable in your environment to match the |
||||
echo location of your Java installation. |
||||
|
||||
goto fail |
||||
|
||||
:init |
||||
@rem Get command-line arguments, handling Windowz variants |
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args |
||||
if "%@eval[2+2]" == "4" goto 4NT_args |
||||
|
||||
:win9xME_args |
||||
@rem Slurp the command line arguments. |
||||
set CMD_LINE_ARGS= |
||||
set _SKIP=2 |
||||
|
||||
:win9xME_args_slurp |
||||
if "x%~1" == "x" goto execute |
||||
|
||||
set CMD_LINE_ARGS=%* |
||||
goto execute |
||||
|
||||
:4NT_args |
||||
@rem Get arguments from the 4NT Shell from JP Software |
||||
set CMD_LINE_ARGS=%$ |
||||
|
||||
:execute |
||||
@rem Setup the command line |
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
||||
|
||||
@rem Execute Gradle |
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
||||
|
||||
:end |
||||
@rem End local scope for the variables with windows NT shell |
||||
if "%ERRORLEVEL%"=="0" goto mainEnd |
||||
|
||||
:fail |
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
||||
rem the _cmd.exe /c_ return code! |
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
||||
exit /b 1 |
||||
|
||||
:mainEnd |
||||
if "%OS%"=="Windows_NT" endlocal |
||||
|
||||
:omega |
@ -0,0 +1 @@ |
||||
include ':app' |
Loading…
Reference in new issue