Android搭建grpc环境过程分步详解

 更新时间:2023年04月11日 10:11:41   作者:haohulala  
本篇文章使用的IDE是Android Studio。这里先吐槽一句,安卓项目搭建grpc环境,不管是引入插件还是引入第三方库,对于版本的要求都极为苛刻,一旦版本不匹配就会报错,所以对于版本的搭配一定要注意

下面介绍的这个版本搭配是我研究好久好久才跑通的,这在我的电脑上是一组可行的配置,如果你使用了同样的配置跑不通,那可能是环境中某一部分还是有不同的地方,需要你自己再去找一下解决问题的办法,那么话不多说,直接上配置吧。

各种配置文件

首先我们需要设置三个配置文件,如下图所示

我们先来看一下项目设置setting.gradle,按照我的理解,这里应该是设置一些gradle仓库地址,还有项目中包含的模块等等信息。

我的配置是这样写的

pluginManagement {
    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        maven { url 'https://repo.eclipse.org/content/repositories/paho-releases/'}
    }
}
rootProject.name = "grpc_project_plus"
include ':app'

接着是项目的的build.gradle,这里面需要引入一些插件和进行gradle版本设置,其中gradle版本设置也是一个坑,版本号要设置对才行

buildscript {
    repositories {
        maven{ url 'https://maven.aliyun.com/repository/jcenter'}
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.2.0"
        classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17"
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

从上面的配置中我们可以看出,我们使用的gradle插件的版本是7.2.0,然后配置的gradle版本是7.4,具体的设置方法就是到gradle的配置文件中指定

当然也有一个简单的办法,就是到project structure中去指定

上面这张图按照我的理解,上面是插件的版本号,下面就是gradle的版本号,这两个不对应的话容易出问题,这里顺便说一下,我的Android Studio的版本应该是2021.3.1,就是海豚的图标。(经过这次的环境搭建,我现在对于版本号真的非常敏感,调版本号真的太折磨人了)

最后就是模块的build.gradle,我找到的一个能跑通demo的设置如下

plugins {
    id 'com.android.application'
    id 'com.google.protobuf'
}
android {
    namespace 'com.example.grpc_project_plus'
    compileSdk 32
    defaultConfig {
        applicationId "com.example.grpc_project_plus"
        minSdk 29
        targetSdk 32
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
        exclude group: 'com.google.guava', module: 'listenablefuture'
    }
    sourceSets {
        main {
            proto {
                srcDir 'src/main/proto'
            }
        }
    }
    packagingOptions {
        pickFirst 'META-INF/INDEX.LIST'
        pickFirst 'META-INF/LICENSE'
        pickFirst 'META-INF/io.netty.versions.properties'
    }
}
protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.17.2'
    }
    plugins {
        /*javalite {
            artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
        }*/
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.39.0' // CURRENT_GRPC_VERSION
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java { option 'lite' }
            }
            task.plugins {
                grpc { // Options added to --grpc_out
                    option 'lite' }
            }
        }
    }
}
dependencies {
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    /*implementation 'io.grpc:grpc-okhttp:1.1.2'
    implementation 'io.grpc:grpc-netty:1.1.2'
    implementation 'io.grpc:grpc-protobuf-lite:1.1.2'
    implementation 'io.grpc:grpc-stub:1.1.2'
    implementation 'javax.annotation:javax.annotation-api:1.2'*/
    // You need to build grpc-java to obtain these libraries below.
    implementation 'io.grpc:grpc-netty:1.39.0'
    implementation 'io.grpc:grpc-okhttp:1.39.0' // CURRENT_GRPC_VERSION
    implementation 'io.grpc:grpc-protobuf-lite:1.39.0' // CURRENT_GRPC_VERSION
    implementation 'io.grpc:grpc-stub:1.39.0' // CURRENT_GRPC_VERSION
    implementation 'org.apache.tomcat:annotations-api:6.0.53'
}

编写proto文件并编译

配置好了上述环境后,我们需要编译proto文件。

首先在main目录下新建一个文件夹proto,然后编写hello.proto文件。

文件的内容如下

syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
    // Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
    string name = 1;
}
// The response message containing the greetings
message HelloReply {
    string message = 1;
}

这是一个简单的grpc接口调用,具体的语法我就不说了,这篇文章主要是讲环境搭建。

接着编译项目,如果编译成功的话,可以在build文件夹中看到grpc相关的java文件。

编写简单的demo代码

这是最后一步,在主Activity中编写简单的客户端和服务端代码测试grpc服务是否可以正常使用。

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "GrpcDemo";
    private static final int PROT = 56322;
    private static final String NAME = "hello world";
    private static final String HOST = "localhost";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "start");
        startServer(PROT);
        Log.d(TAG, "start server.");
        startClient(HOST, PROT, NAME);
        Log.d(TAG, "start client.");
    }
    private void startServer(int port){
        try {
            NettyServerBuilder.forPort(port)
                    .addService(new GreeterImpl())
                    .build()
                    .start();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, e.getMessage());
        }
    }
    private void startClient(String host, int port, String name){
        ManagedChannel mChannel = ManagedChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build();
        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(mChannel);
        HelloRequest message = HelloRequest.newBuilder().setName(name).build();
        stub.sayHello(message, new StreamObserver<HelloReply>() {
            @Override
            public void onNext(HelloReply value) {
                //Log.d(TAG, "sayHello onNext.");
                Log.d(TAG, value.getMessage());
            }
            @Override
            public void onError(Throwable t) {
                Log.d(TAG, "sayHello onError.");
            }
            @Override
            public void onCompleted() {
                Log.d(TAG, "sayHello onCompleted.");
            }
        });
    }
    private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
        public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
            responseObserver.onNext(sayHello(request));
            responseObserver.onCompleted();
        }
        private HelloReply sayHello(HelloRequest request) {
            return HelloReply.newBuilder()
                    .setMessage(request.getName())
                    .build();
        }
    }
}

然后需要在AndroidManifest.xml文件中添加网络权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Grpc_project_plus"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>
</manifest>

运行上述代码,如果能在控制台看到下面的这句话就说明环境搭建成功了。

结语

这次的环境搭建真的非常艰难,前前后后遇到了各种问题。不得不说,安卓编程对于版本太敏感了,只要有一个版本没有对应上项目都可能跑不通。

到此这篇关于Android搭建grpc环境过程分步详解的文章就介绍到这了,更多相关Android搭建grpc环境内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论