音声認識機能の実装

音声認識機能の実装

まずは、追加ボタンをクリックした時に音声認識を起動するために
Intent を使って音声認識機能を呼び出す

まず、音声認識機能を呼び出すIntent のREQUEST_IDは
あらかじめ定数で定義しておく

こっちは、最初のアダプター定義のあたりに書く
private static final int REQUEST_SPEECH =1;

次に、実際の処理
ちなみに、書く場所は
case R.id.add:
listAdapter.add(“追加”);
の下

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
で音声認識 intent 作成

intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

で機能を拡張
それぞれの意味は
RecognizerIntent.EXTRA_LANGUAGE_MODEL

言語モデルを設定

RecognizerIntent.LANGUAGE_MODEL_FREE_FORM

自由に音声を入力したいので
EXTRA_LANGUAGE_MODEL
にしている

次に、/音声認識画面に表示する文字列を設定
今回はthis.getTitle()で呼び出し元Activity の表題にする

intent.putExtra(RecognizerIntent.EXTRA_PROMPT, this.getTitle());
.EXTRA_PROMPT,

音声認識画面に表示する文字列を設定する
ちなみに

Extra() は
文字列をキーとして
値や数値などを格納するリスト
ハッシュとか JSON みたいなイメージ
これを使うことで
intent の詳細設定を追加していくことができる

なので、intent を定義したら
putExtra() で機能追加と考えるとわかりやすい

ここまでできたら
音声認識のダイアログを表示する
例外がでるので
try catch で行う
失敗の可能性のあるものは
try catch と考えるといいかもしれない

あらかじめ、strings.xml で
toast で表示する文字列をつくっておく
これはソースに書くよりも後で変更などのメンテがしやすいため

			//音声認識 dialog 表示
			try{
				startActivityForResult(intent, REQUEST_SPEECH);
			}catch (ActivityNotFoundException e) {
				// TODO: handle exception
				//音声認識が使えなかったら toast で知らせる
				Toast.makeText(this	,getString(R.string.word_disable), Toast.LENGTH_SHORT).show();
				e.printStackTrace();
			}

ここまでできたら
音声入力が正しく終了できたときの処理をつくる

これには
別Activity の処理結果を取得する
onActivityResult() を使う

右クリック > source >
override / implement methods

これはActivity の項目にある
onActivityResult
を選ぶとソースが追記される

ここで
正常処理である場合のみ処理できるように判定する
判定は
if(requestCode == REQUEST_SPEECH && resultCode == RESULT_OK){
でできる

REQUEST_SPEECH

private static final int REQUEST_SPEECH =1;
で設定した定数

ArrayList results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
で結果リストを取得

.getStringArrayListExtra()
認識結果の配列を取得している

このあたりの流れは

http://wiki.livedoor.jp/moonlight_aska/d/%B2%BB%C0%BC%A4%C7%CA%B8%BB%FA%C6%FE%CE%CF%A4%B9%A4%EB
に載っていたのでこれを参考に

音声認識の結果は
data の Extra() に入っているのでこれを
定数の
RecognizerIntent.EXTRA_RESULTS
をキーにして取り出している

if(results.size() > 0){

で0以上、つまり認識結果があるなら
listAdapter.add(results.get(0));
でリストに追加する

ちなみに、
http://wiki.livedoor.jp/moonlight_aska/d/%B2%BB%C0%BC%A4%C7%CA%B8%BB%FA%C6%FE%CE%CF%A4%B9%A4%EB
では
EdutText へ追加するため

inpText.setText(input); 

で文字としてセットしている

private EditText inpText;
inpText = (EditText)findViewById(R.id.result_id);

となっているのが EditText の設定

これで音声入力はできるけど

//音声認識画面に表示する文字列
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, this.getTitle());

になっているから
音声入力を促す画面文字がアプリ名なので微妙だ

intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "音声を入力してください。");

というようにしたほうがすっきりする

Intent によるActivity 呼び出しと戻り値の取得

Intent によるActivity 呼び出しと戻り値の取得

アプリの音声入力を実装
Android の音声入力はIntent により呼び出し可能な独立したアプリとして実装されており
これを呼び出すことで音声を認識し
認識した結果を取得できる

Android Activity は
必要に応じて呼び出 し元Activity に戻り値を返却することができる

Intent により、他のActivity を呼び出し
その戻り値を取得するには
Activity のstartActivityForResult()を使う

とくに戻り値を要求しないなら
Activity の startActivity() のほうを使えばいい

startActivityForResult()は
intent
これはActivity を呼び出すためのIntent

requestCode
これは、リクエストID
という引数になっている

音声処理を始めるのは
追加ボタンを押したときなので
case R.id.add:
listAdapter.add(“追加”);
のところへ追加する

とりあえず、解説を先にメモ

アプリから別のActivity つまり画面を呼び出す
この処理は
同一のアプリでも、別のアプリでもやり方は一緒

構文は

Intent intent = new Intent();

try{
  startActivityForResult(intent , REQUEST_ID);
}
catch(ActivityNotFoundException e){
  //指定したActivity が存在しないときに起こる例外処理
e.prinstackTrace();
}

となる

REQUEST_ID は
Intent
呼び出しを識別するたのID

戻り値を取得するために使うので
あらかじめ定数としておくのが一般的

Intent が暗黙的Intent の場合
Intent が示すActivity を system が発見できないため
ActivityNorFoundException が発生する

呼び出し元Activity が確実に存在する場合
つまり同じアプリの中のActivity 呼び出しとかなら
いらないけど
そんな都合のいいことばかりじゃないので
ActvityNorFooundException が発生する前提でアプリを作成すること

次にActivity の戻り値の取得について
startActivityForResult() でActivity を呼び出した場合
呼び出した Activity が閉じると
呼び出し元、つまり今のActivity の
onActivityResult() が呼び出される

ソースにすると

@Override
public void onActivityResult(int requestCode, int resultCode, intent data){
if(requestCode == REQUEST_ID &&  resultCode == RESULT_OK){
.....
}
super.onActivityResult(requestCode,resultCode,data);
}

となる

この引数の意味は
requestCode
onActivityForResult() で指定した値が格納される

resultCode
Activity が閉じたときの終了コード
Activity クラスの定数である
RESULT_OK
RESULT_CANCEL
RESULT_FIRST_USER
のどれかが格納される
これらの意味は
RESULT_OK
処理が正常終了

RESULT_CANCEL
処理がキャンセルされた

RESULT_FIRST_USER
その他の動作

という意味になる

data
これは、Activity が設定した戻り値を示すIntent オブジェクトを格納

となる

このため

if(requestCode == REQUEST_ID &&  resultCode == RESULT_OK){


requestCode が目的のIDで
resultCode が RESULT_OK
のときだけ処理するという判定になる

ちなみに、自作した Activity の戻り値をかえすようにするには
Activity Object の setResult() を使う

構文は

public final void setResult(int resultCode Intent data);

となる

この時の引数の意味は
resultCode
Activity の処理結果
onActivityResult() のresultcode 対応

data
Activity の処理結果を示すIntent
onActivityResult のdata 対応

Android Beamの送信方法

Android Beamの送信方法

Android Beam でデータ送信するには

NfcAdapterクラスのメソッドを使う

setNdefPushMessage()を使うと
呼び出した時点でビーム送信になる

これは、Activity起動時とか
ボタンのクリックイベントなど特定のタイミングで送信する時に使う

ソースにすると
NfcAdapter.setNdefPushMessage(NdefMessage message, Activity activity, Activity activitys …)

もう一つの送信方法として
setNdefPushMessageCallback()
を使う
これは、端末同士を近づけて
ビームが送受信できる状態になったときにコールバックが受け取れるようにする

コールバックを受け取ると
返信データとなるNDEF Messageを作成する
createNdefMessage()
が自動的に呼ばれる

createNdefMessage()は
Overrideすることで送信に使う
NDEF Messageを作成できる

ソースにすると
NfcAdapter.setNdefPushMessageCallback(NdefAdapter.createNdefMessageCallback callback, Activity activity, Activity activitys …)

となる

NDEFフォーマットでない場合

NDEFフォーマットでない場合

この場合、
NdefFormatableクラスを使う
get()
connect()
close()
の使い方は
NDEFフォーマットのときと同じだけど
タグへの書き込み方が違う

NdefFormatableへ書き込むときには
format()を使って
NDEFへフォーマットしながら
NDEF Messageを書き込むことになる

タグの書き込み

タグの書き込み

NDEFフォーマットで書き込む場合、
はじめにNdefクラスのメソッドを使って
タグ情報から既存のNDEF情報をもったインスタンスを取得する

そして、取得したインスタンスへ
新たに作成したNDEF Messageを追加する形で書き込む

タグへ書き込むときには
connect()
で書き込み操作開始

writeNdefMessage()でタグへ書き込む

終わったら、close()で書き込み終了

このあたりは、他の言語の
ファイルオープン
書き込み
ファイルを閉じる
という流れと変わらない

ソースにすると
//Ndefが含まれている場合なら
Ndef ndef = Ndef.get(tag);

try{
//Ndefデータの上にNDEF Messageを書き込む
ndef.connect();
ndef.writeNdefMessage(tag);
}catch(IOException e){
throw new RuntimeException(getString(R.string.err_connect,e));
}catch(FormatException e){
throw new RuntimeException((R.string.err_format,e());
}finally{
try{
ndef.close();
}catch(IOException e){
}
}

tryには行う処理
catchには例外発生の処理
finallyには絶対行う処理を書く

構文については
http://www.javaroad.jp/java_exception2.htm
を参考に

タグの書き込み判定処理

タグの書き込み判定処理

タグを書き込む前に取得したタグ情報に
NDEFフォーマットが含まれているか確認する

これは、書き込み対象のタグのフォーマットにより書き込み方法が変わるから

書き込み対象から取得したタグ情報に対して
getTechList()を使うと利用可能なNFCの種類がクラス名として取得できる

この中に
Ndef.class.getName()で取得できるクラス名が含まれているなら
NDEFフォーマットになり

NdefFormatable.class.getName()で取得できるクラス名が含まれているなら
NDEFフォーマットが可能なNDEFFormatableと判定できる

これをソースにすると

try{
List techList = Arrays.asList(tag.getTechList());

Array.asList()
については
http://shot606.com/?p=1094
を参考
意味は、配列をリストへ変換する

つまり、tag.getTechList()
で取得した配列をリストに変換して
techList へ格納している

次に書き込みを行うタグへNDEFデータが格納されていているか確認

if(techList.contains(Ndef.class.getName()))

contains()については
http://karetta.jp/book-node/java/230466
を参考にする
意味は、指定した要素が存在するならtrue
今回なら
Ndef.class.getName()で値が取得できたならtrueになる

これで、trueならNDEFが含まれているときの処理を書く

そして、falseだったとき、つまりNDEFでないなら
else if (techList.contains(NdefFormatable.class.getName())){
で判定し、trueなら
NdefFormatableが含まれているときの処理を書く

あとは、catchで例外処理

}catch(RuntimeException e){
Toast.makeText(this,getString(R.string.write_failure),Toast.LENGTH_SHORT).show();
}
これで、例外発生したらToastで表示する

初級ステージ編

初級ステージ編

日経Linux 2013-12にサーバー構築が掲載されている

初級ステージ編では、Ubuntu 13.04 Desktopを使っている

これは、超入門ステージ編で使った物をサーバー構築に使っている

これを改造していくけど
さすがにやり直しになる不安とかありそうなので
仮想環境を作って練習すると効率的にできるし
やりたくない心理も減らせる
実際、私の場合も仮想環境作ってから
サーバー構築の練習したおかげでスキルアップできた

仮想環境を作るには
KVM
vmware player
virtualbox
その他いろいろあるけど
オススメはvirtualbox

これは、ドットインストールの講座で見ることができるし
vmware playerみたいに英語のサイトでアカウント登録しなくてもよいから挫折率低め

virtualboxの講座は、旧版だけど
http://dotinstall.com/lessons/basic_local_development
にある

新版もあるけど
こっちは、Vagrantもつかうため
難易度があがってしまう

途中でいくつかネット公開状態が前提のものもあり、なれないと挫折するかもしれないけど

ローカルで使うなら
30 の VPNサーバー構築
31 プロキシサーバー構築
は省いてしまうのもあり

あと、電子工作が苦手なら
39 のRaspberry Piを使うとかは難しいし
極力お金はかけたくないのなら
40 のAWS は行わなくてもok

AWSは使った分だけ課金になる
クラウドサービス
ちなみに、支払いはドルなので、円安だと厳しいかも

超入門ステージ編

超入門ステージ編

日経Linux 2013-12にサーバー構築が掲載されている

超入門ステージ編では、Ubuntu 13.04 Desktopを使っている

これをサーバー構築に使っている

すでにLinuxユーザーなら基本となっているのがほとんど

サーバー構築が初めてなら
10, 11のルーター設定と、
Ubuntu設定による固定IP設定は見たほうがわかりやすい

13 でドメイン取得載っている
今回使っているのは
お名前.com
ちなみに、年間でお金がかかる

料金については
http://www.onamae.com/sp/price.html
を参考に

ローマ字とか日本語とかこだわらないのなら
年間 500円もかからない

実は、公開するサーバー構築でないなら
これはやらなくてもできる
例えば、家の中でしか使わないのなら
わざわざドメイン取得でお金かけなくてもできる

超入門ステージ編だけど
いきなり公開前提なのは微妙かも
なので、外部公開しないのなら
13 14 15 16 は行わなくてもサーバー構築はできる

個人的には、初期段階で公開はリスクがあると思うし

とりあえず、なれないうちは
ここはとばして
17 のファイアウォール設定へとんだほうがわかりやすい

ここからは端末を使うのがメインになる

ctrl + Alt + t
で端末起動するので
これで起動すると楽

端末操作ではショートカットキーがあり
http://keyamb.hatenablog.com/entry/20100520/1274364225
に掲載されているので、これを参考にする

なれないうちは、テキスト編集へ
geditを使うけど
個人的には、サーバー操作するなら
vim とか Emacs 覚えておくと
クラウドとか、レンタルサーバー使うときに役立つ

これらについては
ドットインストールの講座がわかりやすい
vimは
http://dotinstall.com/lessons/basic_vim

Emacsはつかったことないので保留です

12月11日からソースみるにはお金月880円かかるけど
参考書買うより安い
動画みるだけなら無料なので
Googleでの検索と合わせるならお財布にも優しい

初心者が引っかかるとするなら
20 のインターネットからコンテンツ参照のところの
コンテンツの配置場所
これは、ドキュメントルートという場所におくけど
これは、
DocumentRoot
で設定したフォルダーになる

あと、インターネットとは書いてあるけど
サーバーのIP調べて
http://サーバーIP/contents/
でアクセスしても同じ結果になる

マメ知識として
サブネットマスクとかゲートウエイについて書かれているので
これで足りないなら
各用語をネット検索すると効率的

もし、わからないのなら
Yahoo!知恵袋とかで質問するのもあり

Androidアプリ開発での空文字チェック

Androidアプリ開発での空文字チェック

文字列の空文字チェックは
文字数をカウントして0より多いという条件に加え、nullでないかという判定処理も付けると長くなる

こんなときに便利なのが
AndroidのTextUtilクラス

この中のTextUtilsEmpty()を使うことで
文字チェックとnullチェックを同時にできるので
コードがすっきりする

NDEF Messageは、NDEF Recordの集合体

NDEF Messageは、NDEF Recordの集合体

このため、NDEF Messageを作成するには
最低でも1つ以上のNDEF Recordを作成することになる

これは、どのコンストラクタを作るときも同じ

NdefMessage(byte[] data)
この
バイト配列を渡すコンストラクタは
NDEF RecordをDBへ保存、復元するときのように
NdefRecordのままだと使いにくいような特殊な状況下で使うときに利用する

NdefMessage(NdefRecord[] records)
このNdefRecordを配列で渡すコンストラクタは
配列化したNdefRecordクラスのインスタンスを渡す
配列として定義しないとダメだけど
NdefRecordをそのまま使えるので
ベーシックなコンストラクタとして使われる

NdefMessage(NdefRecord record , NdefRecord … record)
このコンストラクタは、配列を使わず
NdefRecordクラスを、単一、もしくは複数で渡すことができる
パラメーターに直接NdefRecordをセットできるため
直感的でわかりやすいのがメリット
ただし、使えるのがAndroid API level 16
つまり Android 4.1 からでないと使えない