네이버 오픈 API Clova
안녕하세요
오늘은
네이버 오픈 API Clova 에 대해
학습해 보겠습니다.
API를 잘만 활용한다면 보다
질 좋은 앱을 만들 수 있습니다.
그러나 아무리 좋은 API 라도 적용하지 못하면
그림에 떡이나 마찬가지겠지요ㅠㅠ
자 차분히 하나하나 진행해
보도록 하겠습니다.
https://developers.naver.com/main/ 에
접속하시면
네이버에서 제공하는 오픈 API 를
보실 수 있을 것입니다.
그림과 같이 체크 된 아이콘을
클릭하고 접속된 페이지에서
"Clova.al 바로가기" 를 클릭해 줍니다.
아래와 같이 Clova 홈페이지에
접속하실 수 있을 것입니다.
네이버의 자체 API가 아닌
Clova라는 회사와 제휴를
맺은 것으로 판단됩니다.
"손안에 비서" 라는 타이틀로
API를 설명하고 있네요
타이틀만 봐도 API가 어떤 기능을
하는지 보이는 것 같네요
본론으로 들어가서 아래 그림과 같이 상단의
플랫폼 > Clova A.I APIs 를 클릭해 줍니다
그러면 3개의 API를 신청 및 설명을
해주는 페이지로 이동하게 됩니다.
제가 오늘 해볼건
클로바 음성 인식 기술(CSR) 이니
CSR API 사용 신청을 해 보도록 하겠습니다.
아래 그림과 같이 클로바 음성 인식 기술의
API 사용 신청을 클릭해 줍니다.
그럼 API 이용약관 페이지로
이동하게 되니다.
이용약관에 동의합니다를 체크해 주시고
확인을 눌러줍니다.
그러면 아래와 같은
계정설정 페이지로 이동합니다.
휴대폰인증 후
회사 이름을 입력해줍니다.
간단한 절차를 진행 후 본인의 패키지 명을
입력하시면 됩니다.
패키지 명은
AndroidManifest.xml 의
아래의 부분을 참조하시면 됩니다.
그러면 API ID와 PW를 얻으실 수 있습니다.
여기서 ID와 PW를 발급받을때
패키지명으로 명시된
프로젝트여야지만 제대로
작동 된다는 부분 입니다.
(저는 블로그 작성 전
계정을 미리 등록했기 때문에 이부분 캡처는
생략하겠습니다.
아직 초보블로거라
캡처를 자꾸 까먹네요 ㅠㅠㅠ)
그럼 이제 계정발급은 끝이 났습니다.
절반의 성공이라 보시면 되겠네요
다음으로 소스에 적용해 보도록 하겠습니다.
아래 그림에서 개발 가이드 보기를
클릭해 줍니다.
이동 된 페이지에서 아래로 쭉
내리다 보면
"Android API 사용하기"
가 보이실 거에요
이 부분을 따라 그대로 제작해 보겠습니다.
안드로이드스튜디오에서
Gradle Scripts>build.gradle (Module: app) 을
클릭해 줍니다.
개발 가이드에서 설명한대로
문구를 추가해 보도록 하겠습니다.
다음으로 AndroidManifest.xml 에
권한설정을 부여해 줍니다.
개발 가이드에서는 총 4개의 권한을
부여해 주어야 한다고 설명하네요
그대로 권한설정을 해 보도록 하겠습니다.
이제 소스작업을 시작하겠습니다.
저는 사전준비할때는 별 흥미를 못갖지만
소스작업을 시작하면 뭔가
설렘이 있더라구요 .... ㅎㅎㅎ
NaverRecognizer 라는 클래스를
생성해 줍니다.
그리고 SpeechRecognitionListener 를
implements 해 주시면
총 9개의 메소드가
자동으로 오버라이드 됩니다.
위의 사진은 캡처 한계상
6개밖에 보이지 않으나
실질적으로는 9개의 메소드가
생성되어 있습니다.
그 후 다음과 같이
NaverRecognizer 생성자를 생성합니다.
Context, Handler, String 값을 매개변수로
가지고 있는 생성자 입니다.
매개변수 안에 다음과 같이
소스를 작성하여 넣습니다.
그리고 전역변수에 받아온
매개변수의 값을 담을
mHandler 와 mRecognizer을 선언해 줍니다.
이후 다음과 같게 소스를 작성해 줍니다.
public class NaverRecognizer implements SpeechRecognitionListener {
private final static String TAG = NaverRecognizer.class.getSimpleName();
private Handler mHandler;
private SpeechRecognizer mRecognizer;
public NaverRecognizer(Context context, Handler handler, String clientId) {
this.mHandler = handler;
try {
mRecognizer = new SpeechRecognizer(context, clientId);
} catch (SpeechRecognitionException e) {
e.printStackTrace();
}
mRecognizer.setSpeechRecognitionListener(this);
}
public SpeechRecognizer getSpeechRecognizer() {
return mRecognizer;
}
public void recognize() {
try {
mRecognizer.recognize(new SpeechConfig(SpeechConfig.LanguageType.KOREAN, SpeechConfig.EndPointDetectType.AUTO));
} catch (SpeechRecognitionException e) {
e.printStackTrace();
}
}
@Override
public void onInactive() {
Message msg = Message.obtain(mHandler, R.id.clientInactive);
msg.sendToTarget();
}
@Override
public void onReady() {
Message msg = Message.obtain(mHandler, R.id.clientReady);
msg.sendToTarget();
}
@Override
public void onRecord(short[] speech) {
Message msg = Message.obtain(mHandler, R.id.audioRecording, speech);
msg.sendToTarget();
}
@Override
public void onPartialResult(String result) {
Message msg = Message.obtain(mHandler, R.id.partialResult, result);
msg.sendToTarget();
}
@Override
public void onEndPointDetected() {
Log.d(TAG, "Event occurred : EndPointDetected");
}
@Override
public void onResult(SpeechRecognitionResult result) {
Message msg = Message.obtain(mHandler, R.id.finalResult, result);
msg.sendToTarget();
}
@Override
public void onError(int errorCode) {
Message msg = Message.obtain(mHandler, R.id.recognitionError, errorCode);
msg.sendToTarget();
}
@Override
public void onEndPointDetectTypeSelected(SpeechConfig.EndPointDetectType epdType) {
Message msg = Message.obtain(mHandler, R.id.endPointDetectTypeSelected, epdType);
msg.sendToTarget();
}
}
다음은 전체 소스 입니다.
public class NaverActivity extends Activity {
private static final String TAG = NaverActivity.class.getSimpleName();
private static final String CLIENT_ID = "ichkBdibFyJu9a7eyODE"; // "내 애플리케이션"에서 Client ID를 확인해서 이곳에 적어주세요.
private NaverActivity.RecognitionHandler handler;
private NaverRecognizer naverRecognizer;
private TextView txtResult;
private Button btnStart;
private String mResult;
private AudioWriterPCM writer;
private EditText et;
private Button bt2;
// Handle speech recognition Messages.
private void handleMessage(Message msg) {
switch (msg.what) {
case R.id.clientReady: // 음성인식 준비 가능
txtResult.setText("Connected");
writer = new AudioWriterPCM(Environment.getExternalStorageDirectory().getAbsolutePath() + "/NaverSpeechTest");
writer.open("Test");
break;
case R.id.audioRecording:
writer.write((short[]) msg.obj);
break;
case R.id.partialResult:
mResult = (String) (msg.obj);
txtResult.setText(mResult);
break;
case R.id.finalResult: // 최종 인식 결과
SpeechRecognitionResult speechRecognitionResult = (SpeechRecognitionResult) msg.obj;
List<String> results = speechRecognitionResult.getResults();
StringBuilder strBuf = new StringBuilder();
for (String result : results) {
strBuf.append(result);
strBuf.append("\n");
}
mResult = strBuf.toString();
txtResult.setText(mResult);
break;
case R.id.recognitionError:
if (writer != null) {
writer.close();
}
mResult = "Error code : " + msg.obj.toString();
txtResult.setText(mResult);
btnStart.setText(R.string.str_start);
btnStart.setEnabled(true);
break;
case R.id.clientInactive:
if (writer != null) {
writer.close();
}
btnStart.setText(R.string.str_start);
btnStart.setEnabled(true);
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_naver);
txtResult = (TextView) findViewById(R.id.txt_result);
btnStart = (Button) findViewById(R.id.btn_start);
et = (EditText) findViewById(R.id.et);
bt2 = (Button) findViewById(R.id.bt2);
handler = new NaverActivity.RecognitionHandler(this);
naverRecognizer = new NaverRecognizer(this, handler, CLIENT_ID);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!naverRecognizer.getSpeechRecognizer().isRunning()) {
mResult = "";
txtResult.setText("Connecting...");
btnStart.setText(R.string.str_stop);
naverRecognizer.recognize();
} else {
Log.d(TAG, "stop and wait Final Result");
btnStart.setEnabled(false);
naverRecognizer.getSpeechRecognizer().stop();
}
}
});
findViewById(R.id.google_icon).setOnClickListener(buttonClickListener);
findViewById(R.id.naver_icon).setOnClickListener(buttonClickListener);
findViewById(R.id.kakao_icon).setOnClickListener(buttonClickListener);
findViewById(R.id.bt).setOnClickListener(buttonClickListener);
findViewById(R.id.bt2).setOnClickListener(buttonClickListener);
}
@Override
protected void onStart() {
super.onStart(); // 음성인식 서버 초기화는 여기서
naverRecognizer.getSpeechRecognizer().initialize();
}
@Override
protected void onResume() {
super.onResume();
mResult = "";
txtResult.setText("");
btnStart.setText(R.string.str_start);
btnStart.setEnabled(true);
}
@Override
protected void onStop() {
super.onStop(); // 음성인식 서버 종료
naverRecognizer.getSpeechRecognizer().release();
}
// Declare handler for handling SpeechRecognizer thread's Messages.
static class RecognitionHandler extends Handler {
private final WeakReference<NaverActivity> mActivity;
RecognitionHandler(NaverActivity activity) {
mActivity = new WeakReference<NaverActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
NaverActivity activity = mActivity.get();
if (activity != null) {
activity.handleMessage(msg);
}
}
}
/**
* 버튼이벤트를 관여합니다.
*/
private Button.OnClickListener buttonClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt:
String serviceType = SpeechRecognizerClient.SERVICE_TYPE_WEB;
Intent i = new Intent(getApplicationContext(), VoiceRecoActivity.class);
if (serviceType.equals(SpeechRecognizerClient.SERVICE_TYPE_WORD)) {
String wordList = "테스트 중입니다.";
i.putExtra(SpeechRecognizerActivity.EXTRA_KEY_USER_DICTIONARY, wordList);
}
i.putExtra(SpeechRecognizerActivity.EXTRA_KEY_SERVICE_TYPE, serviceType);
startActivityForResult(i, 0);
break;
case R.id.google_icon:
Intent intent = new Intent(NaverActivity.this, MainActivity.class);
startActivity(intent);
finish();
break;
case R.id.naver_icon:
Intent intent2 = new Intent(NaverActivity.this, NaverActivity.class);
startActivity(intent2);
finish();
break;
case R.id.bt2:
APIExamTTS();
break;
default:
break;
}
}
};
public void APIExamTTS() {
try {
//쓰레드완료 후 실행 함수
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
}
}; // end try {
Runnable task = new Runnable() {
public void run() {
String clientId = "ichkBdibFyJu9a7eyODE";//애플리케이션 클라이언트 아이디값";
String clientSecret = "Gr8yql4Bcg";//애플리케이션 클라이언트 시크릿값";
try {
String text = URLEncoder.encode("만나서 반갑습니다.", "UTF-8"); // 13자
String apiURL = "https://openapi.naver.com/v1/voice/tts.bin";
URL url = new URL(apiURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("X-Naver-Client-Id", clientId);
con.setRequestProperty("X-Naver-Client-Secret", clientSecret);
String postParams = "speaker=mijin&speed=0&text=" + text;
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(postParams);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
BufferedReader br;
if (responseCode == 200) { // 정상 호출
InputStream is = con.getInputStream();
int read = 0;
byte[] bytes = new byte[1024];
// 랜덤한 이름으로 mp3 파일 생성
String tempname = Long.valueOf(new Date().getTime()).toString();
// path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File f = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS)+"/", tempname + ".mp3");
f.createNewFile();
OutputStream outputStream = new FileOutputStream(f);
while ((read = is.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
is.close();
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
System.out.println(response.toString());
}
Message msg = handler.obtainMessage();
handler.sendMessage(msg); //핸들러 호출 방법
} catch (Exception e) {
Log.e(getClass().getName(),"ERROR : "+e);
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
e.printStackTrace();
} // end try {
} // end public void run() {
}; // end Runnable task = new Runnable() {
//쓰레드 시작
Thread thread = new Thread(task);
thread.start();
} catch (Exception e) {
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
e.printStackTrace();
} // end try {
}
}