首页 > 其他分享 >【多服务场景化解决方案】让新闻“动”起来

【多服务场景化解决方案】让新闻“动”起来

时间:2022-10-31 20:14:33浏览次数:77  
标签:ASR 场景 String 解决方案 Kit 新闻 MLAsrCaptureConstants public

1、介绍

总览

搜索服务、Network Kit以及机器学习服务是新闻类应用最常用的服务。机器学习服务把用户输入信息传递给搜索服务,搜索服务和Network Kit一起检索相关新闻返回给机器学习服务,机器学习服务再通过语音合成功能播报新闻。

本次codelab描述如何创建Android新闻应用SmartNews,并在应用中集成搜索服务、Network Kit以及机器学习服务。用户可以注册账号,阅读新闻,并选择不同语言听机器学习服务的TTS功能转换的语音新闻。用户可以通过语音或文字搜索信息。

  • Network Kit通过NEWS接口获取新闻。

  • 阅读新闻,可以选择6种语言播放新闻。

  • 切换语言设置。

  • 通过语音或文字搜索新闻。

服务场景描述

本codelab以搜索服务、Network Kit以及机器学习服务为例,描述如何在一个应用中集成多个服务。这种场景在多媒体应用(例如电商应用、娱乐应用、教育应用以及商业应用)中广泛应用。

特性

HMS Core服务

通过TTS服务听语音新闻

机器学习服务

听语音新闻时,切换目标语言

机器学习服务

搜索新闻

搜索服务

通过接口搜索新闻

机器学习服务

传递用户输入,用户新闻搜索

机器学习服务

 

您将建立什么

在本次Codelab中,您将建立一个示例项目并集成服务。在该项目中,您可以:

  1. 获取最新的新闻,并在新闻中展示广告。

    cke_7362.png

  2. 把文本转换为语音。

     

    cke_12645.png

  3. 通过语音或文字搜索新闻。

     

    cke_17874.pngcke_20137.png

  4. TTS转换前切换语言设置。

     

    cke_26015.png

     

    应用流程

    Splash Activity

    启动splash页面。

    NewsDetails Activity

    1. 展示选择的新闻。

    2. 听语音新闻。

    Login Activity

    通过华为账号和调用Login Activity完成登录。

    NewsActivity

    1. 阅读最新新闻,选择新闻离线阅读。

    新闻检索

    输入文字或通过语音搜索新闻。

    语音设置

    1. 查看详情。

    2. 切换语言。

    新闻刷新

    刷新新闻列表,阅读最新新闻。

您需要什么

在本codelab中,你需要学习:

  • 如何集成Network Kit。

  • 如何集成机器学习服务提供TTS、文本翻译以及ASR功能。

  • 如何集成搜索服务。

 

2、您需要什么

硬件需求

提前准备如下硬件:

  • 一台Windows 10台式或笔记本电脑。

  • 一部集成HMS Core (APK) 5.0.0.300或以上版本的华为手机。

软件需求

提前准备如下软件:

  • Android Studio 3.0或以上版本

  • JDK 1.8或以上版本

  • 安卓SDK平台(API 23或以上版本)

  • Gradle 4.6或以上版本

 

3、能力接入准备

集成HMS Core服务之前,注册成为开发者并完成如下准备工作:

  • AppGallery Connect中创建新闻。

  • 创建Android Studio项目。

  • 生成签名证书。

  • 生成签名证书指纹。

  • 配置签名证书指纹。

  • 添加应用包名并保存配置文件。

  • 在项目级build.gradle文件中添加AppGallery Connect插件和Maven仓。

  • 在Android Studio中配置签名证书。

    详情请参见HUAWEI HMS Core集成准备(Android)

 

4、集成Network Kit

本项目通过Network Kit调用第三方接口获取新闻,通过搜索服务将新闻提供给用户。

  1. 在Application类中初始化Network Kit。

    Java

    /**
      * 异步加载Network Kit对象。
      */
    public void initNetworkKIT() {
         NetworkKit.init(
                 getApplicationContext(),
                 new NetworkKit.Callback() {
                     @Override
                     public void onResult(boolean status) {
                         if (status) {
                             Log.d(TAG, getApplication().getResources().getString(R.string.Network_sucess));
                         } else {
                             Log.d(TAG, getApplication().getResources().getString(R.string.Network_failed));
                         }
                    }
                 });

    Kotlin

    /**
      * 异步加载Network Kit对象。
      */
    fun initNetworkKit() {
         NetworkKit.init(this, object : NetworkKit.Callback() {
             override fun onResult(result: Boolean) {
                 if (result) {
                     Log.i(TAG, "Networkkit init success")
                 } else {
                     Log.i(TAG, "Networkkit init failed")
                 }
             }
         })
     }
  2. 实现Network URL请求并创建接口。

    Java

    /**
      * 声明一个请求API。
      **/
    public interface NewsApi {
        @GET("newsapi.org/v2/top-headlines")
         Submit<String> getNews(@Query("country") String country,   
            @Query("apiKey") String apiKey);

    Kotlin

    /**
      * 声明一个请求API。
      **/
     public interface NewsApi
    @GET("newsapi.org/v2/top-headlines")
     fun getNews(@Query("country") country: String?,@Query("apiKey") apiKey: String?): Submit<String>
  3. 创建数据模型类。

    Java

    /**
     * 新闻资源模型描述资源信息
     * 以及新闻文章。
     */
    public class Newsdata {
        @SerializedName("status")
        @Expose
        private String status;
    
        @SerializedName("totalResult")
        @Expose
        private int totalResult;
    
        @SerializedName("articles")
        @Expose
        private List<Article> article;
        public String getStatus() {
            return status;
        }
        public void setStatus(String status) {
            this.status = status;
        }
        public void setTotalResults(int totalresults) {
            this.totalResult = totalresults;
        }
    
        public List<Article> getArticle() {
            return article;
        }
        public void setArticle(List<Article> article) {
            this.article = article;
        }
    }

    Kotlin

     /**
      * 新闻资源模型描述资源信息
      * 以及新闻文章。
      */
    data class NewsSource(
         @SerializedName("status") var status: String = "",
         @SerializedName("source") var source: String = "",
         @SerializedName("sortBy") var sortBy: String = "",
         @SerializedName("articles") var articles: List<News> = emptyList()
     )
  4. Create a RESTClient from Network Kit.

    Java

    /**
      * 提供Network Kit的RestClient。
      */
    @Singleton
     @Provides
    static RestClient provideNetworkService () {
         return new RestClient.Builder().baseUrl(Constants.BASE_URL).httpClient(getHttpClient()).build();
     }
    
    private static HttpClient getHttpClient() {
         return new HttpClient.Builder()
                 .connectTimeout(Constants.CONNECT_TIMEOUT)
                 .readTimeout(Constants.TIMEOUT)
                 .writeTimeout(Constants.WRITE_TIMEOUT)
                 .build();
     }

    Kotlin

    /**
      * 提供Network Kit的RestClient。
      */
    @Singleton
     @Provides
    fun provideNetworkService(): ApiService {
         return RestClient
                 .Builder()
                 .baseUrl(Constants.BASE_URL)
                 .httpClient(getHttpClient())
                 .build()
                 .create(ApiService::class.java)
     }
    
    
    private fun getHttpClient(): HttpClient? {
         return HttpClient.Builder()
                 .connectTimeout(Constants.CONNECT_TIMEOUT)
                 .readTimeout(Constants.TIMEOUT)
                 .writeTimeout(Constants.WRITE_TIMEOUT)
                 .enableQuic(false)
                 .build()
     }
  5. 创建请求接口对象,发送异步请求,使用NewsActivity类中的RecyclerView展示新闻。

    Java

    /**
      * 根据网络连接状态获取新闻。
      */
    private void getNewsList() {
         showProgressBar(true);
         
         viewModel
                 .getNewsList()
                 .observe(
                         this,
                         new Observer<NewsResource<Newsdata>>() {
                             @Override
                             public void onChanged(NewsResource<Newsdata> newsNewsResource) {
                                 switch (newsNewsResource.status) {
                                     case SUCCESS:
                                         recyclerView.setVisibility(View.VISIBLE);
                                         showProgressBar(false);
                                         if (newsNewsResource.data != null
                                                 && newsNewsResource.data.getStatus().equals(Constants.STATUS_OK)) {
                                             newsError.setVisibility(View.GONE);
                                             if (!articles.isEmpty()) {
                                                 articles.clear();
                                             }
                                             articles = newsNewsResource.data.getArticle();
                                             if (articles.size() != 0) {
                                                 adapter =
                                                         new NewsListAdapter(
                                                                 articles, NewsActivity.this, NewsActivity.this);
                                                 recyclerView.setAdapter(adapter);
                                                 adapter.notifyDataSetChanged();
                                             } else newsError.setVisibility(View.VISIBLE);
                                         } else {
                                             recyclerView.setVisibility(View.GONE);
                                             newsError.setVisibility(View.VISIBLE);
                                         }
                                         break;
                                     case ERROR:
                                         showProgressBar(false);
                                         recyclerView.setVisibility(View.GONE);
                                         newsError.setVisibility(View.VISIBLE);
                                         break;
                                 }
                             }
                         });

    Kotlin

    private fun getNews() {
    
         newsArticleViewModel.fetchNewsSearchApi("Today News").observe(this, Observer {
             latestNews = it
             if (latestNews.isNotEmpty()){
                 recyclerView!!.visibility = View.VISIBLE
                 newsError.visibility = View.GONE
                 mAdapter = NewsListAdapter(
                     latestNews,
                     this@NewsActivity,
                     this@NewsActivity
                 )
                 recyclerView!!.adapter = mAdapter
                 mAdapter!!.notifyDataSetChanged()
             }
    
         })

    cke_136120.png

 

5、集成机器学习服务

本应用中,机器学习服务把文本转换为语音,实现TTS和ASR,把文本翻译成多种语言,作为搜索服务的输入。

  1. 在Application类中初始化机器学习服务。

    Java

    /**
      *  初始化机器学习服务。
      *
      */
    private void initMLkit() {
         AGConnectServicesConfig config = AGConnectServicesConfig.fromContext(this);
         MLApplication.getInstance().setApiKey(config.getString(API_KEY));
     }

    Kotlin

    /**
      * 初始化机器学习服务。
      */
    private fun initMLKit() {
         val config = AGConnectServicesConfig.fromContext(this)
         MLApplication.getInstance().apiKey = config.getString(API_KEY)
     }
  2. 自定义MLTtsConfig类,生成对象并传递给MLTtsEngine。

    Java

    /**
      * 定制配置类MLTtsConfig,创建文本到语音转换引擎。
      **/
    public void confingMLkitTTS() {
         mlTtsConfig = new MLTtsConfig().setSpeed(1.0f).setVolume(1.0f);
         mlTtsEngine = new MLTtsEngine(mlTtsConfig);
         mlTtsEngine.updateConfig(mlTtsConfig);
     }

    Kotlin

    /**
      * 定制配置类MLTtsConfig,创建文本到语音转换引擎。
      **/
    fun confMLkitTTS() {
         mlTtsConfig = MLTtsConfig()
                 .setSpeed(1.0f)
                 .setVolume(1.0f)
         mlTtsEngine = MLTtsEngine(mlTtsConfig)
         mlTtsEngine!!.updateConfig(mlTtsConfig)
     }
  3. 翻译文本,提供译文给TTS供用户听语音新闻。

    Java

    /**
      * 根据用户选择的语言将文本翻译为语音。
      *
      * @param 新闻文本以及用户选择的语言
      */
    public void translateText(String text, String lang) {
         MLRemoteTranslateSetting setting = new MLRemoteTranslateSetting.Factory().setTargetLangCode(lang).create();
         MLRemoteTranslator mlRemoteTranslator = MLTranslatorFactory.getInstance().getRemoteTranslator(setting);
         final Task<String> task = mlRemoteTranslator.asyncTranslate(text);
         task.addOnSuccessListener(
                         new OnSuccessListener<String>() {
                             @Override
                             public void onSuccess(String text) {
                                 mlTtsEngine.speak(text, MLTtsEngine.QUEUE_APPEND);
                             }
                         })
                 .addOnFailureListener(
                         new OnFailureListener() {
                             @Override
                             public void onFailure(Exception e) {
                                 try {
                                     MLException mlException = (MLException) e;
                                     Log.e(TAG, "failure to convert TTS");
                                 } catch (Exception error) {
                                 }
                             }
                         });
     }

    Kotlin

    /**
      * 根据用户选择的语言将文本翻译为语音。
      *
      * @param 新闻文本以及用户选择的语言
      */
    fun translateText(text: String?, lang: String?) {
         val setting = MLRemoteTranslateSetting.Factory()
                 .setTargetLangCode(lang)
                 .create()
         val mlRemoteTranslator = MLTranslatorFactory.getInstance().getRemoteTranslator(setting)
         val task = mlRemoteTranslator.asyncTranslate(text)
         task.addOnSuccessListener { text -> mlTtsEngine!!.speak(text, MLTtsEngine.QUEUE_APPEND) }.addOnFailureListener { e ->
             try {
                 val mlException = e as MLException
             } catch (error: Exception) {
                 Log.e(TAG, "failure to convert TTS")
             }
         }
     }

    cke_256963.png

  4. 使用搜索服务实现ASR功能。在NewsActivity类的onCreate()方法中检查是否有所需的权限。

    Java

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
             != PackageManager.PERMISSION_GRANTED) {
         checkPermission();
     }
     
     
    /**
      * 检查SDK所需权限。
      */
    private void checkPermission() {
         if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
             ArrayList<String> permissionsList = new ArrayList<>();
             for (String perm : getAllPermission()) {
                 if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, perm)) {
                     permissionsList.add(perm);
                 }
             }
             if (!permissionsList.isEmpty()) {
                 ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[0]), REQUEST_MICROPHONE);
             }
         }
     }
    
    public static List<String> getAllPermission() {
         return Collections.unmodifiableList(Arrays.asList(ALL_PERMISSION));
     }

    Kotlin

    if (ActivityCompat.checkSelfPermission(
             this,
             Manifest.permission.RECORD_AUDIO
         ) != PackageManager.PERMISSION_GRANTED
    ) {
         this.requestAudioPermission();
     }
     
    /**
      * 检查SDK所需权限。
      */
    private fun requestAudioPermission() {
         val permissions =
             arrayOf(Manifest.permission.RECORD_AUDIO)
         if (!ActivityCompat.shouldShowRequestPermissionRationale(
                 this,
                 Manifest.permission.RECORD_AUDIO
             )
         ) {
             ActivityCompat.requestPermissions(this, permissions, AUDIO_PERMISSION_CODE)
             return
         }
     }
    
    override fun onRequestPermissionsResult(
         requestCode: Int, permissions: Array<String?>,
         grantResults: IntArray
    ) {
         if (requestCode != AUDIO_PERMISSION_CODE) {
             super.onRequestPermissionsResult(requestCode, permissions, grantResults)
             return
         }
     }
  5. 开启搜索框中的ASR按钮点击功能。

    Java

    /**
      * 开启ASR功能,使用Intent实现识别设置。
      * 
      */
    public void startASR() {
         search.clearFocus();
         Intent intent =
                 new Intent(this, MLAsrCaptureActivity.class)
                         .putExtra(MLAsrCaptureConstants.LANGUAGE, "en-US")
                         .putExtra(MLAsrCaptureConstants.FEATURE, MLAsrCaptureConstants.FEATURE_WORDFLUX);
         startActivityForResult(intent, REQUEST_CODE_ASR);
     }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         String text = "";
         if (requestCode == REQUEST_CODE_ASR) {
             switch (resultCode) {
                 case MLAsrCaptureConstants.ASR_SUCCESS:
                     if (data != null) {
                         Bundle bundle = data.getExtras();
                         if (bundle.containsKey(MLAsrCaptureConstants.ASR_RESULT)) {
                             text = bundle.getString(MLAsrCaptureConstants.ASR_RESULT);
                             viewModel.initSearch(text);
                         }
                     }
                     break;
                 case MLAsrCaptureConstants.ASR_FAILURE:
                     if (data != null) {
                         Bundle bundle = data.getExtras();
                         if (bundle.containsKey(MLAsrCaptureConstants.ASR_ERROR_CODE)) {
                             Log.e(TAG, getApplication().getResources().getString(R.string.asr_errorCode));
                         }
                     }
                 default:
                     break;
             }
         }
     }

    Kotlin

    /**
      * 开启ASR功能,使用Intent实现识别设置。
      * 
      */
    fun startASR() {
             search!!.clearFocus()
             val intent = Intent(this, MLAsrCaptureActivity::class.java)
                 .putExtra(MLAsrCaptureConstants.LANGUAGE, "en-US")
                 .putExtra(MLAsrCaptureConstants.FEATURE, MLAsrCaptureConstants.FEATURE_WORDFLUX)
             startActivityForResult(intent, REQUEST_CODE_ASR)
         }
    
         override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
             super.onActivityResult(requestCode, resultCode, data)
             var text = ""
             if (requestCode == REQUEST_CODE_ASR) {
                 when (resultCode) {
                     MLAsrCaptureConstants.ASR_SUCCESS -> if (data != null) {
                         val bundle = data.extras
                         if (bundle!!.containsKey(MLAsrCaptureConstants.ASR_RESULT)) {
                             text = bundle.getString(MLAsrCaptureConstants.ASR_RESULT).toString()
                             if(text!=""){
                             newsArticleViewModel.initSearch(text)
                             }
                         }
                     }
                     MLAsrCaptureConstants.ASR_FAILURE -> if (data != null) {
                         val bundle = data.extras
                         if (bundle!!.containsKey(MLAsrCaptureConstants.ASR_ERROR_CODE)) {
                             val errorCode = bundle.getInt(MLAsrCaptureConstants.ASR_ERROR_CODE)
                             Log.e("TAG", application.resources.getString(R.string.sigin_failed))
                         }
                         if (bundle.containsKey(MLAsrCaptureConstants.ASR_ERROR_MESSAGE)) {
                             val errorMsg = bundle.getString(MLAsrCaptureConstants.ASR_ERROR_MESSAGE)
                         }
                         if (bundle.containsKey(MLAsrCaptureConstants.ASR_SUB_ERROR_CODE)) {
                             val subErrorCode = bundle.getInt(MLAsrCaptureConstants.ASR_SUB_ERROR_CODE)
                         }
                     }
                     else -> {
                     }
                 }
             }
         }
     }

    cke_350693.png

 

6、集成搜索服务

本项目中,搜索服务负责提供搜索功能。用户可以输入文本或通过语音搜索新闻。

  1. 在NewsActivity类中新建搜索框并在Application类中初始化搜索服务。

    Java

    /**
      * Initialize the Search Kit instance.
      */
    private void initSearchKit() {
         SearchKitInstance.init(this, Constants.CLIENT_ID);
     }

    Kotlin

    /**
      * Initialize the Search Kit instance.
      */
    fun initSearchKit() {
         SearchKitInstance.init(this, "103207661")
     }
  2. 获取access token,用于在服务端验证搜索请求。验证成功后返回搜索结果。

    Java

    /**
      * API for obtaining the access token for Search Kit.
      *
      */
    public interface AccessTokenService {
         @POST("oauth-login.cloud.huawei.com/oauth2/v3/token")
         @FormUrlEncoded
         @Headers("Content-Type:application/x-www-form-urlencoded\", \"charset:UTF-8")
         Submit<String> createAccessToken(
                 @Field("grant_type") String grant_type,
                 @Field("client_secret") String client_secret,
                 @Field("client_id") String client_id);
     }

    Kotlin

    /**
      * API for obtaining the access token for Search Kit.
      *
      */
    interface ApiService {
    
         @POST("oauth-login.cloud.huawei.com/oauth2/v3/token")
         @FormUrlEncoded
         @Headers("Content-Type:application/x-www-form-urlencoded\", \"charset:UTF-8")
         fun getAccessToken(
             @Field("grant_type") grant_type: String?,
             @Field("client_secret") client_secret: String?,
             @Field("client_id") client_id: String?
         ): Submit<String>?
  3. 创建请求接口并发送异步请求。

    Java

    restClient
             .create(AccessTokenService.class)
             .createAccessToken(Constants.GRANT_TYPE, Constants.CLIENT_SECRET, Constants.CLIENT_ID). enqueue(searchCallback);
     
    public void searchCallback(String text) {
         searchCallback =
                 new Callback() {
                     @Override
                     public void onResponse(Submit submit, Response response)              
                         processResponse(response)                                
                         
                     @Override
                     public void onFailure(Submit submit, Throwable throwable) {
                         String errorMsg = "response onFailure : ";
                         Log.e(TAG, errorMsg);
                         }     };

    Kotlin

    apiServices.getAccessToken(
    Constants.GRANT_TYPE, Constants.CLIENT_SECRET, Constants.CLIENT_ID
         )?.enqueue(object : Callback<String?>() {
             override fun onResponse(body: Submit<String?>?, response: Response<String?>?) {
                 Handler(Looper.getMainLooper()).postDelayed({
                     val gson = Gson()
                     val tokenModel: TokenModel =
                         gson.fromJson(response!!.body, TokenModel::class.java)
                    val mSearchNews = initSearchKit(tokenModel.access_token, context, text)
                     mCountryList.value = mSearchNews
                     mCallback.onNetworkSuccess()
    
                 }, 1000)
             }
    
             override fun onFailure(p0: Submit<String?>?, p1: Throwable) {
                 mCallback.onFailure("Api Failure")
             }
         })
         return mCountryList
     }
  4. 设置搜索服务实例的access token并把用户文本或语音输入的查询信息传给搜索服务。把新闻列表传给adapter类并通过RecyclerView展示新闻。

    Java

    /**
      * Set the acess token.
      */
    SearchKitInstance.getInstance().setInstanceCredential(accessToken);
     SearchKitInstance.getInstance().getNewsSearcher().setTimeOut(10000);
     
    /**
      * Search for news based on information entered by the user
      */
    private void searchForQuery(String accessToken, String text) {
         CommonSearchRequest commonSearchRequest = new CommonSearchRequest();
         commonSearchRequest.setQ(text);
         commonSearchRequest.setLang(Language.ENGLISH);
         commonSearchRequest.setSregion(Region.UNITEDKINGDOM);
         commonSearchRequest.setPs(10);
         commonSearchRequest.setPn(1);
         SearchKitInstance.getInstance().setInstanceCredential(accessToken);
         SearchKitInstance.getInstance().getNewsSearcher().setTimeOut(10000);
         BaseSearchResponse<List<NewsItem>> response =
                 SearchKitInstance.getInstance().getNewsSearcher().search(commonSearchRequest);
         if (response.getData().isEmpty() || response == null || response.equals("") ) {
             newsStatus.setStatus(Constants.STATUS_FAILED);
             mNews.postValue(newsStatus);
             return;
         }
         List<NewsItem> newinfo = response.getData();
         processbodyforsearch(newinfo);
     }

    Kotlin

        /**
          * Search for news based on information entered by the user.
          */
         private fun searchForQuery(
             accessToken: String?,
             context: Context,
             text: String
         ): ArrayList<News> {
             var mSearchNews = ArrayList<News>()
             val commonSearchRequest = CommonSearchRequest()
             commonSearchRequest.setQ(text)
             commonSearchRequest.setLang(Language.ENGLISH)
             commonSearchRequest.setSregion(Region.UNITEDKINGDOM)
             commonSearchRequest.setPs(10)
             commonSearchRequest.setPn(1)
             SearchKitInstance.init(context, "103207661")
             SearchKitInstance.getInstance().setInstanceCredential(accessToken)
             SearchKitInstance.getInstance().newsSearcher.setTimeOut(10000)
             val response = SearchKitInstance.getInstance().newsSearcher.search(commonSearchRequest)
             if (response.getData().isEmpty() || !(!response.equals("") || response.getData() != null)) {
                 mSearchNews = arrayListOf()
                 mCallback.onFailure("No data Found")
             } else {
                 val newsitem = response!!.getData()
                 for (i in newsitem.indices) {
                     mSearchNews.add(
                         News(
                             null,
                             newsitem[i].title,
                             null,
                             newsitem[i].clickUrl,
                             newsitem[i].provider.logo,
                             newsitem[i].publish_time
                         )
                     )
                 }
                 mCallback.onNetworkSuccess()
             }
             return mSearchNews;
         }
     }

 

7、恭喜您

祝贺您,您已经成功地构建了一个新闻应用并学会:

  • 如何集成Network Kit。

  • 如何实现ML Kit的TTS、文本翻译以及ASR功能。

  • 实现Search Kit的新闻搜索功能。

 

8、参考

参考如下文档获取更多信息:

点击如下链接下载源码:

源码下载

声明:本codelab实现多个HMS Core服务在单个项目中的集成,供您参考。您需要验证确保相关开源代码的安全合法合规。

欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh

标签:ASR,场景,String,解决方案,Kit,新闻,MLAsrCaptureConstants,public
From: https://www.cnblogs.com/developer-huawei/p/16845574.html

相关文章