Check communication from Android to node.js server with protocol buffers

environment

Android side

Server side

things to do

Communicate with server using protobuf-gradle-plugin Check that serialization and deserialization can be done on Android and communication with the server

[Class generation procedure](http://qiita.com/natsuki_summer/items/987f230ec90d231a623c#%E3%82%AF%E3%83%A9%E3%82%B9%E7%94%9F%E6%88%90 % E6% 89% 8B% E9% A0% 86) etc. are the same as the previous article, so they are omitted.

Android and node alone should work without the above protoc command

reference

Almost as it is http://qiita.com/trairia/items/45488e9eee197d58ed7d official https://github.com/google/protobuf-gradle-plugin

.proto file

The content was all right, so it's the same as before

search_request.proto



syntax = "proto3";

package test;

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

Add the description for Protocol Buffers to build.gradle of the Android project you want to use

build.gradle



buildscript {
    repositories {
        //...
        mavenCentral()
    }
    dependencies {
        //...
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
    }
}

//...

app/build.gradle



apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'

android {
    //abridgement
}
//protobuf plugin settings
protobuf {
    //protoc settings
    protoc {
        artifact = "com.google.protobuf:protoc:3.0.0"
    }
    //Use javalite plugin
    plugins {
        lite {
            artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
        }
    }
    //Task related
    generateProtoTasks {
        all().each { task ->
            task.plugins {
                lite {}
            }
        }
    }
}

dependencies {
    //...
    compile 'com.google.protobuf:protobuf-lite:3.0.0'
    compile 'com.squareup.okhttp:okhttp:2.7.5'
}

Add .proto file to {project} / app / src / main / proto /

app/src/main
 ├proto
 │   └search_request.proto
 └java
    └com/example/testapp
        └MainActivity.java

Just do the above and the SearchRequestOuterClass.SearchRequest class will be automatically generated in the package and you should be able to access it from the java file of your project. When creating an object, it looks like the following

SearchRequestOuterClass.SearchRequest.newBuilder()
                .setQuery("xxxx")
                .setPageNumber(1)
                .setResultPerPage(1)
                .build();

Communication tested with OKHttp Set up a local server with node.js and send serialized data, and also send serialized data on the server side in response, and confirm mutual communication, serialization, and deserialization

Client side

The communication destination is http://127.0.0.1:3000/, but for example, if you set up a node server on your local PC and access it on the actual Android, you need to rewrite the part of "127.0.0.1" and connect it to the same wifi. Please make it an accessible IP obtained by ifconfig etc. on the Mac side with

MainActivity.java


public class MainActivity extends AppCompatActivity {
    private String TAG = getClass().getName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new AsyncTask<Void, Void, Void>(){
            @Override
            protected Void doInBackground(Void... params) {
                request();
                return null;
            }
        }.execute();

    }
    //Appropriate data generation
    public static SearchRequestOuterClass.SearchRequest getData(){
        return SearchRequestOuterClass.SearchRequest.newBuilder()
                .setQuery("huga")
                .setPageNumber(1)
                .setResultPerPage(1)
                .build();
    }

    private void request(){
        postBinary("http://127.0.0.1:3000/", new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                Log.d(TAG, "request --- onFailure:"+e);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                Log.d(TAG, "request --- onResponse:"+response);
                SearchRequestOuterClass.SearchRequest data = SearchRequestOuterClass.SearchRequest.parseFrom(response.body().bytes());
                Log.d(TAG, "response --- data.getQuery:"+data.getQuery());
            }
        });
    }

    private void postBinary(String url, final Callback callback){
        OkHttpClient client = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url(url).post(RequestBody.create(MediaType.parse("application/octet-stream"), getData().toByteArray()));
        Request request = builder.build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Request call, IOException e){
                Log.d(TAG, "onFailure --- e:"+e);
                if(callback != null) callback.onFailure(call, e);
            }

            @Override
            public void onResponse(Response response) throws IOException {

                if(callback != null) callback.onResponse(response);
            }
        });
    }
}

Server side

server.js



var fs = require('fs')
var protobuf = require('protocol-buffers')
var messages = protobuf(fs.readFileSync('search_request.proto'))
//Appropriate message generation
var buf = messages.SearchRequest.encode({
  query: "hoge",
  page_number: 1234
})

require('connect')().use(function(req, res, next) {
	next();
}).use(function(req, res) {
	//Serialize request from Android Java
	var body = [];
	req.on('data', function (data) {
		// body +=data;
		body.push(data);
	});
	req.on('end',function(){
		var buf = Buffer.concat( body );

		try {
			console.log(body);
			console.log(buf);
			var obj = messages.SearchRequest.decode(buf)
			console.log(obj)
		} catch (e) {
			console.log(e)
		}
		res.writeHead(200, {'Content-Type': 'application/octet-stream'});
		//Response message
		res.write(buf, 'binary');
		res.end();
	});
  }).listen(3000);

Start the server (it will expire with Ctl + C, so run it on the iOS side while starting)

node server.js

Unlike when server.js receives from Objective-C, deserialization failed unless byte is written to push to var body = [] ;. Confirmed that it can also be received from Objective-C with the above code

that's all

Recommended Posts

Check communication from Android to node.js server with protocol buffers
[Android] Uploading images from your device to the server
Android: How to deal with "Could not determine java version from '10 .0.1'"
I tried to check the operation of gRPC server with grpcurl
protocol buffeer migration from 2.x to 3.x
Stop resending from client to server
Run node.js from android java (processing)
Connect to Rails server with iPhone
Update MySQL from 5.7 to 8.0 with Docker
How to check before sending a message to the server with Spring Integration
Find Raspberry Pi from Android with mDNS
Getting Started with Language Server Protocol with LSP4J
Connect with VS Code from a Windows client to Docker on another server