Reputation: 93
I am trying to access a custom GRPC server (Anki Vector robot) with TLS from my Android app.
I have the proto files in my Android Studio project and all required dependencies are available. Proto files generate the java classes and in my activity I build a channel with OkHttpChannelBuilder. Then I create a client stub (tried with async and blocking stubs)
After that I create a request message and send it with the stub.
The code compiles fine and the app runs on my phone. However, when the request is sent, I get an error stating that the stream is not started.
I don't see any method to start the stream in all the examples that I could find.
what may be the problem preventing the stream to start ?
error message I get :
2019-02-10 01:08:59.303 14691-30895/com.test.anki.grpc D/vectorCTRL: Failed... :
java.lang.IllegalStateException: Not started
at com.google.common.base.Preconditions.checkState(Preconditions.java:510)
at io.grpc.internal.ClientCallImpl.request(ClientCallImpl.java:367)
at io.grpc.PartialForwardingClientCall.request(PartialForwardingClientCall.java:34)
at io.grpc.ForwardingClientCall.request(ForwardingClientCall.java:22)
at io.grpc.ForwardingClientCall$SimpleForwardingClientCall.request(ForwardingClientCall.java:44)
at io.grpc.PartialForwardingClientCall.request(PartialForwardingClientCall.java:34)
at io.grpc.ForwardingClientCall.request(ForwardingClientCall.java:22)
at io.grpc.ForwardingClientCall$SimpleForwardingClientCall.request(ForwardingClientCall.java:44)
at io.grpc.PartialForwardingClientCall.request(PartialForwardingClientCall.java:34)
at io.grpc.ForwardingClientCall.request(ForwardingClientCall.java:22)
at io.grpc.stub.ClientCalls.startCall(ClientCalls.java:314)
at io.grpc.stub.ClientCalls.asyncUnaryRequestCall(ClientCalls.java:280)
at io.grpc.stub.ClientCalls.futureUnaryCall(ClientCalls.java:189)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:127)
at Anki.Vector.external_interface.ExternalInterfaceGrpc$ExternalInterfaceBlockingStub.sayText(ExternalInterfaceGrpc.java:3554)
at com.test.anki.grpc.MainActivity.testapi(MainActivity.java:1106)
at com.test.anki.grpc.MainActivity$GrpcTask.doInBackground(MainActivity.java:1003)
at com.test.anki.grpc.MainActivity$GrpcTask.doInBackground(MainActivity.java:996)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
my code is :
ClientInterceptor clientInterceptor = new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor, CallOptions callOptions, Channel channel) {
// Might need to try to inject the token using that?
return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(channel.newCall(methodDescriptor, callOptions)) {
@Override
protected void checkedStart(Listener listener, Metadata metadata) throws Exception {
Metadata.Key<String> key = Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER);
metadata.put(key, token);
}
};
}
};
SSLContext sslContext=null ;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext .init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(sslContext );
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override public boolean verify(String hostname, SSLSession session) {
return true;
}
});
Channel channel=null;
try {
//ManagedChannel channel = OkHttpChannelBuilder.forAddress(ipaddr, Integer.valueOf(port))
channel = OkHttpChannelBuilder.forAddress(ipaddr, Integer.valueOf(port))
//.overrideAuthority("Vector")
.sslSocketFactory(sslSocketFactory)
.intercept(clientInterceptor)
.build();
//ExternalInterfaceGrpc.ExternalInterfaceStub externalInterfaceStub = ExternalInterfaceGrpc.newStub(channel);
ExternalInterfaceGrpc.ExternalInterfaceBlockingStub externalInterfaceBlockingStub = ExternalInterfaceGrpc.newBlockingStub(channel);
Messages.SayTextRequest sayTextRequest = Messages.SayTextRequest
.newBuilder()
.setText("Yolo")
.build();
Messages.SayTextResponse res = externalInterfaceBlockingStub.sayText(sayTextRequest);
Log.d(TAG, res.getStatus().toString());
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
Log.d(TAG,String.format("Failed... : %n%s", sw));
} finally {
Log.d(TAG,"finally");
/*
try {
if(channel!=null) {((ManagedChannel) channel).shutdown().awaitTermination(1, TimeUnit.SECONDS);}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
*/
}
Upvotes: 1
Views: 1452
Reputation: 26394
The ClientCall
needs to have start()
called. start()
doesn't need to be called if using the stubs, as the stubs themselves will call start()
. But interceptors are exposed to start()
.
The problem is with your clientInterceptor
:
protected void checkedStart(Listener listener, Metadata metadata) throws Exception {
Metadata.Key<String> key = Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER);
metadata.put(key, token);
// FIXME: Missing call to delegate().start(listener, metadata);
}
The stub called start()
which eventually called your interceptor's checkedStart()
, but then the interceptor didn't call start on the real ClientCall.
Note that you have no need for using CheckedForwardingClientCall
since your checkedStart()
is not throwing any exceptions. ForwardingClientCall
is the more common class to use. (Override start()
instead of checkedStart()
).
Upvotes: 2