grpc server on Android - android

I am trying to build a platform agnostic communication channel between a provider and consumer processes. Found grpc + protobuf to be a good option.
Is there an example or implementation of GRPC server (Java/C++) running on Android?
I am following grpc java server example to implement the server i
private class GrpcServerTask extends AsyncTask<Void, Void, String>{
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
int port = 50051;
Server server;
try {
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
#Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
I keep getting the error
io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional server found. Try adding a dependency on the grpc-netty artifact
on executing new GrpcServerTask().execute();
Thanks

Netty server on Android isn't really supported. Android's garbage collector and NIO support are both too poor for good Netty performance. Also some things are unlikely to work, like TLS. If it is just for testing on the newest Android release it may mostly work, but no guarantees that it works now or continues to work in the future.
With that in mind, make sure that you have a dependency on grpc-netty and try without ProGuard as a test. ProGuard's renaming and stripping both can cause trouble; you would need -keepnames io.grpc.ServerProvider and -keep io.grpc.netty.NettyServerProvider in your ProGuard rules, like was done for client-side.
C++ in another option. Client-side has been used on Android already, and I would expect server-side to function if you get client-side working. But I'm also not as aware of the C++ implementation.

Related

Bidirectional-streaming in Android causing OOMs

I've set up a bidirectional stream construct in an Android app, where I am currently using the mechanism to send chunks of large files. The problem I am having is that my app will receive a request message for a file, then I'll respond with potentially hundreds of MBs worth of response GRPC messages, frequently causing an OOM. Pseudo code:
public class Myclass implements StreamObserver<CameraRequest>, Closeable {
...
public void onNext(Request req) {
for (Chunk chunk : getChunks(req))
this.requestObserver.onNext(builder.setChunk(chunk).build());
}
...
}
Is there some good way to rate limit the number of outstanding calls to onNext based on what has actually been put on the wire (and corresponding memory made freeable)? IE only allowing 10 calls to onNext to be made, then subsequent ones block until the data for the preceding calls has successfully been sent by the underlying protocol stack? I could implement a full e2e acknowledgement window in my wire protocol TCP style, but was hoping there was an easier/built in technique others were using.
Thanks!
Cast requestObserver to ClientCallStreamObserver. You can then call clientCallStreamObserver.isReady() to check if you should stop sending.
You will then need notifications for when the RPC is ready for more messages, to resume sending. For that, implement ClientResponseObserver and call clientCallStreamObserver.setOnReadyHandler(Runnable) within beforeStart().
Putting that all together, gets you something like:
public class MyClass implements
ClientResponseObserver<CameraRequest,CameraResponse> {
private ClientCallStreamObserver<CameraRequest> requestObserver;
private Iterable<Chunk> chunks;
public void beforeStart(ClientCallStreamObserver<CameraRequest> requestObserver) {
this.requestObserver = requestObserver;
requestObserver.setOnReadyHandler(MyClass::drain);
}
public void onNext(CameraRequest req) {
// I don't know if this assert valid for your protocol
assert chunks == null || !chunks.hasNext();
chunks = getChunks(req);
drain();
}
public void drain() {
while (requestObserver.isReady() && chunks.hasNext()) {
Chunk chunk = chunks.next();
requestObserver.onNext(builder.setChunk(chunk).build());
}
}
...
}
You can check out the flow control example here.

Fiddler capturing emulator's browser packets but not my app's

I've taken every step described here in Fiddler site for capturing my application (running in emulator) network packets. The strange thing is that I can decode http/https sent from browser but not https packets from my app. It's more interesting that requests get successful responses! Any idea what might be the problem?
I'm completely stocked and have no idea what should I have done which didn't.
First topic, that I've found on Xamarin forum was Why can't Fiddler detect traffic from Xamarin apps?. The answer is to set DefaultWebProxy:
public override void OnCreate()
{
// get IP from fiddler's internet icon at the top right, or via ipconfig for VirtualBox used by Genymotion
WebRequest.DefaultWebProxy = new WebProxy("192.168.56.1", 8888);
base.OnCreate();
...
}
I put it in MainActivity, but it didn't solve my problem.
Which helped me is Debugging HttpClient Calls with fiddler in PCL:
You will need to change your code to use a HttpClientHandler and a proxy
HttpClientHandler handler = new HttpClientHandler ()
{
Proxy = new WebProxy (new Uri("http://[Computer IP]:[Fiddler port number]")),
UseProxy = true
};
using (var client = new HttpClient(handler))
{
// Make your call in here
}
Looks simple enough only PCLs dont include the Web proxy class in its bundled System.Net dll for whatever reason so you will need to write your own by extending the System.Net.IWebProxy interface
like so
public class WebProxy : System.Net.IWebProxy
{
public System.Net.ICredentials Credentials
{
get;
set;
}
private readonly Uri _proxyUri;
public WebProxy(Uri proxyUri)
{
_proxyUri = proxyUri;
}
public Uri GetProxy(Uri destination)
{
return _proxyUri;
}
public bool IsBypassed(Uri host)
{
return false;
}
}
After all this stuff, I was able to capture requests from my Xamarin.Forms app on Android Emulator.

Fails to map api response to pojo when enabling multidex

I'm writing an Android application with lots of dependencies and I needed to enable multidex because it exceeds the limit (65536k methods). I followed this guide and able to compile and run the application on my test device. The problem is I'm getting a nullpointerexception in Robospice RequestListener
for every api call that I make. I'm sure that the api is responding. It seems that the app fails to map the response to my pojo class.
Note: It's running fine before I enabled the multidex.
here is the request listener
private class MyRequestListener implements RequestListener<PojoClass> {
#Override
public void onRequestFailure(SpiceException e) {
}
#Override
public void onRequestSuccess(PojoClass pojoClass) {
// pojoClass <---- this is null
}
}
here are my dependencies for rest and mapping
'org.springframework.android:spring-android-rest-template:2.0.0.M1'
'com.octo.android.robospice:robospice-spring-android:1.4.14'
'org.codehaus.jackson:jackson-core-asl:1.9.13'
'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
Any suggestions

Setting Connection TimeOut in RoboSpice request android

I am using RoboSpice for Rest Api calls in android and i want to add connection timeout for 30 secs in calls how i will do ?
here is my code
public class AddBrandsService extends
SpringAndroidSpiceRequest<AddBrands.Response> {
public final AddBrands.Response loadDataFromNetwork(){
return getRestTemplate().postForObject(url,
request, AddBrands.Response.class);
}
}
this service is called here
private SpiceManager contentManager = new SpiceManager(
JacksonSpringAndroidSpiceService.class);
contentManager.execute(service, lastRequestCacheKey,
DurationInMillis.ONE_SECOND, new AddBrandsListner());
thanks in advance...
Here is the code. Basically, you have to take care of the version of android as spring android switch between two different implementations to avoid a known bug in network stack. Unfortunately both implementations don't share a common interface whith respect to timeouts.
private void manageTimeOuts(RestTemplate restTemplate) {
// set timeout for requests
ClientHttpRequestFactory factory = restTemplate.getRequestFactory();
if (factory instanceof HttpComponentsClientHttpRequestFactory) {
HttpComponentsClientHttpRequestFactory advancedFactory = (HttpComponentsClientHttpRequestFactory) factory;
advancedFactory.setConnectTimeout(WEBSERVICES_TIMEOUT);
advancedFactory.setReadTimeout(WEBSERVICES_TIMEOUT);
} else if (factory instanceof SimpleClientHttpRequestFactory) {
SimpleClientHttpRequestFactory advancedFactory = (SimpleClientHttpRequestFactory) factory;
advancedFactory.setConnectTimeout(WEBSERVICES_TIMEOUT);
advancedFactory.setReadTimeout(WEBSERVICES_TIMEOUT);
}
}

Updating the proxy entity using android fails with "A request is already in progress"

What's a good pattern to use, when I want to
create the proxy entity -- works
set some properties -- works
send to GAE -- works
if the "save" button is clicked again
proxy = requestContext.edit(proxy_returned_from_server_above); // fails with "A request is already in progress"
I have spent a few days, trying many options, without any luck.
Is there a sample android app or suggestions? something that used GAE, android and GWT requestfactory?
using a "new" requestContext as some suggest does not work.
I faced the same problem. So i figured it out that you have to build the MyRequestFactory every time before call its method.
//Build this every time
MyRequestFactory requestFactory = Util.getRequestFactory(mContext,
MyRequestFactory.class);
//
final CustomRequest request = requestFactory
.customRequest();
request.queryImages().fire(
new Receiver<List<ImageProxy>>() {
#Override
public void onFailure(ServerFailure error) {
String erro = "Failure: "
+ error.getMessage();
Log.e("fail",
erro);
}
#Override
public void onSuccess(List<ImageProxy> result) {
db.importImage(result);
}
});

Categories

Resources