
# 一句话识别(http版)
#### 前提条件
- 确保已经按照配置好Android开发环境。
- 请参考[SDK（websocket）](https://support.huaweicloud.com/sdkreference-sis/sis_05_0004.html)获取最新版本SDK包。
 
#### 初始化Client
初始化SisClient,详细信息如下。
1. 配置客户端连接参数。
   - 默认配置
     ```
     // 使用默认配置
     HttpConfig config = HttpConfig.getDefaultHttpConfig();
     ```
     
   
   - 网络代理（可选）
     ```
     // 根据需要配置网络代理，网络代理默认的协议为 `http` 协议
     config.withProxyHost("proxy.huaweicloud.com")
         .withProxyPort(8080)
         .withProxyUsername("test")
         .withProxyPassword("test");
     ```
     
   
   - 超时配置（可选）
     ```
     // 默认连接超时时间为60秒，可根据需要调整
     config.withTimeout(60);
     ```
     
   
   - SSL配置（可选）
     ```
     // 根据需要配置是否跳过SSL证书验证
     config.withIgnoreSSLVerification(true);
     ```
     
    
2. 配置认证信息。 配置AK、SK、project_id信息。华为云通过AK识别用户的身份，通过SK对请求数据进行签名验证，用于确保请求的机密性、完整性和请求者身份的正确性。
   - 使用永久AK和SK
     ```
     BasicCredentials basicCredentials = new BasicCredentials()
         .withAk(ak)
         .withSk(sk)
         .withProjectId(projectId);
     ```
     
   
   - 使用临时AK和SK
     ```
     BasicCredentials basicCredentials = new BasicCredentials()
         .withAk(ak)
         .withSk(sk)
         .withSecurityToken(securityToken)
         .withProjectId(projectId)
     ```
     
   
   
   认证参数说明：
   - ak、sk：访问密钥信息，获取方法请参考[AK/SK认证](https://support.huaweicloud.com/sdkreference-sis/sis_05_0003.html)。
   
   - projectId：华为云项目ID，获取方法请参考[获取项目ID](https://support.huaweicloud.com/api-sis/sis_03_0008.html)。
   
   - securityToken：采用临时AK、SK 认证场景下的安全票据，可以[通过token获取](https://support.huaweicloud.com/api-iam/iam_04_0002.html)或者[通过委托授权获取](https://support.huaweicloud.com/api-iam/iam_04_0101.html)。
    
3. 初始化客户端（region和指定云服务endpoint二选一即可）。
   - 指定region方式（强烈推荐推荐）
     ```
     // 初始化客户端认证信息，使用当前客户端初始化方式可不填 projectId/domainId，以初始化 BasicCredentials 为例
     BasicCredentials basicCredentials = new BasicCredentials()
         .withAk(ak)
         .withSk(sk);
     // 初始化指定云服务的客户端 {Service}Client ，以初始化 Region 级服务Sis的 SisClient 为例
     SisClient client = SisClient.newBuilder()
         .withHttpConfig(config)
         .withCredential(https://developer.huaweicloud.com/endpoint?SISasicCredentials)
         .withRegion(SisRegion.valueOf("cn-north-4"))
         .build();
     ```
     
   
   - 指定云服务endpoint方式（可选）
     ```
     // 指定终端节点，以Sis服务北京四的 endpoint 为例
     String endpoint = "https://sis-ext.cn-north-4.myhuaweicloud.com";
     // 初始化客户端认证信息，需要填写相应 projectId/domainId，以初始化 BasicCredentials 为例
     BasicCredentials basicCredentials = new BasicCredentials()
         .withAk(ak)
         .withSk(sk)
         .withProjectId(projectId);
     // 初始化指定云服务的客户端 {Service}Client ，以初始化 Region 级服务SiS的 SisClient 为例
     SisClient client = SisClient.newBuilder()
         .withHttpConfig(config)
         .withCredential(basicCredentials)
         .withEndpoint(endpoint)
         .build();
     ```
     endpoint是华为云各服务应用区域和各服务的终端节点，详情请查看 [地区和终端节点](https://developer.huaweicloud.com/endpoint?SIS)。
     
    
 
#### 请求参数
1. 请求类为RecognizeShortAudioRequest，该类的body参数为PostShortAudioReq。
2. PostShortAudioReq的包含data,和config两个参数，其中data为识别音频的base64格式的字符串。Config参数详见[表1]。
    表1Config 
   | 参数           | 是否必选 | 参数类型   | 描述                                                                                                                              |
   |:---|:---|:---|:---|
   | audioFormat  | 是    | String | 支持语音的格式，请参考[表 audio_format取值范围](https://support.huaweicloud.com/api-sis/sis_03_0094.html)。                                      |
   | property     | 是    | String | 所使用的模型特征串，通常是 "语种_采样率_领域"的形式，采样率需要与音频采样率保持一致，取值范围请参考[表 property取值范围](https://support.huaweicloud.com/api-sis/sis_03_0094.html)。 |
   | addPunc      | 否    | String | 表示是否在识别结果中添加标点，取值为"yes"和"no"，默认为"no"。                                                                                           |
   | digitNorm    | 否    | String | 表示是否将语音中的数字识别为阿拉伯数字，取值为"yes" 和 "no"，默认为"yes"。                                                                                   |
   | vocabularyId | 否    | String | 热词表id，不使用则不填写。 创建热词表信息请参考[创建热词表](https://support.huaweicloud.com/api-sis/sis_03_0071.html)。          |
   | needWordInfo | 否    | String | 表示是否在识别结果中输出分词结果信息，取值为"yes"和"no"，默认为"no"。                                                                                       |
      
   
3. 伪代码
```
com.huaweicloud.sdk.sis.v1.model.Config configbody = new com.huaweicloud.sdk.sis.v1.model.Config();configbody.setAudioFormat(com.huaweicloud.sdk.sis.v1.model.Config.AudioFormatEnum.fromValue("pcm16k16bit"));
configbody.setProperty(com.huaweicloud.sdk.sis.v1.model.Config.PropertyEnum.fromValue("chinese_16k_general"));
configbody.setAddPunc(com.huaweicloud.sdk.sis.v1.model.Config.AddPuncEnum.YES);
RecognizeShortAudioRequest request = new RecognizeShortAudioRequest();
PostShortAudioReq body = new PostShortAudioReq();body.withData(encoded);body.withConfig(configbody);
request.withBody(body);
```
#### 发送请求
```
RecognizeShortAudioResponse response = client.recognizeShortAudio(request);
```
返回体RecognizeShortAudioResponse的参数如下表所示。
**状态码： 200**
表2响应Body参数 
| 参数       | 是否必选 | 参数类型                                            | 描述                                                                              |
|:---|:---|:---|:---|
| trace_id | 是    | String                                          | 服务内部的令牌，可用于在日志中追溯具体流程，调用失败无此字段。 在某些错误情况下可能没有此令牌字符串。 |
| result   | 是    | [Result] object | 调用成功表示识别结果，调用失败时无此字段。                                                           |
   
 表3Result 
| 参数        | 是否必选 | 参数类型                                                         | 描述                       |
|:---|:---|:---|:---|
| text      | 是    | String                                                       | 调用成功表示识别出的内容。            |
| score     | 是    | Float                                                        | 调用成功表示识别出的置信度，取值范围：0\~1。 |
| word_info | 否    | Array of [WordInfo] objects | 分词信息列表。                  |
   
 表4WordInfo 
| 参数         | 是否必选 | 参数类型    | 描述    |
|:---|:---|:---|:---|
| start_time | 否    | Integer | 起始时间。 |
| end_time   | 否    | Integer | 结束时间。 |
| word       | 否    | String  | 分词。   |
   
**状态码： 400**
表5响应Body参数 
| 参数         | 参数类型   | 描述                     |
|:---|:---|:---|
| error_code | String | 调用失败时的错误码。 调用成功时无此字段。  |
| error_msg  | String | 调用失败时的错误信息。 调用成功时无此字段。 |
   
#### 示例代码
如下示例仅供参考，最新代码请前往[SDK（websocket）](https://support.huaweicloud.com/sdkreference-sis/sis_05_0004.html)章节获取并运行。
```
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */
package com.huaweicloud.sis.android.demo.asr;
import java.io.IOException;
import java.util.Base64;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.sis.v1.SisClient;
import com.huaweicloud.sdk.sis.v1.model.PostShortAudioReq;
import com.huaweicloud.sdk.sis.v1.model.RecognizeShortAudioRequest;
import com.huaweicloud.sdk.sis.v1.model.RecognizeShortAudioResponse;
import com.huaweicloud.sdk.sis.v1.region.SisRegion;
import com.huaweicloud.sis.android.demo.Config;
import com.huaweicloud.sis.android.demo.R;
import com.huaweicloud.sis.android.demo.service.AudioRecordService;
/**
 * 功能描述
 * 一句话识别http
 *
 * @since 2022-07-11
 */
public class SasrHttpActivity extends Activity {
    private TextView result;
    private TextView title;
    private Button startButton;
    private Handler sasrHandler;
    private HttpConfig config;
    private SisClient client;
    private AudioRecordService audioRecordService;
    @Override
    protected void onStart() {
        super.onStart();
        initView();
        initResources();
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sasr_http);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        audioRecordService.releaseAudioRecord();
    }
    /**
     * 绑定界面数据
     */
    private void initView() {
        title = findViewById(R.id.title);
        title.setText("一句话识别(http版)");
        result = findViewById(R.id.result);
        startButton = findViewById(R.id.start);
        startButton.setText("按住说话");
        // 按钮触及事件
        startButton.setOnTouchListener(new View.OnTouchListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_UP: {
                        // 按钮松开之后触发事件
                        audioRecordService.stopAudioRecord();
                        recognitionAfterRecording();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(getApplicationContext(), "录音结束识别中...", Toast.LENGTH_SHORT).show();
                            }
                        });
                        break;
                    }
                    case MotionEvent.ACTION_DOWN: {
                        // 开始录音
                        audioRecordService.startRecording();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(getApplicationContext(), "正在进行录音中...", Toast.LENGTH_SHORT).show();
                            }
                        });
                        break;
                    }
                    default:
                        break;
                }
                return true;
            }
        });
    }
    /**
     * 初始化请求资源
     */
    private void initResources() {
        BasicCredentials auth = new BasicCredentials()
                .withAk(this.getString(R.string.HUAWEICLOUD_SDK_AK))
                .withSk(this.getString(R.string.HUAWEICLOUD_SDK_SK))
                .withProjectId(Config.PROJECT_ID);
        config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);
        client = SisClient.newBuilder()
                .withHttpConfig(config)
                .withCredential(auth)
                .withRegion(SisRegion.valueOf(Config.REGION))
                .build();
        audioRecordService = new AudioRecordService(16000);
        sasrHandler = new Handler(getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message message) {
                super.handleMessage(message);
                switch (message.what) {
                    case 0:
                        Bundle bundle = message.getData();
                        result.setText(bundle.getString("result"));
                        break;
                    default:
                        Log.e("Unexpected value: ", String.valueOf(message.what));
                }
            }
        };
    }
    /**
     * 初始化请求参数
     */
    private RecognizeShortAudioRequest getRecognizeShortAudioRequest() {
        String encoded = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            encoded = Base64.getEncoder().encodeToString(audioRecordService.getByteArrayOutputStream().toByteArray());
        } else {
            encoded = android.util.Base64.encodeToString(audioRecordService.getByteArrayOutputStream().toByteArray(), 2);
        }
        audioRecordService.closeByteArrayOutStream();
        com.huaweicloud.sdk.sis.v1.model.Config configbody = new com.huaweicloud.sdk.sis.v1.model.Config();
        configbody.setAudioFormat(com.huaweicloud.sdk.sis.v1.model.Config.AudioFormatEnum.fromValue("pcm16k16bit"));
        configbody.setProperty(com.huaweicloud.sdk.sis.v1.model.Config.PropertyEnum.fromValue("chinese_16k_general"));
        configbody.setAddPunc(com.huaweicloud.sdk.sis.v1.model.Config.AddPuncEnum.YES);
        RecognizeShortAudioRequest request = new RecognizeShortAudioRequest();
        PostShortAudioReq body = new PostShortAudioReq();
        body.withData(encoded);
        body.withConfig(configbody);
        request.withBody(body);
        return request;
    }
    /**
     * 录音完成开始识别
     *
     * @throws IOException 输入异常
     */
    private void recognitionAfterRecording() {
        new Thread(() -> {
            RecognizeShortAudioRequest request = getRecognizeShortAudioRequest();
            String sasrRequestText = getSasrResponse(request);
            Message message = new Message();
            Bundle mBundle = new Bundle();
            mBundle.putString("result", sasrRequestText);
            message.setData(mBundle);
            sasrHandler.sendMessage(message);
        }).start();
    }
    /**
     * 一句话识别请求。
     *
     * @return 返回识别的文字
     */
    private String getSasrResponse(RecognizeShortAudioRequest request) {
        String resultStr = "";
        try {
            RecognizeShortAudioResponse response = client.recognizeShortAudio(request);
            resultStr = response.getResult().getText();
            Log.i("info:", response.getResult().getText());
        } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) {
            resultStr = e.toString();
            Log.i("error:", e.toString());
        }
        return resultStr;
    }
}
```
