2010年12月15日 星期三

[Android] 如何使用 TextToSpeech (TTS)



這篇是要替上一篇 [Android] 如何使用Google Translate API 和 Spinner 製作翻譯機 所作的翻譯機加上發音功能 , 所以要使用到Android 的 android.speech.tts.TextToSpeech , 對於這個功能Android 官方的部落格有一篇文章介紹得很清楚: An introduction to Text-To-Speech in Android , 大家可以參考一下 , 有些Android 的手機由於儲存的容量限制 , 所以不一定有安裝 TextToSpeech Engine , 所以首先要先檢查TextToSpeech.Engine 是否有被安裝 , 如果沒安裝的話再使用Android API去安裝 , 另外不是每個語言都被支援發音 , 所以我們還要去check一下 , 系統是否支援 , Layout檔案和AndroidManifest.xml都和上一篇一樣沒更改 , 所以這邊只貼程式碼的部分。





package com.android;

import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Button;
import android.widget.Toast;

import com.google.api.translate.Language;
import com.google.api.translate.Translate;

public class GoogleTranslateSpinner extends Activity implements OnItemSelectedListener , Button.OnClickListener , OnInitListener
{
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        AAdapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item,LanguageNameArray);
        AAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //ArrayAdapter設定下拉式清單內容的layout格式
        //android. 開頭的範本是由Android提供的
        
        SpinnerFrom = (Spinner) findViewById(R.id.SpinnerFrom);
        SpinnerFrom.setAdapter(AAdapter);
        SpinnerFrom.setOnItemSelectedListener(this);
        SpinnerTo = (Spinner) findViewById(R.id.SpinnerTo);        
        SpinnerTo.setAdapter(AAdapter);
        SpinnerTo.setOnItemSelectedListener(this);        
        
        EditTextFrom = (EditText) findViewById(R.id.EditTextFrom);
        EditTextTo = (EditText) findViewById(R.id.EditTextTo);
        
        Button = (Button) findViewById(R.id.Button);
        Button.setOnClickListener(this);
        
        Translate.setHttpReferrer("http://shung007.blogspot.com/");
        //Translate.setHttpReferrer(" Enter the URL of your site here");
        //必要!!! 否則程式會出現Exception
        
        Intent checkIntent = new Intent();  
        checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);  
        startActivityForResult(checkIntent, MY_TTS_CHECK_CODE);  
        //前往檢查 TTS Engine有無安裝
    }
    
    final int MY_TTS_CHECK_CODE = 9527;
    TextToSpeech TToSpeech;
    
    Spinner SpinnerFrom , SpinnerTo;
    EditText EditTextFrom , EditTextTo;
    Button Button;
    
    int positionFrom , positionTo;
    
    ArrayAdapter AAdapter;
    
    public String[] LanguageNameArray = new String[]{
            "繁體中文", "CHINESE_SIMPLIFIED", "GERMAN", "ENGLISH",
            "JAPANESE", "FRENCH"
        };
    //作為顯示在Spinner裡的清單內容
    
    public Language[] LanguageCode = new Language[]{
        Language.CHINESE_TRADITIONAL, Language.CHINESE_SIMPLIFIED,
        Language.GERMAN, Language.ENGLISH, Language.JAPANESE, Language.FRENCH      
    };
    //相對應的LanguageCode , 作為之後傳遞的引數用    
    
    public Locale[] LocaleCode = new Locale[]{
      Locale.CHINESE, Locale.CHINA,
      Locale.GERMAN, Locale.ENGLISH, Locale.JAPANESE, Locale.FRENCH      
     };
    //相對應的Locale值 , 準備替我們所選擇的語言發音

    @Override  
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {  
      // TODO Auto-generated method stub  
      if(requestCode == MY_TTS_CHECK_CODE)
      {      
       if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) //如果TTS Engine有成功找到的話
          {         
          TToSpeech = new TextToSpeech(this, this);
            //宣告一個 TextToSpeech instance
         //並註冊android.speech.tts.TextToSpeech.OnInitListener
            //當TTS Engine 初始完畢之後會呼叫 onInit(int status)
          Log.d("onActivityResult" , "onInit");
          }
          else //如果TTS Engine 沒有安裝的話 , 要求API安裝  
          {            
             Intent installIntent = new Intent();  
             installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);  
             startActivity(installIntent);  
          }  
      }
    }
    
 @Override
 public void onItemSelected(AdapterView parent, View view, int position,
   long arg)
 {  
  if(parent.equals(SpinnerFrom)) positionFrom = position;
  else positionTo = position;
  //判斷並記錄使用者選擇了哪個語言翻譯
 }

 @Override
 public void onNothingSelected(AdapterView arg0)
 {
  // TODO Auto-generated method stub  
 }

 @Override
 public void onClick(View ButtonView)
 {
  //按下Translate按鈕之後 , 執行翻譯的動作
  try
  {
   EditTextTo.setText(Translate.execute(EditTextFrom.getText().toString(), LanguageCode[positionFrom], LanguageCode[positionTo]));
   
   int intLocal = TToSpeech.isLanguageAvailable(LocaleCode[positionFrom]);
   
   if(intLocal == TextToSpeech.LANG_MISSING_DATA || intLocal == TextToSpeech.LANG_NOT_SUPPORTED)
   {
    Toast.makeText(this, "不支援這個語言或是資料遺失", Toast.LENGTH_LONG).show();            
   }
   else
   {
    TToSpeech.setLanguage(LocaleCode[positionFrom]);
    TToSpeech.speak(EditTextFrom.getText().toString(), TextToSpeech.QUEUE_ADD, null);
      //發音 , 如果現在TTS Engine 正在發音的話 , 參數 TextToSpeech.QUEUE_FLUSH 代表會將其發音內容中斷 , 並且開始發音
      //TextToSpeech.QUEUE_ADD 代表會等到現在的發音的內容結束才開始發音      
   }
   
  } catch (Exception e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 @Override
 public void onInit(int status)
 {
  // TODO Auto-generated method stub
  Log.d("onInit" , "onInit");
 }
 
 @Override  
  protected void onDestroy()
 {  
     // TODO Auto-generated method stub  
     super.onDestroy();  
     TToSpeech.shutdown();  //釋放 TTS Engine所使用的資源
  }  
}


不過當按下Button的時候 , 要隔一兩秒才會發音 , 另外官網API Referece 的 Locale Class , 所提供的地區參數蠻多的 , 另外 TextToSpeech.OnInitListener interface的介紹 , 但是敘述的不多





看來不支援日文發音 , 就brother這個字來說 , 使用英文 , 德文和法文都可以成功發音


沒有留言:

張貼留言

Google Analytics